From 99e95eebb14fa987906b6f47c65c4ccd4bb596bc Mon Sep 17 00:00:00 2001 From: CamilleLaVey Date: Thu, 9 Jul 2026 02:18:00 -0400 Subject: [PATCH] [vulkan] Initial dynamic rendering implementation --- src/video_core/renderer_vulkan/blit_image.cpp | 124 +++++++++++++----- src/video_core/renderer_vulkan/blit_image.h | 28 ++-- .../renderer_vulkan/vk_graphics_pipeline.cpp | 45 ++++++- .../renderer_vulkan/vk_rasterizer.cpp | 1 + .../renderer_vulkan/vk_scheduler.cpp | 63 ++++++++- src/video_core/renderer_vulkan/vk_scheduler.h | 4 +- .../renderer_vulkan/vk_texture_cache.cpp | 70 +++++++++- .../renderer_vulkan/vk_texture_cache.h | 32 +++++ .../vulkan_common/vulkan_device.cpp | 5 + src/video_core/vulkan_common/vulkan_device.h | 6 + .../vulkan_common/vulkan_wrapper.cpp | 8 ++ src/video_core/vulkan_common/vulkan_wrapper.h | 10 ++ 12 files changed, 339 insertions(+), 57 deletions(-) diff --git a/src/video_core/renderer_vulkan/blit_image.cpp b/src/video_core/renderer_vulkan/blit_image.cpp index 89083d29fb..079dee53a5 100644 --- a/src/video_core/renderer_vulkan/blit_image.cpp +++ b/src/video_core/renderer_vulkan/blit_image.cpp @@ -545,6 +545,10 @@ void RecordShaderReadBarrier(Scheduler& scheduler, const ImageView& image_view) void BeginRenderPass(vk::CommandBuffer& cmdbuf, const Framebuffer* framebuffer) { const VkRenderPass render_pass = framebuffer->RenderPass(); + if (!render_pass) { + framebuffer->BeginRendering(cmdbuf); + return; + } const VkFramebuffer framebuffer_handle = framebuffer->Handle(); const VkExtent2D render_area = framebuffer->RenderArea(); const VkRenderPassBeginInfo renderpass_bi{ @@ -561,6 +565,31 @@ void BeginRenderPass(vk::CommandBuffer& cmdbuf, const Framebuffer* framebuffer) }; cmdbuf.BeginRenderPass(renderpass_bi, VK_SUBPASS_CONTENTS_INLINE); } + +void EndRenderPass(vk::CommandBuffer& cmdbuf, const Framebuffer* framebuffer) { + if (framebuffer->RenderPass()) { + cmdbuf.EndRenderPass(); + } else { + cmdbuf.EndRendering(); + } +} + +[[nodiscard]] VkPipelineRenderingCreateInfo MakePipelineRenderingCreateInfo( + const Framebuffer* framebuffer) { + return VkPipelineRenderingCreateInfo{ + .sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO, + .pNext = nullptr, + .viewMask = 0, + .colorAttachmentCount = framebuffer->NumColorAttachments(), + .pColorAttachmentFormats = framebuffer->ColorAttachmentFormats().data(), + .depthAttachmentFormat = framebuffer->HasAspectDepthBit() + ? framebuffer->DepthAttachmentFormat() + : VK_FORMAT_UNDEFINED, + .stencilAttachmentFormat = framebuffer->HasAspectStencilBit() + ? framebuffer->DepthAttachmentFormat() + : VK_FORMAT_UNDEFINED, + }; +} } // Anonymous namespace BlitImageHelper::BlitImageHelper(const Device& device_, Scheduler& scheduler_, @@ -623,10 +652,12 @@ void BlitImageHelper::BlitColor(const Framebuffer* dst_framebuffer, const ImageV const BlitImagePipelineKey key{ .renderpass = dst_framebuffer->RenderPass(), .operation = operation, + .color_formats = dst_framebuffer->ColorAttachmentFormats(), + .depth_format = dst_framebuffer->DepthAttachmentFormat(), }; const VkPipelineLayout layout = *one_texture_pipeline_layout; const VkSampler sampler = is_linear ? *linear_sampler : *nearest_sampler; - const VkPipeline pipeline = FindOrEmplaceColorPipeline(key); + const VkPipeline pipeline = FindOrEmplaceColorPipeline(key, dst_framebuffer); const VkImageView src_view = src_image_view.Handle(Shader::TextureType::Color2D); RecordShaderReadBarrier(scheduler, src_image_view); @@ -651,9 +682,11 @@ void BlitImageHelper::BlitColor(const Framebuffer* dst_framebuffer, VkImageView const BlitImagePipelineKey key{ .renderpass = dst_framebuffer->RenderPass(), .operation = Tegra::Engines::Fermi2D::Operation::SrcCopy, + .color_formats = dst_framebuffer->ColorAttachmentFormats(), + .depth_format = dst_framebuffer->DepthAttachmentFormat(), }; const VkPipelineLayout layout = *one_texture_pipeline_layout; - const VkPipeline pipeline = FindOrEmplaceColorPipeline(key); + const VkPipeline pipeline = FindOrEmplaceColorPipeline(key, dst_framebuffer); scheduler.RequestOutsideRenderPassOperationContext(); scheduler.Record([this, dst_framebuffer, src_image_view, src_image, src_sampler, dst_region, src_region, src_size, pipeline, layout](vk::CommandBuffer cmdbuf) { @@ -666,7 +699,7 @@ void BlitImageHelper::BlitColor(const Framebuffer* dst_framebuffer, VkImageView nullptr); BindBlitState(cmdbuf, layout, dst_region, src_region, src_size); cmdbuf.Draw(3, 1, 0, 0); - cmdbuf.EndRenderPass(); + EndRenderPass(cmdbuf, dst_framebuffer); }); } @@ -747,10 +780,12 @@ void BlitImageHelper::BlitDepthStencil(const Framebuffer* dst_framebuffer, const BlitImagePipelineKey key{ .renderpass = dst_framebuffer->RenderPass(), .operation = operation, + .color_formats = dst_framebuffer->ColorAttachmentFormats(), + .depth_format = dst_framebuffer->DepthAttachmentFormat(), }; const VkPipelineLayout layout = *two_textures_pipeline_layout; const VkSampler sampler = *nearest_sampler; - const VkPipeline pipeline = FindOrEmplaceDepthStencilPipeline(key); + const VkPipeline pipeline = FindOrEmplaceDepthStencilPipeline(key, dst_framebuffer); const VkImageView src_depth_view = src_image_view.DepthView(); const VkImageView src_stencil_view = src_image_view.StencilView(); @@ -772,25 +807,25 @@ void BlitImageHelper::BlitDepthStencil(const Framebuffer* dst_framebuffer, void BlitImageHelper::ConvertD32ToR32(const Framebuffer* dst_framebuffer, const ImageView& src_image_view) { - ConvertDepthToColorPipeline(convert_d32_to_r32_pipeline, dst_framebuffer->RenderPass()); + ConvertDepthToColorPipeline(convert_d32_to_r32_pipeline, dst_framebuffer); Convert(*convert_d32_to_r32_pipeline, dst_framebuffer, src_image_view); } void BlitImageHelper::ConvertR32ToD32(const Framebuffer* dst_framebuffer, const ImageView& src_image_view) { - ConvertColorToDepthPipeline(convert_r32_to_d32_pipeline, dst_framebuffer->RenderPass()); + ConvertColorToDepthPipeline(convert_r32_to_d32_pipeline, dst_framebuffer); Convert(*convert_r32_to_d32_pipeline, dst_framebuffer, src_image_view); } void BlitImageHelper::ConvertD16ToR16(const Framebuffer* dst_framebuffer, const ImageView& src_image_view) { - ConvertDepthToColorPipeline(convert_d16_to_r16_pipeline, dst_framebuffer->RenderPass()); + ConvertDepthToColorPipeline(convert_d16_to_r16_pipeline, dst_framebuffer); Convert(*convert_d16_to_r16_pipeline, dst_framebuffer, src_image_view); } void BlitImageHelper::ConvertR16ToD16(const Framebuffer* dst_framebuffer, const ImageView& src_image_view) { - ConvertColorToDepthPipeline(convert_r16_to_d16_pipeline, dst_framebuffer->RenderPass()); + ConvertColorToDepthPipeline(convert_r16_to_d16_pipeline, dst_framebuffer); Convert(*convert_r16_to_d16_pipeline, dst_framebuffer, src_image_view); } @@ -801,35 +836,35 @@ void BlitImageHelper::ConvertABGR8ToD24S8(const Framebuffer* dst_framebuffer, LOG_WARNING(Render_Vulkan, "ConvertABGR8ToD24S8 requires shader_stencil_export, skipping"); return; } - ConvertPipelineDepthTargetEx(convert_abgr8_to_d24s8_pipeline, dst_framebuffer->RenderPass(), + ConvertPipelineDepthTargetEx(convert_abgr8_to_d24s8_pipeline, dst_framebuffer, convert_abgr8_to_d24s8_frag); Convert(*convert_abgr8_to_d24s8_pipeline, dst_framebuffer, src_image_view); } void BlitImageHelper::ConvertABGR8ToD32F(const Framebuffer* dst_framebuffer, const ImageView& src_image_view) { - ConvertPipelineDepthTargetEx(convert_abgr8_to_d32f_pipeline, dst_framebuffer->RenderPass(), + ConvertPipelineDepthTargetEx(convert_abgr8_to_d32f_pipeline, dst_framebuffer, convert_abgr8_to_d32f_frag); Convert(*convert_abgr8_to_d32f_pipeline, dst_framebuffer, src_image_view); } void BlitImageHelper::ConvertD32FToABGR8(const Framebuffer* dst_framebuffer, ImageView& src_image_view) { - ConvertPipelineColorTargetEx(convert_d32f_to_abgr8_pipeline, dst_framebuffer->RenderPass(), + ConvertPipelineColorTargetEx(convert_d32f_to_abgr8_pipeline, dst_framebuffer, convert_d32f_to_abgr8_frag); ConvertDepthStencil(*convert_d32f_to_abgr8_pipeline, dst_framebuffer, src_image_view); } void BlitImageHelper::ConvertD24S8ToABGR8(const Framebuffer* dst_framebuffer, ImageView& src_image_view) { - ConvertPipelineColorTargetEx(convert_d24s8_to_abgr8_pipeline, dst_framebuffer->RenderPass(), + ConvertPipelineColorTargetEx(convert_d24s8_to_abgr8_pipeline, dst_framebuffer, convert_d24s8_to_abgr8_frag); ConvertDepthStencil(*convert_d24s8_to_abgr8_pipeline, dst_framebuffer, src_image_view); } void BlitImageHelper::ConvertS8D24ToABGR8(const Framebuffer* dst_framebuffer, ImageView& src_image_view) { - ConvertPipelineColorTargetEx(convert_s8d24_to_abgr8_pipeline, dst_framebuffer->RenderPass(), + ConvertPipelineColorTargetEx(convert_s8d24_to_abgr8_pipeline, dst_framebuffer, convert_s8d24_to_abgr8_frag); ConvertDepthStencil(*convert_s8d24_to_abgr8_pipeline, dst_framebuffer, src_image_view); } @@ -840,8 +875,10 @@ void BlitImageHelper::ClearColor(const Framebuffer* dst_framebuffer, u8 color_ma const BlitImagePipelineKey key{ .renderpass = dst_framebuffer->RenderPass(), .operation = Tegra::Engines::Fermi2D::Operation::BlendPremult, + .color_formats = dst_framebuffer->ColorAttachmentFormats(), + .depth_format = dst_framebuffer->DepthAttachmentFormat(), }; - const VkPipeline pipeline = FindOrEmplaceClearColorPipeline(key); + const VkPipeline pipeline = FindOrEmplaceClearColorPipeline(key, dst_framebuffer); const VkPipelineLayout layout = *clear_color_pipeline_layout; scheduler.RequestRenderpass(dst_framebuffer); scheduler.Record( @@ -867,8 +904,10 @@ void BlitImageHelper::ClearDepthStencil(const Framebuffer* dst_framebuffer, bool .stencil_mask = stencil_mask, .stencil_compare_mask = stencil_compare_mask, .stencil_ref = stencil_ref, + .color_formats = dst_framebuffer->ColorAttachmentFormats(), + .depth_format = dst_framebuffer->DepthAttachmentFormat(), }; - const VkPipeline pipeline = FindOrEmplaceClearStencilPipeline(key); + const VkPipeline pipeline = FindOrEmplaceClearStencilPipeline(key, dst_framebuffer); const VkPipelineLayout layout = *clear_color_pipeline_layout; scheduler.RequestRenderpass(dst_framebuffer); scheduler.Record([pipeline, layout, clear_depth, dst_region](vk::CommandBuffer cmdbuf) { @@ -1140,12 +1179,14 @@ void BlitImageHelper::ConvertDepthStencil(VkPipeline pipeline, const Framebuffer scheduler.InvalidateState(); } -VkPipeline BlitImageHelper::FindOrEmplaceColorPipeline(const BlitImagePipelineKey& key) { +VkPipeline BlitImageHelper::FindOrEmplaceColorPipeline(const BlitImagePipelineKey& key, + const Framebuffer* framebuffer) { const auto it = std::ranges::find(blit_color_keys, key); if (it != blit_color_keys.end()) { return *blit_color_pipelines[std::distance(blit_color_keys.begin(), it)]; } blit_color_keys.push_back(key); + const VkPipelineRenderingCreateInfo rendering_ci = MakePipelineRenderingCreateInfo(framebuffer); const std::array stages = MakeStages(*full_screen_vert, *blit_color_to_color_frag); const VkPipelineColorBlendAttachmentState blend_attachment{ @@ -1173,7 +1214,7 @@ VkPipeline BlitImageHelper::FindOrEmplaceColorPipeline(const BlitImagePipelineKe const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device); blit_color_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({ .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, - .pNext = nullptr, + .pNext = key.renderpass ? nullptr : &rendering_ci, .flags = 0, .stageCount = static_cast(stages.size()), .pStages = stages.data(), @@ -1195,17 +1236,19 @@ VkPipeline BlitImageHelper::FindOrEmplaceColorPipeline(const BlitImagePipelineKe return *blit_color_pipelines.back(); } -VkPipeline BlitImageHelper::FindOrEmplaceDepthStencilPipeline(const BlitImagePipelineKey& key) { +VkPipeline BlitImageHelper::FindOrEmplaceDepthStencilPipeline(const BlitImagePipelineKey& key, + const Framebuffer* framebuffer) { const auto it = std::ranges::find(blit_depth_stencil_keys, key); if (it != blit_depth_stencil_keys.end()) { return *blit_depth_stencil_pipelines[std::distance(blit_depth_stencil_keys.begin(), it)]; } blit_depth_stencil_keys.push_back(key); + const VkPipelineRenderingCreateInfo rendering_ci = MakePipelineRenderingCreateInfo(framebuffer); const std::array stages = MakeStages(*full_screen_vert, *blit_depth_stencil_frag); const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device); blit_depth_stencil_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({ .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, - .pNext = nullptr, + .pNext = key.renderpass ? nullptr : &rendering_ci, .flags = 0, .stageCount = static_cast(stages.size()), .pStages = stages.data(), @@ -1227,12 +1270,14 @@ VkPipeline BlitImageHelper::FindOrEmplaceDepthStencilPipeline(const BlitImagePip return *blit_depth_stencil_pipelines.back(); } -VkPipeline BlitImageHelper::FindOrEmplaceClearColorPipeline(const BlitImagePipelineKey& key) { +VkPipeline BlitImageHelper::FindOrEmplaceClearColorPipeline(const BlitImagePipelineKey& key, + const Framebuffer* framebuffer) { const auto it = std::ranges::find(clear_color_keys, key); if (it != clear_color_keys.end()) { return *clear_color_pipelines[std::distance(clear_color_keys.begin(), it)]; } clear_color_keys.push_back(key); + const VkPipelineRenderingCreateInfo rendering_ci = MakePipelineRenderingCreateInfo(framebuffer); const std::array stages = MakeStages(*clear_color_vert, *clear_color_frag); const VkPipelineColorBlendAttachmentState color_blend_attachment_state{ .blendEnable = VK_TRUE, @@ -1258,7 +1303,7 @@ VkPipeline BlitImageHelper::FindOrEmplaceClearColorPipeline(const BlitImagePipel const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device); clear_color_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({ .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, - .pNext = nullptr, + .pNext = key.renderpass ? nullptr : &rendering_ci, .flags = 0, .stageCount = static_cast(stages.size()), .pStages = stages.data(), @@ -1281,12 +1326,13 @@ VkPipeline BlitImageHelper::FindOrEmplaceClearColorPipeline(const BlitImagePipel } VkPipeline BlitImageHelper::FindOrEmplaceClearStencilPipeline( - const BlitDepthStencilPipelineKey& key) { + const BlitDepthStencilPipelineKey& key, const Framebuffer* framebuffer) { const auto it = std::ranges::find(clear_stencil_keys, key); if (it != clear_stencil_keys.end()) { return *clear_stencil_pipelines[std::distance(clear_stencil_keys.begin(), it)]; } clear_stencil_keys.push_back(key); + const VkPipelineRenderingCreateInfo rendering_ci = MakePipelineRenderingCreateInfo(framebuffer); const std::array stages = MakeStages(*clear_color_vert, *clear_stencil_frag); const auto stencil = VkStencilOpState{ .failOp = VK_STENCIL_OP_KEEP, @@ -1314,7 +1360,7 @@ VkPipeline BlitImageHelper::FindOrEmplaceClearStencilPipeline( const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device); clear_stencil_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({ .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, - .pNext = nullptr, + .pNext = key.renderpass ? nullptr : &rendering_ci, .flags = 0, .stageCount = static_cast(stages.size()), .pStages = stages.data(), @@ -1462,25 +1508,29 @@ VkPipeline BlitImageHelper::FindOrEmplaceMSAACopyPipeline(const MSAACopyPipeline return *msaa_copy_pipelines.back(); } -void BlitImageHelper::ConvertDepthToColorPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass) { - ConvertPipeline(pipeline, renderpass, false); +void BlitImageHelper::ConvertDepthToColorPipeline(vk::Pipeline& pipeline, + const Framebuffer* framebuffer) { + ConvertPipeline(pipeline, framebuffer, false); } -void BlitImageHelper::ConvertColorToDepthPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass) { - ConvertPipeline(pipeline, renderpass, true); +void BlitImageHelper::ConvertColorToDepthPipeline(vk::Pipeline& pipeline, + const Framebuffer* framebuffer) { + ConvertPipeline(pipeline, framebuffer, true); } -void BlitImageHelper::ConvertPipelineEx(vk::Pipeline& pipeline, VkRenderPass renderpass, +void BlitImageHelper::ConvertPipelineEx(vk::Pipeline& pipeline, const Framebuffer* framebuffer, vk::ShaderModule& module, bool single_texture, bool is_target_depth) { if (pipeline) { return; } + const VkRenderPass renderpass = framebuffer->RenderPass(); + const VkPipelineRenderingCreateInfo rendering_ci = MakePipelineRenderingCreateInfo(framebuffer); const std::array stages = MakeStages(*full_screen_vert, *module); const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device); pipeline = device.GetLogical().CreateGraphicsPipeline(VkGraphicsPipelineCreateInfo{ .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, - .pNext = nullptr, + .pNext = renderpass ? nullptr : &rendering_ci, .flags = 0, .stageCount = static_cast(stages.size()), .pStages = stages.data(), @@ -1502,28 +1552,32 @@ void BlitImageHelper::ConvertPipelineEx(vk::Pipeline& pipeline, VkRenderPass ren }); } -void BlitImageHelper::ConvertPipelineColorTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass, +void BlitImageHelper::ConvertPipelineColorTargetEx(vk::Pipeline& pipeline, + const Framebuffer* framebuffer, vk::ShaderModule& module) { - ConvertPipelineEx(pipeline, renderpass, module, false, false); + ConvertPipelineEx(pipeline, framebuffer, module, false, false); } -void BlitImageHelper::ConvertPipelineDepthTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass, +void BlitImageHelper::ConvertPipelineDepthTargetEx(vk::Pipeline& pipeline, + const Framebuffer* framebuffer, vk::ShaderModule& module) { - ConvertPipelineEx(pipeline, renderpass, module, true, true); + ConvertPipelineEx(pipeline, framebuffer, module, true, true); } -void BlitImageHelper::ConvertPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass, +void BlitImageHelper::ConvertPipeline(vk::Pipeline& pipeline, const Framebuffer* framebuffer, bool is_target_depth) { if (pipeline) { return; } + const VkRenderPass renderpass = framebuffer->RenderPass(); + const VkPipelineRenderingCreateInfo rendering_ci = MakePipelineRenderingCreateInfo(framebuffer); VkShaderModule frag_shader = is_target_depth ? *convert_float_to_depth_frag : *convert_depth_to_float_frag; const std::array stages = MakeStages(*full_screen_vert, frag_shader); const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device); pipeline = device.GetLogical().CreateGraphicsPipeline(VkGraphicsPipelineCreateInfo{ .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, - .pNext = nullptr, + .pNext = renderpass ? nullptr : &rendering_ci, .flags = 0, .stageCount = static_cast(stages.size()), .pStages = stages.data(), diff --git a/src/video_core/renderer_vulkan/blit_image.h b/src/video_core/renderer_vulkan/blit_image.h index 67294d594b..ea8f37a48f 100644 --- a/src/video_core/renderer_vulkan/blit_image.h +++ b/src/video_core/renderer_vulkan/blit_image.h @@ -33,6 +33,8 @@ struct BlitImagePipelineKey { VkRenderPass renderpass; Tegra::Engines::Fermi2D::Operation operation; + std::array color_formats; + VkFormat depth_format; }; struct BlitDepthStencilPipelineKey { @@ -43,6 +45,8 @@ struct BlitDepthStencilPipelineKey { u8 stencil_mask; u32 stencil_compare_mask; u32 stencil_ref; + std::array color_formats; + VkFormat depth_format; }; struct MSAACopyPipelineKey { @@ -123,31 +127,35 @@ private: void ConvertDepthStencil(VkPipeline pipeline, const Framebuffer* dst_framebuffer, ImageView& src_image_view); - [[nodiscard]] VkPipeline FindOrEmplaceColorPipeline(const BlitImagePipelineKey& key); + [[nodiscard]] VkPipeline FindOrEmplaceColorPipeline(const BlitImagePipelineKey& key, + const Framebuffer* framebuffer); - [[nodiscard]] VkPipeline FindOrEmplaceDepthStencilPipeline(const BlitImagePipelineKey& key); + [[nodiscard]] VkPipeline FindOrEmplaceDepthStencilPipeline(const BlitImagePipelineKey& key, + const Framebuffer* framebuffer); - [[nodiscard]] VkPipeline FindOrEmplaceClearColorPipeline(const BlitImagePipelineKey& key); + [[nodiscard]] VkPipeline FindOrEmplaceClearColorPipeline(const BlitImagePipelineKey& key, + const Framebuffer* framebuffer); [[nodiscard]] VkPipeline FindOrEmplaceClearStencilPipeline( - const BlitDepthStencilPipelineKey& key); + const BlitDepthStencilPipelineKey& key, const Framebuffer* framebuffer); [[nodiscard]] VkPipeline FindOrEmplaceMSAACopyPipeline(const MSAACopyPipelineKey& key); [[nodiscard]] VkPipeline FindOrEmplaceBlitColorMSAAPipeline(const BlitMSAAPipelineKey& key); [[nodiscard]] VkPipeline FindOrEmplaceResolveDepthStencilPipeline(VkRenderPass renderpass, bool resolve_stencil); - void ConvertPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass, bool is_target_depth); + void ConvertPipeline(vk::Pipeline& pipeline, const Framebuffer* framebuffer, + bool is_target_depth); - void ConvertDepthToColorPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass); + void ConvertDepthToColorPipeline(vk::Pipeline& pipeline, const Framebuffer* framebuffer); - void ConvertColorToDepthPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass); + void ConvertColorToDepthPipeline(vk::Pipeline& pipeline, const Framebuffer* framebuffer); - void ConvertPipelineEx(vk::Pipeline& pipeline, VkRenderPass renderpass, + void ConvertPipelineEx(vk::Pipeline& pipeline, const Framebuffer* framebuffer, vk::ShaderModule& module, bool single_texture, bool is_target_depth); - void ConvertPipelineColorTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass, + void ConvertPipelineColorTargetEx(vk::Pipeline& pipeline, const Framebuffer* framebuffer, vk::ShaderModule& module); - void ConvertPipelineDepthTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass, + void ConvertPipelineDepthTargetEx(vk::Pipeline& pipeline, const Framebuffer* framebuffer, vk::ShaderModule& module); const Device& device; diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index 757e0f3ccf..9815157b97 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp @@ -290,7 +290,10 @@ GraphicsPipeline::GraphicsPipeline( descriptor_update_template = builder.CreateTemplate(set_layout, *pipeline_layout, uses_push_descriptor); - const VkRenderPass render_pass{render_pass_cache.Get(MakeRenderPassKey(key.state, device))}; + VkRenderPass render_pass{}; + if (!device.IsKhrDynamicRenderingSupported()) { + render_pass = render_pass_cache.Get(MakeRenderPassKey(key.state, device)); + } Validate(); try { MakePipeline(render_pass); @@ -996,9 +999,47 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) { flags |= VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR; } + const RenderPassKey renderpass_key{MakeRenderPassKey(key.state, device)}; + std::array color_attachment_formats{}; + for (size_t index = 0; index < renderpass_key.color_formats.size(); ++index) { + const PixelFormat pixel_format{renderpass_key.color_formats[index]}; + if (pixel_format == PixelFormat::Invalid) { + color_attachment_formats[index] = VK_FORMAT_UNDEFINED; + continue; + } + color_attachment_formats[index] = + MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, true, pixel_format).format; + } + VkFormat depth_attachment_format{VK_FORMAT_UNDEFINED}; + VkFormat stencil_attachment_format{VK_FORMAT_UNDEFINED}; + if (renderpass_key.depth_format != PixelFormat::Invalid) { + const VkFormat format{ + MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, true, + renderpass_key.depth_format) + .format}; + const auto surface_type{VideoCore::Surface::GetFormatType(renderpass_key.depth_format)}; + if (surface_type == VideoCore::Surface::SurfaceType::Depth || + surface_type == VideoCore::Surface::SurfaceType::DepthStencil) { + depth_attachment_format = format; + } + if (surface_type == VideoCore::Surface::SurfaceType::Stencil || + surface_type == VideoCore::Surface::SurfaceType::DepthStencil) { + stencil_attachment_format = format; + } + } + const VkPipelineRenderingCreateInfo rendering_ci{ + .sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO, + .pNext = nullptr, + .viewMask = 0, + .colorAttachmentCount = static_cast(NumAttachments(key.state)), + .pColorAttachmentFormats = color_attachment_formats.data(), + .depthAttachmentFormat = depth_attachment_format, + .stencilAttachmentFormat = stencil_attachment_format, + }; + pipeline = device.GetLogical().CreateGraphicsPipeline({ .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, - .pNext = nullptr, + .pNext = device.IsKhrDynamicRenderingSupported() ? &rendering_ci : nullptr, .flags = flags, .stageCount = static_cast(shader_stages.size()), .pStages = shader_stages.data(), diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 720f3b868c..a937f8e0c1 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -423,6 +423,7 @@ void RasterizerVulkan::Clear(u32 layer_count) { const bool can_defer_clear = ENABLE_DEFERRED_CLEAR && !regs.clear_control.use_scissor && regs.clear_surface.layer == 0 && !scheduler.IsRenderPassActive() && + !device.IsKhrDynamicRenderingSupported() && (!use_color || color_full_channels) && ds_deferrable; if (!can_defer_clear) { scheduler.RequestRenderpass(framebuffer); diff --git a/src/video_core/renderer_vulkan/vk_scheduler.cpp b/src/video_core/renderer_vulkan/vk_scheduler.cpp index 6234b41978..3c70e5c786 100644 --- a/src/video_core/renderer_vulkan/vk_scheduler.cpp +++ b/src/video_core/renderer_vulkan/vk_scheduler.cpp @@ -95,11 +95,40 @@ void Scheduler::DispatchWork() { void Scheduler::BeginRenderPassImpl(const Framebuffer* framebuffer, VkRenderPass renderpass, const VkClearValue* clear_values, u32 clear_value_count) { - const VkFramebuffer framebuffer_handle = framebuffer->Handle(); const VkExtent2D render_area = framebuffer->RenderArea(); + if (device.IsKhrDynamicRenderingSupported()) { + std::array attachment_views{}; + const auto& color_views = framebuffer->ColorAttachments(); + for (size_t index = 0; index < color_views.size(); ++index) { + attachment_views[index] = color_views[index]; + } + attachment_views[8] = framebuffer->DepthAttachment(); + state.renderpass = VkRenderPass{}; + state.framebuffer = VkFramebuffer{}; + state.attachment_views = attachment_views; + state.render_area = render_area; + state.rendering = true; + + if (GPU::Logging::IsActive() && Settings::values.gpu_log_vulkan_calls.GetValue()) { + const std::string render_pass_info = + fmt::format("renderArea={}x{}, numImages={}", render_area.width, render_area.height, + framebuffer->NumImages()); + GPU::Logging::GPULogger::GetInstance().LogRenderPassBegin(render_pass_info); + } + + Record([framebuffer](vk::CommandBuffer cmdbuf) { + framebuffer->BeginRendering(cmdbuf); + }); + num_renderpass_images = framebuffer->NumImages(); + renderpass_images = framebuffer->Images(); + renderpass_image_ranges = framebuffer->ImageRanges(); + return; + } + const VkFramebuffer framebuffer_handle = framebuffer->Handle(); state.renderpass = renderpass; state.framebuffer = framebuffer_handle; state.render_area = render_area; + state.rendering = true; if (GPU::Logging::IsActive() && Settings::values.gpu_log_vulkan_calls.GetValue()) { const std::string render_pass_info = @@ -195,9 +224,25 @@ void Scheduler::RequestRenderpass(const Framebuffer* framebuffer) { RealizeDeferredClear(); return; } + const VkExtent2D render_area = framebuffer->RenderArea(); + if (device.IsKhrDynamicRenderingSupported()) { + std::array attachment_views{}; + const auto& color_views = framebuffer->ColorAttachments(); + for (size_t index = 0; index < color_views.size(); ++index) { + attachment_views[index] = color_views[index]; + } + attachment_views[8] = framebuffer->DepthAttachment(); + if (state.rendering && attachment_views == state.attachment_views && + render_area.width == state.render_area.width && + render_area.height == state.render_area.height) { + return; + } + EndRenderPass(); + BeginRenderPassImpl(framebuffer, VkRenderPass{}, nullptr, 0); + return; + } const VkRenderPass renderpass = framebuffer->RenderPass(); const VkFramebuffer framebuffer_handle = framebuffer->Handle(); - const VkExtent2D render_area = framebuffer->RenderArea(); if (renderpass == state.renderpass && framebuffer_handle == state.framebuffer && render_area.width == state.render_area.width && render_area.height == state.render_area.height) { @@ -380,7 +425,7 @@ void Scheduler::EndPendingOperations() { void Scheduler::EndRenderPass() { RealizeDeferredClear(); - if (!state.renderpass) { + if (!state.rendering) { return; } @@ -398,7 +443,8 @@ void Scheduler::EndRenderPass() Record([num_images = num_renderpass_images, images = renderpass_images, ranges = renderpass_image_ranges, - has_transform_feedback = device.IsExtTransformFeedbackSupported()]( + has_transform_feedback = device.IsExtTransformFeedbackSupported(), + dynamic_rendering = device.IsKhrDynamicRenderingSupported()]( vk::CommandBuffer cmdbuf) { std::array barriers; for (size_t i = 0; i < num_images; ++i) { @@ -435,7 +481,11 @@ void Scheduler::EndRenderPass() .subresourceRange = range, }; } - cmdbuf.EndRenderPass(); + if (dynamic_rendering) { + cmdbuf.EndRendering(); + } else { + cmdbuf.EndRenderPass(); + } cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, 0, nullptr, nullptr, vk::Span(barriers.data(), num_images)); @@ -453,6 +503,9 @@ void Scheduler::EndRenderPass() }); state.renderpass = VkRenderPass{}; + state.framebuffer = VkFramebuffer{}; + state.attachment_views = {}; + state.rendering = false; num_renderpass_images = 0; } diff --git a/src/video_core/renderer_vulkan/vk_scheduler.h b/src/video_core/renderer_vulkan/vk_scheduler.h index 5c4af8c146..7f44fb22ec 100644 --- a/src/video_core/renderer_vulkan/vk_scheduler.h +++ b/src/video_core/renderer_vulkan/vk_scheduler.h @@ -71,7 +71,7 @@ public: /// Returns true when a render pass is currently active in the scheduler state. bool IsRenderPassActive() const { - return state.renderpass != VK_NULL_HANDLE; + return state.rendering; } /// Update the pipeline to the current execution context. @@ -250,8 +250,10 @@ private: struct State { VkRenderPass renderpass{}; VkFramebuffer framebuffer{}; + std::array attachment_views{}; VkExtent2D render_area = {0, 0}; GraphicsPipeline* graphics_pipeline = nullptr; + bool rendering = false; bool is_rescaling = false; bool rescaling_defined = false; bool needs_state_enable_refresh = false; diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index 44a4227a19..5e6b702e3b 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp @@ -1353,7 +1353,7 @@ void TextureCacheRuntime::BlitImage(Framebuffer* dst_framebuffer, ImageView& dst } void TextureCacheRuntime::ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view) { - if (!dst->RenderPass()) { + if (!dst->RenderPass() && !device.IsKhrDynamicRenderingSupported()) { return; } @@ -2683,7 +2683,7 @@ Framebuffer::Framebuffer(TextureCacheRuntime& runtime, std::spanSamples(); + color_attachments[index] = color_buffer->RenderTarget(); + color_attachment_formats[index] = + MaxwellToVK::SurfaceFormat(runtime.device, FormatType::Optimal, true, + color_buffer->format) + .format; + num_color_attachments = static_cast(index + 1); ++num_images; } const size_t num_colors = attachments.size(); @@ -2741,6 +2747,11 @@ void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime, const VkImageSubresourceRange subresource_range = MakeSubresourceRange(depth_buffer); image_ranges[num_images] = subresource_range; samples = depth_buffer->Samples(); + depth_attachment = depth_buffer->RenderTarget(); + depth_attachment_format = + MaxwellToVK::SurfaceFormat(runtime.device, FormatType::Optimal, true, + depth_buffer->format) + .format; ++num_images; has_depth = (subresource_range.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) != 0; has_stencil = (subresource_range.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) != 0; @@ -2755,7 +2766,6 @@ void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime, discard_msaa_color = ENABLE_MSAA_RESOLVE_CONSUME && ENABLE_MSAA_COLOR_DISCARD && do_resolve_color; - renderpass = runtime.render_pass_cache.Get(renderpass_key); render_pass_key = renderpass_key; render_pass_cache = &runtime.render_pass_cache; render_area.width = (std::min)(render_area.width, width); @@ -2819,6 +2829,11 @@ void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime, } num_color_buffers = static_cast(num_colors); + layer_count = static_cast((std::max)(num_layers, 1)); + if (runtime.device.IsKhrDynamicRenderingSupported()) { + return; + } + renderpass = runtime.render_pass_cache.Get(renderpass_key); framebuffer = runtime.device.GetLogical().CreateFramebuffer({ .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, .pNext = nullptr, @@ -2828,7 +2843,7 @@ void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime, .pAttachments = attachments.data(), .width = render_area.width, .height = render_area.height, - .layers = static_cast((std::max)(num_layers, 1)), + .layers = layer_count, }); } @@ -2844,6 +2859,53 @@ VkRenderPass Framebuffer::RenderPassVariant(u32 color_clear_mask, bool depth_ste return render_pass_cache->Get(key); } +void Framebuffer::BeginRendering(vk::CommandBuffer cmdbuf) const { + std::array color_attachment_infos{}; + for (size_t index = 0; index < num_color_attachments; ++index) { + color_attachment_infos[index] = VkRenderingAttachmentInfo{ + .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO, + .pNext = nullptr, + .imageView = color_attachments[index], + .imageLayout = VK_IMAGE_LAYOUT_GENERAL, + .resolveMode = VK_RESOLVE_MODE_NONE, + .resolveImageView = VK_NULL_HANDLE, + .resolveImageLayout = VK_IMAGE_LAYOUT_UNDEFINED, + .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD, + .storeOp = VK_ATTACHMENT_STORE_OP_STORE, + .clearValue = {}, + }; + } + const VkRenderingAttachmentInfo depth_attachment_info{ + .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO, + .pNext = nullptr, + .imageView = depth_attachment, + .imageLayout = VK_IMAGE_LAYOUT_GENERAL, + .resolveMode = VK_RESOLVE_MODE_NONE, + .resolveImageView = VK_NULL_HANDLE, + .resolveImageLayout = VK_IMAGE_LAYOUT_UNDEFINED, + .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD, + .storeOp = VK_ATTACHMENT_STORE_OP_STORE, + .clearValue = {}, + }; + const VkRenderingInfo rendering_info{ + .sType = VK_STRUCTURE_TYPE_RENDERING_INFO, + .pNext = nullptr, + .flags = 0, + .renderArea = + { + .offset = {.x = 0, .y = 0}, + .extent = render_area, + }, + .layerCount = layer_count, + .viewMask = 0, + .colorAttachmentCount = num_color_attachments, + .pColorAttachments = color_attachment_infos.data(), + .pDepthAttachment = has_depth ? &depth_attachment_info : nullptr, + .pStencilAttachment = has_stencil ? &depth_attachment_info : nullptr, + }; + cmdbuf.BeginRendering(rendering_info); +} + void TextureCacheRuntime::AccelerateImageUpload( Image& image, const StagingBufferRef& map, std::span swizzles, diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h index 99f2978cca..003d7995cc 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.h +++ b/src/video_core/renderer_vulkan/vk_texture_cache.h @@ -178,6 +178,8 @@ public: std::span color_buffers, ImageView* depth_buffer, bool is_rescaled = false); + void BeginRendering(vk::CommandBuffer cmdbuf) const; + [[nodiscard]] VkFramebuffer Handle() const noexcept { return *framebuffer; } @@ -193,6 +195,30 @@ public: [[nodiscard]] VkRenderPass RenderPassVariant(u32 color_clear_mask, bool depth_stencil_clear, u32 color_discard_mask) const; + [[nodiscard]] u32 NumColorAttachments() const noexcept { + return num_color_attachments; + } + + [[nodiscard]] const std::array& ColorAttachments() const noexcept { + return color_attachments; + } + + [[nodiscard]] const std::array& ColorAttachmentFormats() const noexcept { + return color_attachment_formats; + } + + [[nodiscard]] VkImageView DepthAttachment() const noexcept { + return depth_attachment; + } + + [[nodiscard]] VkFormat DepthAttachmentFormat() const noexcept { + return depth_attachment_format; + } + + [[nodiscard]] u32 NumLayers() const noexcept { + return layer_count; + } + [[nodiscard]] VkExtent2D RenderArea() const noexcept { return render_area; } @@ -255,6 +281,12 @@ private: std::array images{}; std::array image_ranges{}; std::array rt_map{}; + std::array color_attachments{}; + std::array color_attachment_formats{}; + VkImageView depth_attachment{}; + VkFormat depth_attachment_format = VK_FORMAT_UNDEFINED; + u32 num_color_attachments = 0; + u32 layer_count = 1; bool has_depth{}; bool has_stencil{}; bool is_rescaled{}; diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index 8fd9b6e69f..52e99a0842 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp @@ -1373,6 +1373,11 @@ void Device::RemoveUnsuitableExtensions() { extensions.maintenance3 = loaded_extensions.contains(VK_KHR_MAINTENANCE_3_EXTENSION_NAME); RemoveExtensionIfUnsuitable(extensions.maintenance3, VK_KHR_MAINTENANCE_3_EXTENSION_NAME); + // VK_KHR_dynamic_rendering + extensions.dynamic_rendering = features.dynamic_rendering.dynamicRendering; + RemoveExtensionFeatureIfUnsuitable(extensions.dynamic_rendering, features.dynamic_rendering, + VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME); + // VK_KHR_maintenance4 extensions.maintenance4 = features.maintenance4.maintenance4; RemoveExtensionFeatureIfUnsuitable(extensions.maintenance4, features.maintenance4, diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index c449f60324..10268c3e25 100644 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h @@ -43,6 +43,7 @@ VK_DEFINE_HANDLE(VmaAllocator) FEATURE(EXT, ShaderDemoteToHelperInvocation, SHADER_DEMOTE_TO_HELPER_INVOCATION, \ shader_demote_to_helper_invocation) \ FEATURE(EXT, SubgroupSizeControl, SUBGROUP_SIZE_CONTROL, subgroup_size_control) \ + FEATURE(KHR, DynamicRendering, DYNAMIC_RENDERING, dynamic_rendering) \ FEATURE(KHR, Maintenance4, MAINTENANCE_4, maintenance4) \ FEATURE(KHR, Synchronization2, SYNCHRONIZATION_2, synchronization2) @@ -941,6 +942,11 @@ FN_MAX_LIMIT_LIST return extensions.maintenance3; } + /// Returns true if the device supports VK_KHR_dynamic_rendering. + bool IsKhrDynamicRenderingSupported() const { + return extensions.dynamic_rendering; + } + /// Returns true if the device supports VK_KHR_maintenance4. bool IsKhrMaintenance4Supported() const { return extensions.maintenance4; diff --git a/src/video_core/vulkan_common/vulkan_wrapper.cpp b/src/video_core/vulkan_common/vulkan_wrapper.cpp index 4943705859..91344227c5 100644 --- a/src/video_core/vulkan_common/vulkan_wrapper.cpp +++ b/src/video_core/vulkan_common/vulkan_wrapper.cpp @@ -92,6 +92,7 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept { X(vkCmdBeginConditionalRenderingEXT); X(vkCmdBeginQuery); X(vkCmdBeginRenderPass); + X(vkCmdBeginRendering); X(vkCmdBeginTransformFeedbackEXT); X(vkCmdBeginDebugUtilsLabelEXT); X(vkCmdBindDescriptorSets); @@ -119,6 +120,7 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept { X(vkCmdEndConditionalRenderingEXT); X(vkCmdEndQuery); X(vkCmdEndRenderPass); + X(vkCmdEndRendering); X(vkCmdEndTransformFeedbackEXT); X(vkCmdEndDebugUtilsLabelEXT); X(vkCmdFillBuffer); @@ -257,6 +259,12 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept { Proc(dld.vkCmdDrawIndexedIndirectCount, dld, "vkCmdDrawIndexedIndirectCountKHR", device); } + // Support for dynamic rendering is optional until Vulkan 1.3 + if (!dld.vkCmdBeginRendering) { + Proc(dld.vkCmdBeginRendering, dld, "vkCmdBeginRenderingKHR", device); + Proc(dld.vkCmdEndRendering, dld, "vkCmdEndRenderingKHR", device); + } + // Synchronization2 is core in Vulkan 1.3, otherwise requires VK_KHR_synchronization2 if (!dld.vkCmdPipelineBarrier2) { Proc(dld.vkCmdPipelineBarrier2, dld, "vkCmdPipelineBarrier2KHR", device); diff --git a/src/video_core/vulkan_common/vulkan_wrapper.h b/src/video_core/vulkan_common/vulkan_wrapper.h index ef975e2bda..022e111c5d 100644 --- a/src/video_core/vulkan_common/vulkan_wrapper.h +++ b/src/video_core/vulkan_common/vulkan_wrapper.h @@ -208,6 +208,7 @@ struct DeviceDispatch : InstanceDispatch { PFN_vkCmdBeginDebugUtilsLabelEXT vkCmdBeginDebugUtilsLabelEXT{}; PFN_vkCmdBeginQuery vkCmdBeginQuery{}; PFN_vkCmdBeginRenderPass vkCmdBeginRenderPass{}; + PFN_vkCmdBeginRendering vkCmdBeginRendering{}; PFN_vkCmdBeginTransformFeedbackEXT vkCmdBeginTransformFeedbackEXT{}; PFN_vkCmdBindDescriptorSets vkCmdBindDescriptorSets{}; PFN_vkCmdBindIndexBuffer vkCmdBindIndexBuffer{}; @@ -236,6 +237,7 @@ struct DeviceDispatch : InstanceDispatch { PFN_vkCmdEndDebugUtilsLabelEXT vkCmdEndDebugUtilsLabelEXT{}; PFN_vkCmdEndQuery vkCmdEndQuery{}; PFN_vkCmdEndRenderPass vkCmdEndRenderPass{}; + PFN_vkCmdEndRendering vkCmdEndRendering{}; PFN_vkCmdEndTransformFeedbackEXT vkCmdEndTransformFeedbackEXT{}; PFN_vkCmdFillBuffer vkCmdFillBuffer{}; PFN_vkCmdPipelineBarrier vkCmdPipelineBarrier{}; @@ -1186,6 +1188,14 @@ public: dld->vkCmdEndRenderPass(handle); } + void BeginRendering(const VkRenderingInfo& rendering_info) const noexcept { + dld->vkCmdBeginRendering(handle, &rendering_info); + } + + void EndRendering() const noexcept { + dld->vkCmdEndRendering(handle); + } + void BeginQuery(VkQueryPool query_pool, u32 query, VkQueryControlFlags flags) const noexcept { dld->vkCmdBeginQuery(handle, query_pool, query, flags); }