Upgrade to Pro — share decks privately, control downloads, hide ads and more …

低レイヤーグラフィックAPI Vulkanを始めよう

Fadis
July 22, 2017

低レイヤーグラフィックAPI Vulkanを始めよう

次世代グラフィックAPI Vulkanがどんなヤツであるかを、実際のコードを交えて解説します。
これは2017年7月22日に行われた 第13回 カーネル/VM探検隊 の発表資料です。

Fadis

July 22, 2017
Tweet

More Decks by Fadis

Other Decks in Programming

Transcript

  1. glPixelStorei(GL_UNPACK_ALIGNMENT,1); glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,tw,th, 0,GL_RGB,GL_UNSIGNED_BYTE,texture); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); … glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glLightfv(GL_LIGHT0,GL_DIFFUSE,diffuse_color); glLightfv(GL_LIGHT0,GL_SPECULAR,specular_color);

    glLightfv(GL_LIGHT0,GL_AMBIENT,ambient_color); … glMaterialfv(GL_FRONT,GL_AMBIENT_AND_DIFFUSE,material_color); glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); glFrontFace(GL_CCW); glCullFace(GL_BACK); glClearColor(0.0,0.0,0.0,0.0); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glEnable(GL_TEXTURE_2D); glDrawArrays(GL_TRIANGLES,0,vertex_count); ౰࣌ͷ ςΫενϟͷಡΈํΛࢦఆ ϥΠτΛ༗ޮʹ͢Δ ϥΠτͷ৭Λࢦఆ ਂ౓ςετΛ༗ޮʹ͢Δ എ໘ΧϦϯάΛ༗ޮʹ͢Δ ϑϨʔϜόοϑΝΛফڈʹͯ͠ %SBXίʔϧ
  2. ϢχϑΝΠυγΣʔμΞʔΩςΫνϟ ϓϩηοα ϓϩηοα ϓϩηοα ϓϩηοα ϓϩηοα ϓϩηοα ʜ ൚༻తͳܭࢉ͕Ͱ͖ΔϓϩηοαΛ େྔʹฒ΂ͨΞʔΩςΫνϟ

    άϥϑΟοΫύΠϓϥΠϯ͸ ͜ͷ্Ͱಈ͘ιϑτ΢ΣΞͱ࣮ͯ͠૷͞ΕΔ ϓϩηοα ϓϩηοα ϓϩηοα ϓϩηοα ϓϩηοα ϓϩηοα ϓϩηοα ϓϩηοα ϓϩηοα ϓϩηοα ϓϩηοα ϓϩηοα
  3. ςΫενϟʹඳ͘ ઃఆΛม͑Δ ςΫενϟʹඳ͘ ઃఆΛม͑Δ ςΫενϟʹඳ͘ ઃఆΛม͑Δ ςΫενϟʹඳ͘ ઃఆΛม͑Δ ઃఆΛม͑Δ ը໘ʹඳ͘

    υϥΠό͸ίϚϯυΛه࿥ͯ͠ (16Ͱ࣮ߦ͢Δίʔυͷੜ੒Λ஗Ԇͤ͞Δ υϥΠό͸ը໘ʹԿ͔͕ ൓ө͞Εͳ͚Ε͹ ͳΒͳ͘ͳͬͨ࣌఺Ͱ ͦ͜·ͰͷॲཧΛશͯ·ͱΊͨ ίʔυΛੜ੒ υϥΠό͸ σʔλͷґଘؔ܎Λௐ΂ ಉ࣌ʹ࣮ߦͰ͖Δ෺͸ ಉ࣌ʹ࣮ߦ͢Δ
  4. ϑϨʔϜ໨ ςΫενϟʹඳ͘ ઃఆΛม͑Δ ςΫενϟʹඳ͘ ઃఆΛม͑Δ ςΫενϟʹඳ͘ ઃఆΛม͑Δ ςΫενϟʹඳ͘ ઃఆΛม͑Δ ઃఆΛม͑Δ

    ը໘ʹඳ͘ ςΫενϟʹඳ͘ ઃఆΛม͑Δ ςΫενϟʹඳ͘ ઃఆΛม͑Δ ςΫενϟʹඳ͘ ઃఆΛม͑Δ ςΫενϟʹඳ͘ ઃఆΛม͑Δ ઃఆΛม͑Δ ը໘ʹඳ͘ ϑϨʔϜ໨ υϥΠό͸ ίϚϯυྻΛൺֱͯ͠ Ұ౓ੜ੒ͨ͠όΠφϦ͕ ࠶ར༻Մೳ͔Λ൑அ͢Δ
  5. σεΫϦϓληοτ ύΠϓϥΠϯ Ϩϯμʔύε ͭͷॏཁͳΦϒδΣΫτ ͲͷΑ͏ͳσʔλΛ࢖ͬͯ ඳըΛߦ͏͔Λ ఆٛͨ͠΋ͷ ͲͷΑ͏ͳॱংͰ ඳըΛߦ͏͔Λ ఆٛͨ͠΋ͷ

    ͲͷΑ͏ͳํ๏Ͱ ඳըΛߦ͏͔Λ ఆٛͨ͠΋ͷ ͭͷΦϒδΣΫτ͕ଗͬͨ࣌ ༐ऀ͕௖఺όοϑΝΛ౤͛Δͱ(16͕ಈ͖ͩ͢
  6. const auto avail_ext=vk::enumerateInstanceExtensionProperties(); for(const char *w:ext) if(std::find_if(avail_ext.begin(),avail_ext.end(), [&](const auto &v){return

    !strcmp(v.extensionName,w);} )==avail_ext.end()) throw ExtensionNotAvailable(); const auto avail_layers=vk::enumerateInstanceLayerProperties(); for(const char *w:layers) if(std::find_if(avail_layers.begin(),avail_layers.end(), [&](const auto &v){return !strcmp(v.layerName,w);} )==avail_layers.end())throw LayerNotAvailable(); const auto app_info = vk::ApplicationInfo( app_name.c_str(),VK_MAKE_VERSION(1,0,0),”HogeEngine", VK_MAKE_VERSION(1,0,0),VK_API_VERSION_1_0 ); instance=vk::createInstance( vk::InstanceCreateInfo() .setPApplicationInfo(&app_info) .setEnabledExtensionCount(ext.size()) .setPpEnabledExtensionNames(ext.data()) .setEnabledLayerCount(layers.size()) .setPpEnabledLayerNames(layers.data()) ); ͷΠϯελϯεΛ࡞Δ ΞϓϦέʔγϣϯ͕ඞཁͱ͍ͯ͠Δ ֦ுͱϨΠϠʔΛ γεςϜͷϥϯλΠϜ͕ αϙʔτ͍ͯ͠Δ͔Λௐ΂Δ
  7. const auto avail_ext=vk::enumerateInstanceExtensionProperties(); for(const char *w:ext) if(std::find_if(avail_ext.begin(),avail_ext.end(), [&](const auto &v){return

    !strcmp(v.extensionName,w);} )==avail_ext.end()) throw ExtensionNotAvailable(); const auto avail_layers=vk::enumerateInstanceLayerProperties(); for(const char *w:layers) if(std::find_if(avail_layers.begin(),avail_layers.end(), [&](const auto &v){return !strcmp(v.layerName,w);} )==avail_layers.end())throw LayerNotAvailable(); const auto app_info = vk::ApplicationInfo( app_name.c_str(),VK_MAKE_VERSION(1,0,0),”HogeEngine", VK_MAKE_VERSION(1,0,0),VK_API_VERSION_1_0 ); instance=vk::createInstance( vk::InstanceCreateInfo() .setPApplicationInfo(&app_info) .setEnabledExtensionCount(ext.size()) .setPpEnabledExtensionNames(ext.data()) .setEnabledLayerCount(layers.size()) .setPpEnabledLayerNames(layers.data()) ); ͷΠϯελϯεΛ࡞Δ createInstanceͰ ΠϯελϯεΛ࡞Δ ͜ͷ࣌ɺ࢖͍͍֦ͨுͱϨΠϠʔΛࢦఆ͢Δ
  8. auto devices=instance.enumeratePhysicalDevices(); if(devices.empty())throw DeviceNotAvailable(); const auto physical_device=std::find_if( devices.begin(),devices.end(),[&](const auto &d)->bool{

    const auto prop=d.getProperties(); // (தུ) σόΠεͷ৘ใΛݟͯ࢖͍ͨ͘ͳ͍σόΠεΛআ֎͢Δ return true; } ); if(physical_device==devices.end())throw DeviceNotAvailable(); ࢖͏෺ཧσόΠεΛબͿ σόΠεͷछྨ΍ݶք஋ αϙʔτ͢Δ֦ு౳Λௐ΂ͯ࢖͏(16ΛબͿ Ͱ͸ͭͷΞϓϦέʔγϣϯ͕ ෳ਺ͷ(16Λಈ͔ͯ͠΋ྑ͍ ͨͩ͠(16ʹಛผͳ࢓૊Έ͕ͳ͍ݶΓ (16ؒͷσʔλͷసૹ͸$16Λհ͢ࣄʹͳΔ
  9. int scr; xcb.reset( xcb_connect(nullptr,&scr),[](auto p){if(p)xcb_disconnect(p);} ); if(xcb_connection_has_error(xcb.get())>0) throw XServerUnreachable(); xcb_screen_t

    *xcb_screen=nullptr; const xcb_setup_t * const xcb_setup=xcb_get_setup(xcb.get()); xcb_screen_iterator_t xcb_screen_iter= xcb_setup_roots_iterator(xcb_setup); while(scr-->0)xcb_screen_next(&xcb_screen_iter); xcb_screen=xcb_screen_iter.data; xcb_window=xcb_generate_id(xcb_connection.get()); const uint32_t value_mask=XCB_CW_BACK_PIXEL|XCB_CW_EVENT_MASK; const std::array<uint32_t,32u> value_list{{ xcb_screen->black_pixel,XCB_EVENT_MASK_KEY_RELEASE| XCB_EVENT_MASK_EXPOSURE|XCB_EVENT_MASK_STRUCTURE_NOTIFY, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }}; xcb_create_window( xcb.get(),XCB_COPY_FROM_PARENT,xcb_window,xcb_screen->root, 0,0,width,height,0,XCB_WINDOW_CLASS_INPUT_OUTPUT, xcb_screen->root_visual,value_mask,value_list.data() ΢Οϯυ΢γεςϜ͔ΒαʔϑΣεΛ΋Β͏ 9αʔόʹ઀ଓ͢Δ
  10. xcb_screen_iterator_t xcb_screen_iter= xcb_setup_roots_iterator(xcb_setup); while(scr-->0)xcb_screen_next(&xcb_screen_iter); xcb_screen=xcb_screen_iter.data; xcb_window=xcb_generate_id(xcb_connection.get()); const uint32_t value_mask=XCB_CW_BACK_PIXEL|XCB_CW_EVENT_MASK; const

    std::array<uint32_t,32u> value_list{{ xcb_screen->black_pixel,XCB_EVENT_MASK_KEY_RELEASE| XCB_EVENT_MASK_EXPOSURE|XCB_EVENT_MASK_STRUCTURE_NOTIFY, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }}; xcb_create_window( xcb.get(),XCB_COPY_FROM_PARENT,xcb_window,xcb_screen->root, 0,0,width,height,0,XCB_WINDOW_CLASS_INPUT_OUTPUT, xcb_screen->root_visual,value_mask,value_list.data() ); xcb_intern_atom_cookie_t xcb_cookie= xcb_intern_atom(xcb.get(),1,12,"WM_PROTOCOLS"); std::unique_ptr<xcb_intern_atom_reply_t> reply( xcb_intern_atom_reply(xcb.get(),xcb_cookie,0) ); xcb_intern_atom_cookie_t cookie2= xcb_intern_atom(xcb.get(),0,16,"WM_DELETE_WINDOW"); atom_wm_delete_window= ΢Οϯυ΢γεςϜ͔ΒαʔϑΣεΛ΋Β͏ ΢Οϯυ΢Λ࡞Δ
  11. xcb_screen->root_visual,value_mask,value_list.data() ); xcb_intern_atom_cookie_t xcb_cookie= xcb_intern_atom(xcb.get(),1,12,"WM_PROTOCOLS"); std::unique_ptr<xcb_intern_atom_reply_t> reply( xcb_intern_atom_reply(xcb.get(),xcb_cookie,0) ); xcb_intern_atom_cookie_t

    cookie2= xcb_intern_atom(xcb.get(),0,16,"WM_DELETE_WINDOW"); atom_wm_delete_window= xcb_intern_atom_reply(xcb.get(),cookie2,0); xcb_change_property( xcb.get(),XCB_PROP_MODE_REPLACE,xcb_window,(*reply).atom, 4,32,1,&(*atom_wm_delete_window).atom ); xcb_map_window(xcb.get(),xcb_window); const uint32_t coords[]={0,0}; xcb_configure_window( xcb.get(),xcb_window, XCB_CONFIG_WINDOW_X|XCB_CONFIG_WINDOW_Y,coords ); xcb_flush(xcb.get()); surface = instance.createXcbSurfaceKHR( vk::XcbSurfaceCreateInfoKHR() .setConnection(xcb.get()) ΢Οϯυ΢γεςϜ͔ΒαʔϑΣεΛ΋Β͏ ͦͷଞࡉ͔͍ઃఆΛͯ͠qVTI
  12. xcb_intern_atom(xcb.get(),0,16,"WM_DELETE_WINDOW"); atom_wm_delete_window= xcb_intern_atom_reply(xcb.get(),cookie2,0); xcb_change_property( xcb.get(),XCB_PROP_MODE_REPLACE,xcb_window,(*reply).atom, 4,32,1,&(*atom_wm_delete_window).atom ); xcb_map_window(xcb.get(),xcb_window); const uint32_t

    coords[]={0,0}; xcb_configure_window( xcb.get(),xcb_window, XCB_CONFIG_WINDOW_X|XCB_CONFIG_WINDOW_Y,coords ); xcb_flush(xcb.get()); surface = instance.createXcbSurfaceKHR( vk::XcbSurfaceCreateInfoKHR() .setConnection(xcb.get()) .setWindow(xcb_window) ); ΢Οϯυ΢γεςϜ͔ΒαʔϑΣεΛ΋Β͏ xcb_window͔Β ͷαʔϑΣεΛ࡞Δ
  13. uint32_t graphics_queue_index = 0u; uint32_t present_queue_index = 0u; const auto

    queue_props= physical_device->getQueueFamilyProperties(); std::vector< VkBool32 > supportsPresent(queue_props.size()); for(uint32_t i=0;i<queue_props.size();++i) physical_device->getSurfaceSupportKHR( i,surface, &supportsPresent[i] ); graphics_queue_index=std::distance( queue_props.begin(), std::find_if( queue_props.begin(),queue_props.end(),[](const auto &v){ return bool(v.queueFlags& vk::QueueFlagBits::eGraphics); } ) ); present_queue_index=( graphics_queue_index!=queue_props.size()&& supportsPresent[ graphics_queue_index ]==VK_TRUE )? graphics_queue_index: ඳըʹ࢖͑ͦ͏ͳΩϡʔΛબͿ ඳը໋ྩΛ౤͛ΒΕΔΩϡʔΛ୳͢
  14. queue_props.begin(),queue_props.end(),[](const auto &v){ return bool(v.queueFlags& vk::QueueFlagBits::eGraphics); } ) ); present_queue_index=(

    graphics_queue_index!=queue_props.size()&& supportsPresent[ graphics_queue_index ]==VK_TRUE )? graphics_queue_index: std::distance( supportsPresent.begin(), std::find( supportsPresent.begin(),supportsPresent.end(),VK_TRUE ) ); if( graphics_queue_index==queue_props.size()|| present_queue_index==queue_props.size() ) throw UnableToCreateSwapChain(); ඳըʹ࢖͑ͦ͏ͳΩϡʔΛબͿ ϨϯμϦϯά݁ՌͷදࣔཁٻΛ ౤͛ΒΕΔΩϡʔΛ୳͢
  15. const float priority=0.0f; const auto features=physical_device->getFeatures(); std::vector<vk::DeviceQueueCreateInfo> queues{ vk::DeviceQueueCreateInfo() .setQueueFamilyIndex(graphics_queue_index)

    .setQueueCount(1) .setPQueuePriorities(&priority) }; if(graphics_queue_index!=present_queue_index) queues.emplace_back( vk::DeviceQueueCreateInfo() .setQueueFamilyIndex(present_queue_index) .setQueueCount(1) .setPQueuePriorities(&priority) ); device=physical_device->createDevice( vk::DeviceCreateInfo() .setQueueCreateInfoCount(queues.size()) .setPQueueCreateInfos(queues.data()) .setEnabledLayerCount(dlayers.size()) .setPpEnabledLayerNames(dlayers.data()) .setEnabledExtensionCount(dext.size()) ඞཁͳΩϡʔʹؔ͢Δ৘ใΛ༻ҙ͢Δ ࿦ཧσόΠεΛ࡞Δ
  16. .setQueueCount(1) .setPQueuePriorities(&priority) }; if(graphics_queue_index!=present_queue_index) queues.emplace_back( vk::DeviceQueueCreateInfo() .setQueueFamilyIndex(present_queue_index) .setQueueCount(1) .setPQueuePriorities(&priority) );

    device=physical_device->createDevice( vk::DeviceCreateInfo() .setQueueCreateInfoCount(queues.size()) .setPQueueCreateInfos(queues.data()) .setEnabledLayerCount(dlayers.size()) .setPpEnabledLayerNames(dlayers.data()) .setEnabledExtensionCount(dext.size()) .setPpEnabledExtensionNames(dext.data()) .setPEnabledFeatures(&features) ); graphics_queue=device.getQueue(graphics_queue_index,0); present_queue=device.getQueue(present_queue_index,0); createDeviceʹ ඞཁͳ֦ுɺϨΠϠʔɺΩϡʔͷ৘ใΛ౉ͯ͠ ࿦ཧσόΠεΛ࡞Δ ࿦ཧσόΠεΛ࡞Δ Ҏ߱GPUʹର͢Δ΄ͱΜͲͷૢ࡞͸ ࿦ཧσόΠεʹରͯ͠ߦ͏ࣄʹͳΔ
  17. const auto surface_capabilities= physical_device->getSurfaceCapabilitiesKHR(surface); const auto present_modes= physical_device->getSurfacePresentModesKHR(surface); vk::Extent2D swapchain_extent;

    if(surface_capabilities.currentExtent.width==(uint32_t)-1){ sc_extent.width = width; sc_extent.height = height; }else{ sc_extent=surface_capabilities.currentExtent; width=surface_capabilities.currentExtent.width; height=surface_capabilities.currentExtent.height; } const uint32_t sc_image_count= std::min(surface_capabilities.minImageCount+1, surface_capabilities.maxImageCount); const vk::SurfaceTransformFlagBitsKHR transform_flag= (surface_capabilities.supportedTransforms& vk::SurfaceTransformFlagBitsKHR::eIdentity)? vk::SurfaceTransformFlagBitsKHR::eIdentity: surface_capabilities.currentTransform; ϋʔυ΢ΣΞʹΑͬͯ͸εϫοϓνΣΠϯͷ ը૾ͷαΠζ͕ݻఆ͞Ε͍ͯΔ͜ͱ͕͋Δ SurfaceCapabiitiesΛௐ΂ͯ -1͕ηοτ͞Ε͍ͯͨΒ೚ҙͷαΠζΛࢦఆͰ͖Δ εϫοϓνΣΠϯ
  18. const auto surface_capabilities= physical_device->getSurfaceCapabilitiesKHR(surface); const auto present_modes= physical_device->getSurfacePresentModesKHR(surface); vk::Extent2D swapchain_extent;

    if(surface_capabilities.currentExtent.width==(uint32_t)-1){ sc_extent.width = width; sc_extent.height = height; }else{ sc_extent=surface_capabilities.currentExtent; width=surface_capabilities.currentExtent.width; height=surface_capabilities.currentExtent.height; } const uint32_t sc_image_count= std::min(surface_capabilities.minImageCount+1, surface_capabilities.maxImageCount); const vk::SurfaceTransformFlagBitsKHR transform_flag= (surface_capabilities.supportedTransforms& vk::SurfaceTransformFlagBitsKHR::eIdentity)? vk::SurfaceTransformFlagBitsKHR::eIdentity: surface_capabilities.currentTransform; εϫοϓνΣΠϯͷ࠷খຕ਺ͱ࠷େຕ਺͸ ϋʔυ΢ΣΞʹΑͬͯҟͳΔ ࡞੒͢ΔεϫοϓνΣΠϯͷຕ਺͸ ͜ͷൣғ಺ͷ஋Ͱͳ͚Ε͹ͳΒͳ͍ εϫοϓνΣΠϯ
  19. swapchain=device.createSwapchainKHR( vk::SwapchainCreateInfoKHR().setSurface(surface) .setMinImageCount(sc_image_count) .setImageFormat(format) .setImageColorSpace(color_space) .setImageExtent({sc_extent.width, sc_extent.height}) .setImageArrayLayers(1) .setImageUsage(vk::ImageUsageFlagBits::eColorAttachment) .setImageSharingMode(vk::SharingMode::eExclusive)

    .setQueueFamilyIndexCount(0) .setPQueueFamilyIndices(nullptr) .setPreTransform(transform_flag) .setCompositeAlpha(vk::CompositeAlphaFlagBitsKHR::eOpaque) .setPresentMode(vk::PresentModeKHR::eFifo) .setClipped(true) ); swapchain_images=device.getSwapchainImagesKHR(swapchain); for(auto &swapchain_image:swapchain_images){ swapchain_views.emplace_back(device.createImageView( vk::ImageViewCreateInfo().setImage(swapchain_image) .setViewType(vk::ImageViewType::e2D) .setFormat(format) ࢦఆͨ͠αΠζͱϑΥʔϚοτͷΠϝʔδΛ ࢦఆͨ͠ຕ਺࣋ͭεϫοϓνΣΠϯΛ࡞Δ εϫοϓνΣΠϯ
  20. .setPQueueFamilyIndices(nullptr) .setPreTransform(transform_flag) .setCompositeAlpha(vk::CompositeAlphaFlagBitsKHR::eOpaque) .setPresentMode(vk::PresentModeKHR::eFifo) .setClipped(true) ); swapchain_images=device.getSwapchainImagesKHR(swapchain); for(auto &swapchain_image:swapchain_images){ swapchain_views.emplace_back(device.createImageView(

    vk::ImageViewCreateInfo().setImage(swapchain_image) .setViewType(vk::ImageViewType::e2D) .setFormat(format) .setSubresourceRange(vk::ImageSubresourceRange( vk::ImageAspectFlagBits::eColor,0,1,0,1 )) ) ); } ϓϨθϯτϞʔυ vk::PresentModeKHR::eImmediate ඳըΛऴ͑ͨΠϝʔδΛදࣔՄೳঢ়ଶʹͨ͠ޙ ͦΕ͕͍ͭදࣔ͞ΕΔ͔Λίϯτϩʔϧ͢Δ ը໘ͷਨ௚ಉظΛ଴ͨͣʹ௚ͪʹΠϝʔδΛೖΕସ͑Δ ςΟΞϦϯά͕ى͜ΔՄೳੑ͕͋Δ͕࠷΋ૣ͘ද͕ࣔߋ৽͞ΕΔ vk::PresentModeKHR::eMailbox ը໘ͷਨ௚ಉظΛ଴ͬͯΠϝʔδΛೖΕସ͑Δ ·ͩද͍ࣔͯ͠ͳ͍Πϝʔδ͕͋Δͷʹ࣍ͷΠϝʔδ͕དྷͨ৔߹ ઌʹදࣔΩϡʔʹੵ·Ε͍ͯͨΠϝʔδ͸ഁغ͞ΕΔ vk::PresentModeKHR::eFIFO ը໘ͷਨ௚ಉظΛ଴ͬͯΠϝʔδΛೖΕସ͑Δ ·ͩද͍ࣔͯ͠ͳ͍Πϝʔδ͕͋Δͷʹ࣍ͷΠϝʔδ͕དྷͨ৔߹ ઌʹදࣔΩϡʔʹੵ·Ε͍ͯͨΠϝʔδ͔Βॱʹදࣔ͞ΕΔ
  21. .setPQueueFamilyIndices(nullptr) .setPreTransform(transform_flag) .setCompositeAlpha(vk::CompositeAlphaFlagBitsKHR::eOpaque) .setPresentMode(vk::PresentModeKHR::eFifo) .setClipped(true) ); swapchain_images=device.getSwapchainImagesKHR(swapchain); for(auto &swapchain_image:swapchain_images){ swapchain_views.emplace_back(device.createImageView(

    vk::ImageViewCreateInfo().setImage(swapchain_image) .setViewType(vk::ImageViewType::e2D) .setFormat(format) .setSubresourceRange(vk::ImageSubresourceRange( vk::ImageAspectFlagBits::eColor,0,1,0,1 )) ) ); } ϓϨθϯτϞʔυ vk::PresentModeKHR::eImmediate ඳըΛऴ͑ͨΠϝʔδΛදࣔՄೳঢ়ଶʹͨ͠ޙ ͦΕ͕͍ͭදࣔ͞ΕΔ͔Λίϯτϩʔϧ͢Δ ը໘ͷਨ௚ಉظΛ଴ͨͣʹ௚ͪʹΠϝʔδΛೖΕସ͑Δ ςΟΞϦϯά͕ى͜ΔՄೳੑ͕͋Δ͕࠷΋ૣ͘ද͕ࣔߋ৽͞ΕΔ vk::PresentModeKHR::eMailbox ը໘ͷਨ௚ಉظΛ଴ͬͯΠϝʔδΛೖΕସ͑Δ ·ͩද͍ࣔͯ͠ͳ͍Πϝʔδ͕͋Δͷʹ࣍ͷΠϝʔδ͕དྷͨ৔߹ ઌʹදࣔΩϡʔʹੵ·Ε͍ͯͨΠϝʔδ͸ഁغ͞ΕΔ vk::PresentModeKHR::eFIFO ը໘ͷਨ௚ಉظΛ଴ͬͯΠϝʔδΛೖΕସ͑Δ ·ͩද͍ࣔͯ͠ͳ͍Πϝʔδ͕͋Δͷʹ࣍ͷΠϝʔδ͕དྷͨ৔߹ ઌʹදࣔΩϡʔʹੵ·Ε͍ͯͨΠϝʔδ͔Βॱʹදࣔ͞ΕΔ
  22. .setPQueueFamilyIndices(nullptr) .setPreTransform(transform_flag) .setCompositeAlpha(vk::CompositeAlphaFlagBitsKHR::eOpaque) .setPresentMode(vk::PresentModeKHR::eFifo) .setClipped(true) ); swapchain_images=device.getSwapchainImagesKHR(swapchain); for(auto &swapchain_image:swapchain_images){ swapchain_views.emplace_back(device.createImageView(

    vk::ImageViewCreateInfo().setImage(swapchain_image) .setViewType(vk::ImageViewType::e2D) .setFormat(format) .setSubresourceRange(vk::ImageSubresourceRange( vk::ImageAspectFlagBits::eColor,0,1,0,1 )) ) ); } ϓϨθϯτϞʔυ vk::PresentModeKHR::eImmediate ඳըΛऴ͑ͨΠϝʔδΛදࣔՄೳঢ়ଶʹͨ͠ޙ ͦΕ͕͍ͭදࣔ͞ΕΔ͔Λίϯτϩʔϧ͢Δ ը໘ͷਨ௚ಉظΛ଴ͨͣʹ௚ͪʹΠϝʔδΛೖΕସ͑Δ ςΟΞϦϯά͕ى͜ΔՄೳੑ͕͋Δ͕࠷΋ૣ͘ද͕ࣔߋ৽͞ΕΔ vk::PresentModeKHR::eMailbox ը໘ͷਨ௚ಉظΛ଴ͬͯΠϝʔδΛೖΕସ͑Δ ·ͩද͍ࣔͯ͠ͳ͍Πϝʔδ͕͋Δͷʹ࣍ͷΠϝʔδ͕དྷͨ৔߹ ઌʹදࣔΩϡʔʹੵ·Ε͍ͯͨΠϝʔδ͸ഁغ͞ΕΔ vk::PresentModeKHR::eFIFO ը໘ͷਨ௚ಉظΛ଴ͬͯΠϝʔδΛೖΕସ͑Δ ·ͩද͍ࣔͯ͠ͳ͍Πϝʔδ͕͋Δͷʹ࣍ͷΠϝʔδ͕དྷͨ৔߹ ઌʹදࣔΩϡʔʹੵ·Ε͍ͯͨΠϝʔδ͔Βॱʹදࣔ͞ΕΔ
  23. .setPresentMode(vk::PresentModeKHR::eFifo) .setClipped(true) ); swapchain_images=device.getSwapchainImagesKHR(swapchain); for(auto &swapchain_image:swapchain_images){ swapchain_views.emplace_back(device.createImageView( vk::ImageViewCreateInfo().setImage(swapchain_image) .setViewType(vk::ImageViewType::e2D) .setFormat(format)

    .setSubresourceRange(vk::ImageSubresourceRange( vk::ImageAspectFlagBits::eColor,0,1,0,1 )) ) ); } εϫοϓνΣΠϯͷΠϝʔδΛऔಘͯ͠ ΠϝʔδϏϡʔΛ࡞͓ͬͯ͘ ΠϝʔδϏϡʔͱ͸ ը૾σʔλΛͲ͏ղऍ͢΂͖͔Λఆٛͨ͠΋ͷ Πϝʔδʹରͯ͠ಡΈॻ͖Λߦ͏ͷʹඞཁ εϫοϓνΣΠϯ
  24. Πϝʔδ (16ʹஔ͘σʔλͷ͏ͪ த਎ΛԿΒ͔ͷϑΥʔϚοτͷ ը૾σʔλͱͯ͠ղऍ͢Δ΋ͷ Πϝʔδ F4BNQMFE F4UPSBHF F$PMPS"UUBDINFOU F%FQUI4UFODJM"UUBDINFOU F*OQVU"UUBDINFOU

    ςΫενϟ γΣʔμ͔Β ೚ҙͷϐΫηϧΛ ಡΈॻ͖Ͱ͖Δը૾ ϨϯμϦϯά݁Ռ ਂ౓όοϑΝ લͷαϒύε͔Βͷ ೖྗը૾ ͜ΕΒ͸͍ͣΕ΋createImageͰ࡞ΕΔ FUD
  25. ίϚϯυ ౤ೖ ϨϯμϦϯά ׬ྃ U U U U U දࣔ

    ྘ͱ੨͕ϨϯμϦϯάதͰ੺͕දࣔத εϫοϓνΣΠϯ͕ຕҎ্͋Δ৔߹ ෳ਺ͷϨϯμϦϯά͕ಉ࣌ʹ૸͍ͬͯΔՄೳੑ͕͋Δ
  26. for(size_t i=0u;i!=swapchain_image_count;++i){ depth_image.emplace_back(device.createImage( vk::ImageCreateInfo() .setImageType(vk::ImageType::e2D) .setFormat(vk::Format::eD16Unorm) .setExtent({width,height,1}) .setMipLevels(1) .setArrayLayers(1) .setUsage(

    vk::ImageUsageFlagBits::eDepthStencilAttachment| vk::ImageUsageFlagBits::eTransferDst ) )); position_image.emplace_back(device.createImage( vk::ImageCreateInfo() .setImageType(vk::ImageType::e2D) .setExtent(vk::Extent3D(width,height,1)) .setFormat(vk::Format::eR32G32B32A32Sfloat) .setMipLevels(1) .setArrayLayers(1) ਂ౓όοϑΝ౳Ұ࣌తͳ஋Λஔ͘Πϝʔδ͸ গͳ͘ͱ΋εϫοϓνΣΠϯͷຕ਺ຕඞཁ
  27. for(size_t i=0u;i!=swapchain_image_count;++i){ depth_image.emplace_back(device.createImage( vk::ImageCreateInfo() .setImageType(vk::ImageType::e2D) .setFormat(vk::Format::eD16Unorm) .setExtent({width,height,1}) .setMipLevels(1) .setArrayLayers(1) .setUsage(

    vk::ImageUsageFlagBits::eDepthStencilAttachment| vk::ImageUsageFlagBits::eTransferDst ) )); position_image.emplace_back(device.createImage( vk::ImageCreateInfo() .setImageType(vk::ImageType::e2D) .setExtent(vk::Extent3D(width,height,1)) .setFormat(vk::Format::eR32G32B32A32Sfloat) .setMipLevels(1) .setArrayLayers(1) .setUsage( vk::ImageUsageFlagBits::eColorAttachment| vk::ImageUsageFlagBits::eTransferDst| ਂ౓όοϑΝ ઃఆ͸্͔Βॱʹ ࣍ݩΠϝʔδͰɺCJU੔਺ͷਂ౓஋ͷΈͰɺ େ͖͞͸ը໘αΠζͱಉ͡Ͱɺ.JQͳ͠ɺ ϨΠϠʔຕɺ༻్͸ਂ౓όοϑΝͱσʔλసૹઌ ϨϯμʔόοϑΝΛ࡞Δ
  28. vk::ImageUsageFlagBits::eSampled ) )); position_image.emplace_back(device.createImage( vk::ImageCreateInfo() .setImageType(vk::ImageType::e2D) .setExtent(vk::Extent3D(width,height,1)) .setFormat(vk::Format::eR32G32B32A32Sfloat) .setMipLevels(1) .setArrayLayers(1)

    .setUsage( vk::ImageUsageFlagBits::eColorAttachment| vk::ImageUsageFlagBits::eTransferDst| vk::ImageUsageFlagBits::eInputAttachment ) )); normal_image.emplace_back(device.createImage( vk::ImageCreateInfo() .setImageType(vk::ImageType::e2D) .setExtent(vk::Extent3D(width,height,1)) .setFormat(vk::Format::eR32G32B32A32Sfloat) .setMipLevels(1) .setArrayLayers(1) .setUsage( vk::ImageUsageFlagBits::eColorAttachment| ϫʔϧυ࠲ඪόοϑΝ༻ͷΠϝʔδΛ࡞Δ ઃఆ͸্͔Βॱʹ ࣍ݩΠϝʔδͰɺCJUුಈখ਺ͷ3(#"Ͱɺ େ͖͞͸ը໘αΠζͱಉ͡Ͱɺ.JQͳ͠ɺϨΠϠʔຕɺ ༻్͸ΧϥʔόοϑΝͱσʔλసૹઌͱ*OQVU"UUBDINFOU ϫʔϧυ࠲ඪόοϑΝ
  29. vk::ImageUsageFlagBits::eInputAttachment ) )); normal_image.emplace_back(device.createImage( vk::ImageCreateInfo() .setImageType(vk::ImageType::e2D) .setExtent(vk::Extent3D(width,height,1)) .setFormat(vk::Format::eR32G32B32A32Sfloat) .setMipLevels(1) .setArrayLayers(1)

    .setUsage( vk::ImageUsageFlagBits::eColorAttachment| vk::ImageUsageFlagBits::eTransferDst| vk::ImageUsageFlagBits::eInputAttachment ) )); } ϫʔϧυ๏ઢόοϑΝ༻ͷΠϝʔδΛ࡞Δ ઃఆ͸্͔Βॱʹ ࣍ݩΠϝʔδͰɺCJUුಈখ਺ͷ3(#"Ͱɺ େ͖͞͸ը໘αΠζͱಉ͡Ͱɺ.JQͳ͠ɺϨΠϠʔຕɺ ༻్͸ΧϥʔόοϑΝͱσʔλసૹઌͱ*OQVU"UUBDINFOU ϫʔϧυ๏ઢόοϑΝ
  30. for(size_t i=0u;i!=swapchain_image_count;++i){ const auto depth_memory_requirements= device.getImageMemoryRequirements(depth_image[i]); if(total_image_memory%depth_memory_requirements.alignment) total_image_memory+= depth_memory_requirements.alignment -(total_image_memory%depth_memory_requirements.alignment);

    depth_memory_offsets.emplace_back( total_image_memory,depth_memory_requirements.size ); total_image_memory+=depth_memory_requirements.size; const auto position_memory_requirements= device.getImageMemoryRequirements(position_image[i]); if(total_image_memory%position_memory_requirements.alignment) total_image_memory+= position_memory_requirements.alignment -( total_image_memory% position_memory_requirements.alignment ); createImage͸࣮ࡍͷσʔλ͕ஔ͔ΕΔ ϝϞϦྖҬΛ֬อ͸͠ͳ͍ ֤Πϝʔδʹඞཁͳ ϝϞϦͷαΠζͱΞϥΠϯϝϯτΛऔಘͯ͠
  31. const auto required_memory_props= vk::MemoryPropertyFlagBits::eDeviceLocal; const auto memory_type_index= std::distance( memory_properties.memoryTypes, std::find_if(

    memory_properties.memoryTypes, memory_properties.memoryTypes + VK_MAX_MEMORY_TYPES, [&](const auto &v){ return (v.propertyFlags&required_memory_props)== required_memory_props; } ) ); image_memory=device.allocateMemory( vk::MemoryAllocateInfo() .setAllocationSize(total_image_memory) .setMemoryTypeIndex(memory_type_index) ); allocateMemoryͰඞཁͳϝϞϦྖҬΛ֬อ σόΠεͰ࢖͑ΔϝϞϦͷத͔Β Α͛͞ͳϝϞϦΛબΜͰ
  32. for(size_t i=0u; i!=swapchain_image_count;++i){ device.bindImageMemory( depth_image[i],image_memory,depth_memory_offsets[i].first ); device.bindImageMemory( position_image[i],image_memory, position_memory_offsets[i].first );

    device.bindImageMemory( normal_image[i],image_memory, normal_memory_offsets[ i ].first ); depth_view.emplace_back(device.createImageView( vk::ImageViewCreateInfo() .setImage(depth_image[i]) .setViewType(vk::ImageViewType::e2D) .setFormat(vk::Format::eD16Unorm) .setSubresourceRange(vk::ImageSubresourceRange( vk::ImageAspectFlagBits::eDepth,0,1,0,1 )) )); ֬อͨ͠ϝϞϦΛ*NBHFʹCJOEͯ͠ ϑϨʔϜόοϑΝΛ࡞Δ
  33. normal_image[i],image_memory, normal_memory_offsets[ i ].first ); depth_view.emplace_back(device.createImageView( vk::ImageViewCreateInfo() .setImage(depth_image[i]) .setViewType(vk::ImageViewType::e2D) .setFormat(vk::Format::eD16Unorm)

    .setSubresourceRange(vk::ImageSubresourceRange( vk::ImageAspectFlagBits::eDepth,0,1,0,1 )) )); position_view.emplace_back(device.createImageView( vk::ImageViewCreateInfo() .setImage(position_image[i]) .setViewType(vk::ImageViewType::e2D) .setFormat(vk::Format::eR32G32B32A32Sfloat) .setSubresourceRange(vk::ImageSubresourceRange( vk::ImageAspectFlagBits::eColor,0,1,0,1 )) )); normal_view.emplace_back( device.createImageView( vk::ImageViewCreateInfo() .setImage( normal_image[ i ] ) .setViewType( vk::ImageViewType::e2D ) ΠϝʔδϏϡʔΛ࡞͓ͬͯ͘ ϑϨʔϜόοϑΝΛ࡞Δ ༁͜ͷྖҬ͸CJUුಈখ਺3(#"ͷ࣍ݩը૾ͱͯ͠࢖ͬͯͶ ༁͜ͷྖҬ͸CJU੔਺ਂ౓ͷΈͷ࣍ݩը૾ͱͯ͠࢖ͬͯͶ
  34. framebuffers.emplace_back(device.createFramebuffer( vk::FramebufferCreateInfo() .setRenderPass(render_pass) .setAttachmentCount(attachments.size()) .setPAttachments(attachments.data()) .setWidth(width) .setHeight(height) .setLayers(1) ) );

    *NBHF7JFXͷ഑ྻͱ ͍ͩͿޙͷํͰ࡞Δ *NBHF7JFXͷ࢖͍ํΛઃఆͨ͠ϨϯμʔύεΛ ૊Έ߹ΘͤͯϑϨʔϜόοϑΝ͕׬੒͢Δ ϑϨʔϜόοϑΝΛ࡞Δ ͜Ε
  35. ίϚϯυόοϑΝ ίϚϯυόοϑΝ ඳըͯ͠ ύΠϓϥΠϯมߋ σʔλసૹͯ͠ ׬ྃ଴ͬͯ σόΠε Ωϡʔ (16΁ͷίϚϯυ͸ ·ͣίϚϯυόοϑΝʹੵΉ

    ͜ͷ࣌఺ͰίϚϯυ͸ (16Ͱͷ۩ମతͳॲཧʹ ຋༁͞ΕΔ ࣮ߦ ίϚϯυόοϑΝ୯ҐͰ ΩϡʔʹίϚϯυΛੵΉ ίϚϯυόοϑΝ͸Կ౓Ͱ΋ΩϡʔʹੵΊΔ ຖϑϨʔϜߦ͏ॲཧͷίϚϯυྻΛ ຖϑϨʔϜͭͮͭ౤͛Δඞཁ͸ͳ͍
  36. ίϚϯυόοϑΝ ίϚϯυόοϑΝ ඳըͯ͠ ύΠϓϥΠϯมߋ σʔλసૹͯ͠ σόΠε Ωϡʔ ࣮ߦ ίϚϯυόοϑΝ ඳըͯ͠

    ύΠϓϥΠϯมߋ σʔλసૹͯ͠ εϨου εϨου ίϚϯυόοϑΝ͸ෳ਺ͷεϨουͰ࡞ͬͯ ͭͷΩϡʔʹੵΜͰ΋ྑ͍
  37. όοϑΝ (16ʹஔ͘σʔλͷ͏ͪ த਎Λը૾σʔλͱͯ͠ղऍ͠ͳ͍΋ͷ όοϑΝ F6OJGPSN#V⒎FS F4UPSBHF5FYFM#V⒎FS F7FSUFY#V⒎FS F*OEFY#V⒎FS F4UPSBHF#V⒎FS γΣʔμͷ

    VOJGPSN஋ ΠϝʔδόοϑΝ ௖఺όοϑΝ ௖఺ ΠϯσοΫε γΣʔμετϨʔδ όοϑΝ ͜ΕΒ͸͍ͣΕ΋createBufferͰ࡞ΕΔ FUD
  38. vertex_buffer=device.createBuffer( vk::BufferCreateInfo() .setSize(sizeof(vertex_t)*scene_.get_vertices().size()) .setUsage( vk::BufferUsageFlagBits::eVertexBuffer| vk::BufferUsageFlagBits::eTransferDst ) ); vertex_memory=device.allocateMemory( vk::MemoryAllocateInfo()

    .setAllocationSize(vertex_memory_requirements.size) .setMemoryTypeIndex(memory_type_index) ); device.bindBufferMemory(vertex_buffer,vertex_memory,0); std::shared_ptr<uint8_t> mapped_memory( static_cast<uint8_t*>(device.mapMemory( vertex_memory,0,vertex_memory_requirements.size )), [&](uint8_t *p){if(p)device.unmapMemory(vertex_memory);} ); memcpy( mapped_memory.get(),scene_.get_vertices().data(), sizeof(vertex_t)*scene_.get_vertices().size() ௖఺όοϑΝ ༻్F7FSUFY#V⒎FSͰόοϑΝΛ࡞੒ ࣍ݩܗঢ়ͷ৘ใ
  39. vertex_buffer=device.createBuffer( vk::BufferCreateInfo() .setSize(sizeof(vertex_t)*scene_.get_vertices().size()) .setUsage( vk::BufferUsageFlagBits::eVertexBuffer| vk::BufferUsageFlagBits::eTransferDst ) ); vertex_memory=device.allocateMemory( vk::MemoryAllocateInfo()

    .setAllocationSize(vertex_memory_requirements.size) .setMemoryTypeIndex(memory_type_index) ); device.bindBufferMemory(vertex_buffer,vertex_memory,0); std::shared_ptr<uint8_t> mapped_memory( static_cast<uint8_t*>(device.mapMemory( vertex_memory,0,vertex_memory_requirements.size )), [&](uint8_t *p){if(p)device.unmapMemory(vertex_memory);} ); memcpy( mapped_memory.get(),scene_.get_vertices().data(), sizeof(vertex_t)*scene_.get_vertices().size() ௖఺όοϑΝ Πϝʔδಉ༷࣮ࡍͷϝϞϦྖҬ͸ࣗ෼Ͱ֬อ
  40. vertex_buffer=device.createBuffer( vk::BufferCreateInfo() .setSize(sizeof(vertex_t)*scene_.get_vertices().size()) .setUsage( vk::BufferUsageFlagBits::eVertexBuffer| vk::BufferUsageFlagBits::eTransferDst ) ); vertex_memory=device.allocateMemory( vk::MemoryAllocateInfo()

    .setAllocationSize(vertex_memory_requirements.size) .setMemoryTypeIndex(memory_type_index) ); device.bindBufferMemory(vertex_buffer,vertex_memory,0); std::shared_ptr<uint8_t> mapped_memory( static_cast<uint8_t*>(device.mapMemory( vertex_memory,0,vertex_memory_requirements.size )), [&](uint8_t *p){if(p)device.unmapMemory(vertex_memory);} ); memcpy( mapped_memory.get(),scene_.get_vertices().data(), sizeof(vertex_t)*scene_.get_vertices().size() ); ௖఺όοϑΝ సૹํ๏΋Πϝʔδͱಉ͡ $16ͷϝϞϦۭؒʹϚοϓͯ͠ίϐʔ
  41. const auto vertex_input_binding= vk::VertexInputBindingDescription() .setBinding(0) .setStride(sizeof(vertex_t)) .setInputRate(vk::VertexInputRate::eVertex); const std::vector<vk::VertexInputAttributeDescription> vertex_input_attribute{

    vk::VertexInputAttributeDescription() .setLocation(0) .setBinding(0) .setFormat(vk::Format::eR32G32B32Sfloat) .setOffset(offsetof(vertex_t,position)), vk::VertexInputAttributeDescription() .setLocation(1) .setBinding(0) .setFormat(vk::Format::eR32G32B32Sfloat) .setOffset(offsetof(vertex_t,color)), vk::VertexInputAttributeDescription() .setLocation(2) .setBinding(0) .setFormat(vk::Format::eR32G32B32Sfloat) .setOffset(offsetof(vertex_t,normal)), ௖఺όοϑΝ ͜ͷ௖఺όοϑΝʹ ௖఺͕ͲͷΑ͏ʹ֨ೲ͞Ε͍ͯΔ͔Λද͢ vk::PipelineVertexInputStateCreateInfo Λ࡞͓ͬͯ͘ ௖఺ݸͷαΠζ ௖఺γΣʔμͷԿ൪໨ͷ௖఺ଐੑʹ ରԠ͚ͮΔ͔ CJUුಈখ਺͔ͭΒͳΔϕΫτϧ஋ ௖఺ͷઌ಄͔ΒԿόΠτ໨ʹஔ͔Ε͍ͯΔ͔
  42. uniform_buffer=device.createBuffer( vk::BufferCreateInfo() .setSize(sizeof(glm::mat4)*scene_.get_matrices().size()) .setUsage( vk::BufferUsageFlagBits::eUniformBuffer| vk::BufferUsageFlagBits::eTransferDst ) ); uniform_memory =

    device.allocateMemory( vk::MemoryAllocateInfo() .setAllocationSize(uniform_memory_requirements.size) .setMemoryTypeIndex(memory_type_index) ); device.bindBufferMemory(uniform_buffer,uniform_memory,0); std::shared_ptr<uint8_t> mapped_memory( static_cast<uint8_t*>(device.mapMemory( uniform_memory,0,uniform_memory_requirements.size )),[&](uint8_t *p){if(p)device.unmapMemory(uniform_memory);} ); memcpy( mapped_memory.get(), scene_.get_matrices().data(), sizeof(glm::mat4)*scene_.get_matrices().size() ϢχϑΥʔϜόοϑΝ γΣʔμ͕࣮ߦதʹΞΫηεͰ͖Δఆ਺ ༻్F6OJGPSN#V⒎FSͰόοϑΝΛ࡞੒
  43. uniform_buffer=device.createBuffer( vk::BufferCreateInfo() .setSize(sizeof(glm::mat4)*scene_.get_matrices().size()) .setUsage( vk::BufferUsageFlagBits::eUniformBuffer| vk::BufferUsageFlagBits::eTransferDst ) ); uniform_memory =

    device.allocateMemory( vk::MemoryAllocateInfo() .setAllocationSize(uniform_memory_requirements.size) .setMemoryTypeIndex(memory_type_index) ); device.bindBufferMemory(uniform_buffer,uniform_memory,0); std::shared_ptr<uint8_t> mapped_memory( static_cast<uint8_t*>(device.mapMemory( uniform_memory,0,uniform_memory_requirements.size )),[&](uint8_t *p){if(p)device.unmapMemory(uniform_memory);} ); memcpy( mapped_memory.get(), scene_.get_matrices().data(), sizeof(glm::mat4)*scene_.get_matrices().size() ); ϢχϑΥʔϜόοϑΝ ޙͷखॱ͸௖఺όοϑΝͱҰॹ
  44. std::fstream file("vert.spv",std::ios::in|std::ios::binary); const std::vector<char> bin( (std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>() ); mesh_pass_vertex_shader_module=device.createShaderModule( vk::ShaderModuleCreateInfo()

    .setCodeSize(bin.size()) .setPCode(reinterpret_cast<const uint32_t*>(bin.data())) ); γΣʔμϞδϡʔϧ ύΠϓϥΠϯͷ೚ҙͷܭࢉ͕Ͱ͖Δ෦෼Ͱ࣮ߦ͢Δίʔυ Ͱ͸GLSLͱݺ͹ΕΔߴڃݴޠͷιʔεΛ౉ͯ͠ ࣮ߦ࣌ʹίϯύΠϧ͍͕ͯͨ͠ Ͱ͸SPIR-Vͱݺ͹ΕΔίϯύΠϧࡁΈͷ தؒݴޠͷΧλϚϦΛ౉ͯ͠γΣʔμϞδϡʔϧΛ࡞Δ γΣʔμ͸41*37Ͱు͔Ε͍ͯ͑͞Ε͹ԿݴޠͰॻ͍ͯ΋ྑ͍
  45. ϝϞϦ σεΫϦϓληοτ ύΠϓϥΠϯͱ࣮ࡍͷσʔλͷؒʹڬ·ͬͯ ͲͷσʔλΛ࢖ͬͯϨϯμϦϯά͢Δ͔ Λ੾Γସ͑ΔτϥϯϙϦϯͷΑ͏ͳ΋ͷ Πϝʔδ Πϝʔδ ௖఺όοϑΝ ϢχϑΥʔϜ όοϑΝ

    ετϨʔδ όοϑΝ σεΫϦϓλ ηοτ σεΫϦϓλ ηοτ ύΠϓϥΠϯ ຕ໨ͷ ςΫενϟ͍ͩ͘͞ ຕ໨ͷ ςΫενϟ͍ͩ͘͞
  46. const std::array<vk::DescriptorPoolSize,2> types{ vk::DescriptorPoolSize() .setType(vk::DescriptorType::eUniformBuffer) .setDescriptorCount(1), vk::DescriptorPoolSize() .setType(vk::DescriptorType::eInputAttachment) .setDescriptorCount(2) };

    descriptor_pool=device.createDescriptorPool( vk::DescriptorPoolCreateInfo() .setPoolSizeCount(types.size()) .setPPoolSizes(types.data()) .setMaxSets(100) ); const std::array<vk::DescriptorSetLayoutBinding,3> descriptor_set_layout_bindings{ vk::DescriptorSetLayoutBinding() σεΫϦϓληοτΛ࡞Δ σεΫϦϓλ༻ͷϝϞϦϓʔϧΛ࡞੒
  47. .setPPoolSizes(types.data()) .setMaxSets(100) ); const std::array<vk::DescriptorSetLayoutBinding,3> descriptor_set_layout_bindings{ vk::DescriptorSetLayoutBinding() .setDescriptorType(vk::DescriptorType::eUniformBuffer) .setDescriptorCount(1) .setBinding(0)

    .setStageFlags(vk::ShaderStageFlagBits::eVertex) .setPImmutableSamplers(nullptr), vk::DescriptorSetLayoutBinding() .setDescriptorType(vk::DescriptorType::eInputAttachment) .setDescriptorCount(1) .setBinding(1) .setStageFlags(vk::ShaderStageFlagBits::eFragment) .setPImmutableSamplers(nullptr), vk::DescriptorSetLayoutBinding() .setDescriptorType(vk::DescriptorType::eInputAttachment) .setDescriptorCount(1) .setBinding(2) .setStageFlags(vk::ShaderStageFlagBits::eFragment) .setPImmutableSamplers(nullptr) }; const std::vector<vk::DescriptorSetLayout> σεΫϦϓληοτΛ࡞Δ ༁௖఺γΣʔμͰಡΊΔϢχϑΥʔϜόοϑΝΛ CJOEJOHʹׂΓ౰ͯ
  48. .setPPoolSizes(types.data()) .setMaxSets(100) ); const std::array<vk::DescriptorSetLayoutBinding,3> descriptor_set_layout_bindings{ vk::DescriptorSetLayoutBinding() .setDescriptorType(vk::DescriptorType::eUniformBuffer) .setDescriptorCount(1) .setBinding(0)

    .setStageFlags(vk::ShaderStageFlagBits::eVertex) .setPImmutableSamplers(nullptr), vk::DescriptorSetLayoutBinding() .setDescriptorType(vk::DescriptorType::eInputAttachment) .setDescriptorCount(1) .setBinding(1) .setStageFlags(vk::ShaderStageFlagBits::eFragment) .setPImmutableSamplers(nullptr), vk::DescriptorSetLayoutBinding() .setDescriptorType(vk::DescriptorType::eInputAttachment) .setDescriptorCount(1) .setBinding(2) .setStageFlags(vk::ShaderStageFlagBits::eFragment) .setPImmutableSamplers(nullptr) }; const std::vector<vk::DescriptorSetLayout> σεΫϦϓληοτΛ࡞Δ ༁ϑϥάϝϯτγΣʔμͰಡΊΔೖྗΞλονϝϯτΛ CJOEJOHʹׂΓ౰ͯ
  49. vk::DescriptorSetLayoutBinding() .setDescriptorType(vk::DescriptorType::eInputAttachment) .setDescriptorCount(1) .setBinding(1) .setStageFlags(vk::ShaderStageFlagBits::eFragment) .setPImmutableSamplers(nullptr), vk::DescriptorSetLayoutBinding() .setDescriptorType(vk::DescriptorType::eInputAttachment) .setDescriptorCount(1) .setBinding(2)

    .setStageFlags(vk::ShaderStageFlagBits::eFragment) .setPImmutableSamplers(nullptr) }; const std::vector<vk::DescriptorSetLayout> descriptor_set_layout{ device.createDescriptorSetLayout( vk::DescriptorSetLayoutCreateInfo() .setBindingCount( descriptor_set_layout_bindings.size() ) .setPBindings( descriptor_set_layout_bindings.data() ), nullptr ) }; ༁ϑϥάϝϯτγΣʔμͰಡΊΔೖྗΞλονϝϯτΛ CJOEJOHʹׂΓ౰ͯ layout(input_attachment_index=0,set=0,binding=1) uniform subpassInput position; layout(input_attachment_index=1,set=0,binding=2) uniform subpassInput normal; void main() { vec3 pos=subpassLoad(position).xyz; vec3 N=subpassLoad(normal).xyz; vec3 V=normalize(eye-pos); vec3 L=normalize(lightpos-pos); ͜ͷೖྗΞλονϝϯτ͸γΣʔμͰ͸ positionͱ͍͏໊લͰΞΫηεͰ͖ΔΑ͏ʹͳΔ GLSL
  50. .setDescriptorType(vk::DescriptorType::eInputAttachment) .setDescriptorCount(1) .setBinding(2) .setStageFlags(vk::ShaderStageFlagBits::eFragment) .setPImmutableSamplers(nullptr) }; const std::vector<vk::DescriptorSetLayout> descriptor_set_layout{ device.createDescriptorSetLayout(

    vk::DescriptorSetLayoutCreateInfo() .setBindingCount( descriptor_set_layout_bindings.size() ) .setPBindings( descriptor_set_layout_bindings.data() ), nullptr ) }; σεΫϦϓληοτΛ࡞Δ σεΫϦϓληοτͷͲ͜ʹ Կͷ৘ใ͕ஔ͔Ε͍ͯΔ͔Λද͢ σεΫϦϓληοτϨΠΞ΢τΛ࡞Δ
  51. const auto descriptor_set_=device.allocateDescriptorSets( vk::DescriptorSetAllocateInfo() .setDescriptorPool(descriptor_pool) .setDescriptorSetCount(descriptor_set_layout.size()) .setPSetLayouts(descriptor_set_layout.data()) ); const std::vector<vk::DescriptorImageInfo>

    image_descriptors{ vk::DescriptorImageInfo() .setImageView(position_view[i]) .setImageLayout(vk::ImageLayout::eShaderReadOnlyOptimal), vk::DescriptorImageInfo() .setImageView(normal_view[i]) .setImageLayout(vk::ImageLayout::eShaderReadOnlyOptimal) }; const std::vector<vk::WriteDescriptorSet> write_descriptor_set{ vk::WriteDescriptorSet() .setDstSet(descriptor_set_[0]) .setDescriptorType(vk::DescriptorType::eUniformBuffer) .setDescriptorCount(1) .setPBufferInfo( &uniform_buffer_info ) .setDstBinding( 0 ), // (ུ) σεΫϦϓληοτΛ࡞Δ σεΫϦϓληοτʹඞཁͳྖҬΛׂΓ౰ͯΔ
  52. .setDescriptorSetCount(descriptor_set_layout.size()) .setPSetLayouts(descriptor_set_layout.data()) ); const std::vector<vk::DescriptorImageInfo> image_descriptors{ vk::DescriptorImageInfo() .setImageView(position_view[i]) .setImageLayout(vk::ImageLayout::eShaderReadOnlyOptimal), vk::DescriptorImageInfo()

    .setImageView(normal_view[i]) .setImageLayout(vk::ImageLayout::eShaderReadOnlyOptimal) }; const std::vector<vk::WriteDescriptorSet> write_descriptor_set{ vk::WriteDescriptorSet() .setDstSet(descriptor_set_[0]) .setDescriptorType(vk::DescriptorType::eUniformBuffer) .setDescriptorCount(1) .setPBufferInfo( &uniform_buffer_info ) .setDstBinding( 0 ), // (ུ) }; device.updateDescriptorSets( write_descriptor_set, nullptr ); descriptor_set.emplace_back( std::move( descriptor_set_ ) ); σεΫϦϓληοτΛ࡞Δ ࢖༻͢ΔΠϝʔδͱόοϑΝΛྻڍ͢Δ
  53. .setDescriptorSetCount(descriptor_set_layout.size()) .setPSetLayouts(descriptor_set_layout.data()) ); const std::vector<vk::DescriptorImageInfo> image_descriptors{ vk::DescriptorImageInfo() .setImageView(position_view[i]) .setImageLayout(vk::ImageLayout::eShaderReadOnlyOptimal), vk::DescriptorImageInfo()

    .setImageView(normal_view[i]) .setImageLayout(vk::ImageLayout::eShaderReadOnlyOptimal) }; const std::vector<vk::WriteDescriptorSet> write_descriptor_set{ vk::WriteDescriptorSet() .setDstSet(descriptor_set_[0]) .setDescriptorType(vk::DescriptorType::eUniformBuffer) .setDescriptorCount(1) .setPBufferInfo( &uniform_buffer_info ) .setDstBinding( 0 ), // (ུ) }; device.updateDescriptorSets( write_descriptor_set, nullptr ); descriptor_set.emplace_back( std::move( descriptor_set_ ) ); σεΫϦϓληοτΛ࡞Δ σεΫϦϓληοτͷ஋Λߋ৽
  54. const std::vector<vk::AttachmentDescription> attachments{ vk::AttachmentDescription() .setFormat(vk::Format::eR32G32B32Sfloat) .setSamples(vk::SampleCountFlagBits::e1) .setLoadOp(vk::AttachmentLoadOp::eClear) .setStoreOp(vk::AttachmentStoreOp::eStore) .setStencilLoadOp(vk::AttachmentLoadOp::eDontCare) .setStencilStoreOp(vk::AttachmentStoreOp::eDontCare)

    .setInitialLayout(vk::ImageLayout::eColorAttachmentOptimal) .setFinalLayout( vk::ImageLayout::eShaderReadOnlyOptimal), // (ུ) }; const std::array<vk::AttachmentReference,2u> mesh_pass_color_reference{ vk::AttachmentReference() .setAttachment(0) .setLayout(vk::ImageLayout::eColorAttachmentOptimal), vk::AttachmentReference() .setAttachment(1) .setLayout(vk::ImageLayout::eColorAttachmentOptimal) }; const std::array<vk::AttachmentReference,1u> ϨϯμʔύεΛ࡞Δ Ϩϯμʔύεʹొ৔͢ΔΞλονϝϯτΛఆٛ
  55. const std::array<vk::AttachmentReference,1u> mesh_pass_depth_reference{ // (ུ) const std::vector<vk::SubpassDescription> subpass{ vk::SubpassDescription() .setPipelineBindPoint(

    vk::PipelineBindPoint::eGraphics ) .setInputAttachmentCount( 0 ) .setPInputAttachments( nullptr ) .setColorAttachmentCount( mesh_pass_color_reference.size() ) .setPColorAttachments( mesh_pass_color_reference.data() ) .setPResolveAttachments( nullptr ) .setPDepthStencilAttachment( &mesh_pass_depth_reference ) .setPreserveAttachmentCount( 0 ) .setPPreserveAttachments( nullptr ), // (ུ) }; ϨϯμʔύεΛ࡞Δ ࢖༻͢ΔΞλονϝϯτΛࢦఆͯ͠ αϒύεΛఆٛ
  56. std::array<vk::SubpassDependency,1u> subpass_dependency{ vk::SubpassDependency() .setSrcSubpass( 0 ) .setDstSubpass( 1 ) .setSrcStageMask(

    vk::PipelineStageFlagBits::eColorAttachmentOutput ) .setDstStageMask(vk::PipelineStageFlagBits::eFragmentShader) .setSrcAccessMask(vk::AccessFlagBits::eColorAttachmentWrite) .setDstAccessMask(vk::AccessFlagBits::eInputAttachmentRead) }; ϨϯμʔύεΛ࡞Δ ༁αϒύεͷϑϥάϝϯτγΣʔμ͸ αϒύεͷΧϥʔΞλονϝϯτ΁ͷग़ྗ͕ ׬ྃͨ͠ޙʹ࣮ߦ͞Εͳ͚Ε͹ͳΒͳ͍ αϒύεͰΧϥʔΞλονϝϯτͩͬͨ΋ͷ͕ αϒύεͰೖྗΞλονϝϯτͱͯ͠࢖ΘΕΔ
  57. ௖఺γΣʔμ ը໘͔Β͸Έग़͢ࡾ֯ܗΛࣺͯΔ ࡾ֯ܗͷ಺ଆͷϐΫηϧΛٻΊΔ ϑϥάϝϯτγΣʔμ طʹඳ͔Εͨ෺ΑΓखલ͔֬ೝ ϑϨʔϜόοϑΝͷ৭Λߋ৽ δΦϝτϦγΣʔμ ςηϨʔγϣϯ੍ޚγΣʔμ ςηϨʔγϣϯධՁγΣʔμ Ͱ͔͍ϓϦϛςΟϒΛ෼ׂ

    ௖఺γΣʔμ ը໘͔Β͸Έग़͢ࡾ֯ܗΛࣺͯΔ ࡾ֯ܗͷ಺ଆͷϐΫηϧΛٻΊΔ ϑϥάϝϯτγΣʔμ طʹඳ͔Εͨ෺ΑΓखલ͔֬ೝ ϑϨʔϜόοϑΝͷ৭Λߋ৽ δΦϝτϦγΣʔμ ςηϨʔγϣϯ੍ޚγΣʔμ ςηϨʔγϣϯධՁγΣʔμ Ͱ͔͍ϓϦϛςΟϒΛ෼ׂ ಉظ αϒύε αϒύε
  58. pipeline_cache= device.createPipelineCache(vk::PipelineCacheCreateInfo()); const std::array<vk::PipelineShaderStageCreateInfo,2u> mesh_pass_pipeline_shader_stages{ vk::PipelineShaderStageCreateInfo() .setStage(vk::ShaderStageFlagBits::eVertex) .setModule(mesh_pass_vertex_shader_module) .setPName(“main"), //

    (ུ) }; auto const input_assembly_info= vk::PipelineInputAssemblyStateCreateInfo() .setTopology(vk::PrimitiveTopology::eTriangleList); auto const viewport_info= vk::PipelineViewportStateCreateInfo() .setViewportCount(1) .setScissorCount(1); auto const rasterization_info= vk::PipelineRasterizationStateCreateInfo() .setDepthClampEnable(VK_FALSE) ύΠϓϥΠϯΛ࡞Δ
  59. .setAttachmentCount(mesh_color_blend_attachments.size()) .setPAttachments(mesh_color_blend_attachments.data()); const std::array<vk::PipelineColorBlendAttachmentState,1u> ɹpost_color_blend_attachments{ vk::PipelineColorBlendAttachmentState() .setColorWriteMask( ɹ vk::ColorComponentFlagBits::eR| vk::ColorComponentFlagBits::eG|

    vk::ColorComponentFlagBits::eB| vk::ColorComponentFlagBits::eA ) }; const auto post_color_blend_info= vk::PipelineColorBlendStateCreateInfo() .setAttachmentCount(post_color_blend_attachments.size()) .setPAttachments(post_color_blend_attachments.data()); const std::array<vk::DynamicState,2u> dynamic_states{ vk::DynamicState::eViewport, vk::DynamicState::eScissor }; const auto dynamic_state_info= vk::PipelineDynamicStateCreateInfo() .setDynamicStateCount(dynamic_states.size()) .setPDynamicStates(dynamic_states.data()); ύΠϓϥΠϯΛ࡞Δ
  60. ύΠϓϥΠϯΛ࡞Δ const std::array<vk::GraphicsPipelineCreateInfo,2u> pipeline_create_info{ vk::GraphicsPipelineCreateInfo() .setStageCount(mesh_pass_pipeline_shader_stages.size()) .setPStages(mesh_pass_pipeline_shader_stages.data()) .setPVertexInputState(&vertex_input_state) .setPInputAssemblyState(&input_assembly_info) .setPViewportState(&viewport_info)

    .setPRasterizationState(&rasterization_info) .setPMultisampleState(&multisample_info) .setPDepthStencilState(&depth_stencil_info) .setPColorBlendState(&mesh_color_blend_info) .setPDynamicState(&dynamic_state_info) .setLayout(pipeline_layout) .setRenderPass(render_pass) .setSubpass(0), // (ུ) }; graphics_pipeline=device.createGraphicsPipelines( pipeline_cache,pipeline_create_info );
  61. const std::array<vk::ClearValue,4> clear_values{ vk::ClearColorValue( std::array<float,4>({{0.0f,0.0f,0.0f,1.0f}}) ), // (ུ) }; command_buffer[i].begin(

    vk::CommandBufferBeginInfo() .setFlags( vk::CommandBufferUsageFlagBits::eSimultaneousUse ) ); auto const pass_info= vk::RenderPassBeginInfo() .setRenderPass(render_pass) .setFramebuffer(framebuffers[i]) .setRenderArea(vk::Rect2D( vk::Offset2D(0,0),vk::Extent2D(width,height)) ) .setClearValueCount(clear_values.size()) .setPClearValues(clear_values.data()); ίϚϯυΛه࿥͢Δ ίϚϯυͷه࿥Λ։࢝
  62. vk::CommandBufferUsageFlagBits::eSimultaneousUse ) ); auto const pass_info= vk::RenderPassBeginInfo() .setRenderPass(render_pass) .setFramebuffer(framebuffers[i]) .setRenderArea(vk::Rect2D(

    vk::Offset2D(0,0),vk::Extent2D(width,height)) ) .setClearValueCount(clear_values.size()) .setPClearValues(clear_values.data()); command_buffer[i].beginRenderPass( &pass_info,vk::SubpassContents::eInline ); command_buffer[i].bindPipeline( vk::PipelineBindPoint::eGraphics,graphics_pipeline[0] ); std::vector<uint32_t> ds_offset{0}; command_buffer[i].bindDescriptorSets( vk::PipelineBindPoint::eGraphics,pipeline_layout,0, descriptor_set[ i ], ds_offset ); ίϚϯυΛه࿥͢Δ ϨϯμʔύεΛ։࢝
  63. .setFramebuffer(framebuffers[i]) .setRenderArea(vk::Rect2D( vk::Offset2D(0,0),vk::Extent2D(width,height)) ) .setClearValueCount(clear_values.size()) .setPClearValues(clear_values.data()); command_buffer[i].beginRenderPass( &pass_info,vk::SubpassContents::eInline ); command_buffer[i].bindPipeline(

    vk::PipelineBindPoint::eGraphics,graphics_pipeline[0] ); std::vector<uint32_t> ds_offset{0}; command_buffer[i].bindDescriptorSets( vk::PipelineBindPoint::eGraphics,pipeline_layout,0, descriptor_set[ i ], ds_offset ); ίϚϯυΛه࿥͢Δ ύΠϓϥΠϯͱ σεΫϦϓληοτΛ CJOE
  64. command_buffer[i].pushConstants( pipeline_layout,vk::ShaderStageFlagBits::eVertex, 0,sizeof(glm::mat4), &scene_.get_matrices()[offset.matrix] ); command_buffer[i].pushConstants( pipeline_layout,vk::ShaderStageFlagBits::eVertex, sizeof(glm::mat4),sizeof(glm::mat4), &scene_.get_cameras()[0] );

    std::vector<vk::DeviceSize> vb_offsets{ offset.vertex_begin*sizeof(vertex_t) }; command_buffer[i].bindVertexBuffers(0,vb,vb_offsets); command_buffer[i].draw(offset.vertex_count,1,0,0); ίϚϯυΛه࿥͢Δ ࠲ඪม׵༻ͷߦྻΛॻ͍ͯ ௖఺όοϑΝΛCJOEͯ͠ %SBXίʔϧ
  65. auto &fence=fences[current_frame]; device.waitForFences(1,&fence,VK_TRUE,UINT64_MAX); device.resetFences(1,&fence); auto image_index=device.acquireNextImageKHR( swapchain,UINT64_MAX, image_acquired_semaphores[current_frame], vk::Fence() );

    auto &image=swapchain_images[image_index.value]; vk::PipelineStageFlags const pipe_stage_flags= vk::PipelineStageFlagBits::eColorAttachmentOutput; const auto submit_info=vk::SubmitInfo() .setPWaitDstStageMask(&pipe_stage_flags) .setWaitSemaphoreCount(1) .setPWaitSemaphores(&image_acquired_semaphores[current_frame]) .setCommandBufferCount(1) .setPCommandBuffers(&command_buffer[image_index.value]) .setSignalSemaphoreCount(1) .setPSignalSemaphores( &draw_complete_semaphores[current_frame] ); graphics_queue.submit(1,&submit_info,fences[current_frame]); ΩϡʔʹίϚϯυΛྲྀ͢ εϫοϓνΣΠϯ͔Β දࣔதͰ΋ඳըதͰ΋ͳ͍ΠϝʔδΛ΋Β͏
  66. vk::Fence() ); auto &image=swapchain_images[image_index.value]; vk::PipelineStageFlags const pipe_stage_flags= vk::PipelineStageFlagBits::eColorAttachmentOutput; const auto

    submit_info=vk::SubmitInfo() .setPWaitDstStageMask(&pipe_stage_flags) .setWaitSemaphoreCount(1) .setPWaitSemaphores(&image_acquired_semaphores[current_frame]) .setCommandBufferCount(1) .setPCommandBuffers(&command_buffer[image_index.value]) .setSignalSemaphoreCount(1) .setPSignalSemaphores( &draw_complete_semaphores[current_frame] ); graphics_queue.submit(1,&submit_info,fences[current_frame]); auto const presentInfo=vk::PresentInfoKHR() .setWaitSemaphoreCount(1) .setPWaitSemaphores(&draw_complete_semaphores[current_frame]) .setSwapchainCount(1) .setPSwapchains(&swapchain) .setPImageIndices(&image_index.value); present_queue.presentKHR(&presentInfo); ΩϡʔʹίϚϯυΛྲྀ͢ ίϚϯυόοϑΝΛΩϡʔʹsubmit͢Δ submit͸ඳըͷ׬ྃΛ଴ͨͣʹฦΔ͕ fenceΛ౉͓͚ͯ͠͹ ඳը׬ྃ࣌ʹγάφϧΛड͚औΔfenceʹͳΔ
  67. vk::Fence() ); auto &image=swapchain_images[image_index.value]; vk::PipelineStageFlags const pipe_stage_flags= vk::PipelineStageFlagBits::eColorAttachmentOutput; const auto

    submit_info=vk::SubmitInfo() .setPWaitDstStageMask(&pipe_stage_flags) .setWaitSemaphoreCount(1) .setPWaitSemaphores(&image_acquired_semaphores[current_frame]) .setCommandBufferCount(1) .setPCommandBuffers(&command_buffer[image_index.value]) .setSignalSemaphoreCount(1) .setPSignalSemaphores( &draw_complete_semaphores[current_frame] ); graphics_queue.submit(1,&submit_info,fences[current_frame]); auto const presentInfo=vk::PresentInfoKHR() .setWaitSemaphoreCount(1) .setPWaitSemaphores(&draw_complete_semaphores[current_frame]) .setSwapchainCount(1) .setPSwapchains(&swapchain) .setPImageIndices(&image_index.value); present_queue.presentKHR(&presentInfo); ΩϡʔʹίϚϯυΛྲྀ͢ ηϚϑΥͰඳը׬ྃΛ଴ͬͯ ΠϝʔδΛදࣔՄೳʹ͢Δ