3636#endif
3737
3838// #define APP_USE_UNLIMITED_FRAME_RATE
39+ // #define APP_USE_DYNAMIC_RENDERING // Uncomment to use Vulkan dynamic rendering (requires Vulkan 1.3 or VK_KHR_dynamic_rendering)
3940#ifdef _DEBUG
4041#define APP_USE_VULKAN_DEBUG_REPORT
4142static VkDebugReportCallbackEXT g_DebugReport = VK_NULL_HANDLE ;
@@ -50,6 +51,10 @@ static uint32_t g_QueueFamily = (uint32_t)-1;
5051static VkQueue g_Queue = VK_NULL_HANDLE ;
5152static VkPipelineCache g_PipelineCache = VK_NULL_HANDLE ;
5253static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE ;
54+ #ifdef APP_USE_DYNAMIC_RENDERING
55+ static PFN_vkCmdBeginRenderingKHR g_vkCmdBeginRendering = nullptr ;
56+ static PFN_vkCmdEndRenderingKHR g_vkCmdEndRendering = nullptr ;
57+ #endif
5358
5459static ImGui_ImplVulkanH_Window g_MainWindowData;
5560static uint32_t g_MinImageCount = 2 ;
@@ -68,6 +73,19 @@ static void check_vk_result(VkResult err)
6873 abort ();
6974}
7075
76+ #ifdef APP_USE_DYNAMIC_RENDERING
77+ static void LoadDynamicRenderingFunctions ()
78+ {
79+ g_vkCmdBeginRendering = reinterpret_cast <PFN_vkCmdBeginRenderingKHR>(vkGetDeviceProcAddr (g_Device, " vkCmdBeginRendering" ));
80+ g_vkCmdEndRendering = reinterpret_cast <PFN_vkCmdEndRenderingKHR>(vkGetDeviceProcAddr (g_Device, " vkCmdEndRendering" ));
81+ if (g_vkCmdBeginRendering == nullptr || g_vkCmdEndRendering == nullptr )
82+ {
83+ g_vkCmdBeginRendering = reinterpret_cast <PFN_vkCmdBeginRenderingKHR>(vkGetDeviceProcAddr (g_Device, " vkCmdBeginRenderingKHR" ));
84+ g_vkCmdEndRendering = reinterpret_cast <PFN_vkCmdEndRenderingKHR>(vkGetDeviceProcAddr (g_Device, " vkCmdEndRenderingKHR" ));
85+ }
86+ }
87+ #endif
88+
7189#ifdef APP_USE_VULKAN_DEBUG_REPORT
7290static VKAPI_ATTR VkBool32 VKAPI_CALL debug_report (VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char * pLayerPrefix, const char * pMessage, void * pUserData)
7391{
@@ -158,7 +176,14 @@ static void SetupVulkan(ImVector<const char*> instance_extensions)
158176 // Create Logical Device (with 1 queue)
159177 {
160178 ImVector<const char *> device_extensions;
161- device_extensions.push_back (" VK_KHR_swapchain" );
179+ device_extensions.push_back (VK_KHR_SWAPCHAIN_EXTENSION_NAME );
180+ #ifdef APP_USE_DYNAMIC_RENDERING
181+ device_extensions.push_back (VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME );
182+ device_extensions.push_back (VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME );
183+ device_extensions.push_back (VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME );
184+ device_extensions.push_back (VK_KHR_MAINTENANCE2_EXTENSION_NAME );
185+ device_extensions.push_back (VK_KHR_MULTIVIEW_EXTENSION_NAME );
186+ #endif
162187
163188 // Enumerate physical device extension
164189 uint32_t properties_count;
@@ -179,13 +204,23 @@ static void SetupVulkan(ImVector<const char*> instance_extensions)
179204 queue_info[0 ].pQueuePriorities = queue_priority;
180205 VkDeviceCreateInfo create_info = {};
181206 create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO ;
207+ #ifdef APP_USE_DYNAMIC_RENDERING
208+ VkPhysicalDeviceDynamicRenderingFeaturesKHR physicalDeviceDynamicRenderingFeaturesKHR{};
209+ physicalDeviceDynamicRenderingFeaturesKHR.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES_KHR ;
210+ physicalDeviceDynamicRenderingFeaturesKHR.pNext = nullptr ;
211+ physicalDeviceDynamicRenderingFeaturesKHR.dynamicRendering = VK_TRUE ;
212+ create_info.pNext = &physicalDeviceDynamicRenderingFeaturesKHR;
213+ #endif
182214 create_info.queueCreateInfoCount = sizeof (queue_info) / sizeof (queue_info[0 ]);
183215 create_info.pQueueCreateInfos = queue_info;
184216 create_info.enabledExtensionCount = (uint32_t )device_extensions.Size ;
185217 create_info.ppEnabledExtensionNames = device_extensions.Data ;
186218 err = vkCreateDevice (g_PhysicalDevice, &create_info, g_Allocator, &g_Device);
187219 check_vk_result (err);
188220 vkGetDeviceQueue (g_Device, g_QueueFamily, 0 , &g_Queue);
221+ #ifdef APP_USE_DYNAMIC_RENDERING
222+ LoadDynamicRenderingFunctions ();
223+ #endif
189224 }
190225
191226 // Create Descriptor Pool
@@ -238,6 +273,9 @@ static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface
238273
239274 // Create SwapChain, RenderPass, Framebuffer, etc.
240275 IM_ASSERT (g_MinImageCount >= 2 );
276+ #ifdef APP_USE_DYNAMIC_RENDERING
277+ wd->UseDynamicRendering = true ;
278+ #endif
241279 ImGui_ImplVulkanH_CreateOrResizeWindow (g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount, 0 );
242280}
243281
@@ -290,6 +328,43 @@ static void FrameRender(ImGui_ImplVulkanH_Window* wd, ImDrawData* draw_data)
290328 err = vkBeginCommandBuffer (fd->CommandBuffer , &info);
291329 check_vk_result (err);
292330 }
331+ #ifdef APP_USE_DYNAMIC_RENDERING
332+ if (wd->UseDynamicRendering )
333+ {
334+ VkImageMemoryBarrier barrier = {};
335+ barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER ;
336+ barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT ;
337+ barrier.oldLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR ;
338+ barrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ;
339+ barrier.image = fd->Backbuffer ;
340+ barrier.subresourceRange .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT ;
341+ barrier.subresourceRange .levelCount = 1 ;
342+ barrier.subresourceRange .layerCount = 1 ;
343+ vkCmdPipelineBarrier (fd->CommandBuffer , VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_NONE , VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT , 0 , 0 , nullptr , 0 , nullptr , 1 , &barrier);
344+
345+ VkRenderingAttachmentInfo attachmentInfo = {};
346+ attachmentInfo.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR ;
347+ attachmentInfo.imageView = fd->BackbufferView ;
348+ attachmentInfo.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ;
349+ attachmentInfo.resolveMode = VK_RESOLVE_MODE_NONE ;
350+ attachmentInfo.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR ;
351+ attachmentInfo.storeOp = VK_ATTACHMENT_STORE_OP_STORE ;
352+ attachmentInfo.clearValue = wd->ClearValue ;
353+
354+ VkRenderingInfo renderingInfo = {};
355+ renderingInfo.sType = VK_STRUCTURE_TYPE_RENDERING_INFO_KHR ;
356+ renderingInfo.renderArea .extent .width = wd->Width ;
357+ renderingInfo.renderArea .extent .height = wd->Height ;
358+ renderingInfo.layerCount = 1 ;
359+ renderingInfo.viewMask = 0 ;
360+ renderingInfo.colorAttachmentCount = 1 ;
361+ renderingInfo.pColorAttachments = &attachmentInfo;
362+
363+ IM_ASSERT (g_vkCmdBeginRendering != nullptr );
364+ g_vkCmdBeginRendering (fd->CommandBuffer , &renderingInfo);
365+ }
366+ else
367+ #endif
293368 {
294369 VkRenderPassBeginInfo info = {};
295370 info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO ;
@@ -306,7 +381,30 @@ static void FrameRender(ImGui_ImplVulkanH_Window* wd, ImDrawData* draw_data)
306381 ImGui_ImplVulkan_RenderDrawData (draw_data, fd->CommandBuffer );
307382
308383 // Submit command buffer
309- vkCmdEndRenderPass (fd->CommandBuffer );
384+ #ifdef APP_USE_DYNAMIC_RENDERING
385+ if (wd->UseDynamicRendering )
386+ {
387+ IM_ASSERT (g_vkCmdEndRendering != nullptr );
388+ g_vkCmdEndRendering (fd->CommandBuffer );
389+
390+ // Transition image to a layout suitable for presentation
391+ VkImageMemoryBarrier barrier = {};
392+ barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER ;
393+ barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT ;
394+ barrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ;
395+ barrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR ;
396+ barrier.image = fd->Backbuffer ;
397+ barrier.subresourceRange .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT ;
398+ barrier.subresourceRange .levelCount = 1 ;
399+ barrier.subresourceRange .layerCount = 1 ;
400+ vkCmdPipelineBarrier (fd->CommandBuffer , VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT , VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT , 0 , 0 , nullptr , 0 , nullptr , 1 , &barrier);
401+ }
402+ else
403+ #endif
404+ {
405+ // Submit command buffer
406+ vkCmdEndRenderPass (fd->CommandBuffer );
407+ }
310408 {
311409 VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT ;
312410 VkSubmitInfo info = {};
@@ -426,9 +524,23 @@ int main(int, char**)
426524 init_info.MinImageCount = g_MinImageCount;
427525 init_info.ImageCount = wd->ImageCount ;
428526 init_info.Allocator = g_Allocator;
527+ #ifdef APP_USE_DYNAMIC_RENDERING
528+ VkFormat color_attachment_format = wd->SurfaceFormat .format ;
529+ VkPipelineRenderingCreateInfo pipeline_rendering_create_info = {};
530+ pipeline_rendering_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO ;
531+ pipeline_rendering_create_info.pNext = nullptr ;
532+ pipeline_rendering_create_info.colorAttachmentCount = 1 ;
533+ pipeline_rendering_create_info.pColorAttachmentFormats = &color_attachment_format;
534+ init_info.UseDynamicRendering = true ;
535+ init_info.PipelineInfoMain .PipelineRenderingCreateInfo = pipeline_rendering_create_info;
536+ init_info.PipelineInfoMain .MSAASamples = VK_SAMPLE_COUNT_1_BIT ;
537+ init_info.PipelineInfoForViewports .PipelineRenderingCreateInfo = pipeline_rendering_create_info;
538+ init_info.PipelineInfoForViewports .MSAASamples = VK_SAMPLE_COUNT_1_BIT ;
539+ #else
429540 init_info.PipelineInfoMain .RenderPass = wd->RenderPass ;
430541 init_info.PipelineInfoMain .Subpass = 0 ;
431542 init_info.PipelineInfoMain .MSAASamples = VK_SAMPLE_COUNT_1_BIT ;
543+ #endif
432544 init_info.CheckVkResultFn = check_vk_result;
433545 ImGui_ImplVulkan_Init (&init_info);
434546
0 commit comments