diff --git a/src/video_core/renderer_vulkan/blit_image.cpp b/src/video_core/renderer_vulkan/blit_image.cpp index dad11ae613..7b0b784ac6 100644 --- a/src/video_core/renderer_vulkan/blit_image.cpp +++ b/src/video_core/renderer_vulkan/blit_image.cpp @@ -609,7 +609,7 @@ void BlitImageHelper::BlitColor(const Framebuffer* dst_framebuffer, const ImageV Tegra::Engines::Fermi2D::Operation operation) { const bool is_linear = filter == Tegra::Engines::Fermi2D::Filter::Bilinear; const BlitImagePipelineKey key{ - .renderpass = dst_framebuffer->RenderPass(), + .formats = dst_framebuffer->Formats(), .operation = operation, }; VkSampler sampler = *nearest_sampler; @@ -626,7 +626,7 @@ void BlitImageHelper::BlitColor(const Framebuffer* dst_framebuffer, VkImageView const Region2D& dst_region, const Region2D& src_region, const Extent3D& src_size) { const BlitImagePipelineKey key{ - .renderpass = dst_framebuffer->RenderPass(), + .formats = dst_framebuffer->Formats(), .operation = Tegra::Engines::Fermi2D::Operation::SrcCopy, }; const VkPipelineLayout layout = *one_texture_pipeline_layout; @@ -686,7 +686,7 @@ void BlitImageHelper::BlitColorMSAA(const Framebuffer* dst_framebuffer, const ImageView& src_image_view, const Region2D& dst_region, const Region2D& src_region) { const BlitMSAAPipelineKey key{ - .renderpass = dst_framebuffer->RenderPass(), + .formats = dst_framebuffer->Formats(), .samples = dst_framebuffer->Samples(), }; BlitImpl(dst_framebuffer, src_image_view, dst_region, src_region, @@ -700,7 +700,7 @@ void BlitImageHelper::BlitDepthStencilMSAA(const Framebuffer* dst_framebuffer, const bool blit_stencil = dst_framebuffer->HasAspectStencilBit() && device.IsExtShaderStencilExportSupported(); const BlitMSAAPipelineKey key{ - .renderpass = dst_framebuffer->RenderPass(), + .formats = dst_framebuffer->Formats(), .samples = dst_framebuffer->Samples(), }; VkImageView src_stencil_view = VK_NULL_HANDLE; @@ -715,7 +715,7 @@ void BlitImageHelper::BlitDepthStencilMSAA(const Framebuffer* dst_framebuffer, void BlitImageHelper::BlitDepth(const Framebuffer* dst_framebuffer, ImageView& src_image_view, const Region2D& dst_region, const Region2D& src_region) { BlitImpl(dst_framebuffer, src_image_view, dst_region, src_region, - FindOrEmplaceBlitDepthPipeline(dst_framebuffer->RenderPass()), *nearest_sampler, + FindOrEmplaceBlitDepthPipeline(dst_framebuffer->Formats()), *nearest_sampler, src_image_view.DepthView(), VK_NULL_HANDLE, false); } @@ -729,7 +729,7 @@ void BlitImageHelper::ResolveDepthStencil(const Framebuffer* dst_framebuffer, src_stencil_view = src_image_view.StencilView(); } BlitImpl(dst_framebuffer, src_image_view, dst_region, src_region, - FindOrEmplaceResolveDepthStencilPipeline(dst_framebuffer->RenderPass(), + FindOrEmplaceResolveDepthStencilPipeline(dst_framebuffer->Formats(), resolve_stencil), *nearest_sampler, src_image_view.DepthView(), src_stencil_view, resolve_stencil); } @@ -743,7 +743,7 @@ void BlitImageHelper::BlitDepthStencil(const Framebuffer* dst_framebuffer, ASSERT(operation == Tegra::Engines::Fermi2D::Operation::SrcCopy); const bool blit_stencil = device.IsExtShaderStencilExportSupported(); const BlitImagePipelineKey key{ - .renderpass = dst_framebuffer->RenderPass(), + .formats = dst_framebuffer->Formats(), .operation = operation, }; VkPipeline pipeline{}; @@ -752,7 +752,7 @@ void BlitImageHelper::BlitDepthStencil(const Framebuffer* dst_framebuffer, pipeline = FindOrEmplaceDepthStencilPipeline(key); src_stencil_view = src_image_view.StencilView(); } else { - pipeline = FindOrEmplaceBlitDepthPipeline(key.renderpass); + pipeline = FindOrEmplaceBlitDepthPipeline(key.formats); } BlitImpl(dst_framebuffer, src_image_view, dst_region, src_region, pipeline, *nearest_sampler, src_image_view.DepthView(), src_stencil_view, blit_stencil); @@ -760,25 +760,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->Formats()); 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->Formats()); 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->Formats()); 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->Formats()); Convert(*convert_r16_to_d16_pipeline, dst_framebuffer, src_image_view); } @@ -789,35 +789,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->Formats(), 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->Formats(), 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->Formats(), 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->Formats(), 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->Formats(), convert_s8d24_to_abgr8_frag); ConvertDepthStencil(*convert_s8d24_to_abgr8_pipeline, dst_framebuffer, src_image_view); } @@ -826,7 +826,7 @@ void BlitImageHelper::ClearColor(const Framebuffer* dst_framebuffer, u8 color_ma const std::array& clear_color, const Region2D& dst_region) { const BlitImagePipelineKey key{ - .renderpass = dst_framebuffer->RenderPass(), + .formats = dst_framebuffer->Formats(), .operation = Tegra::Engines::Fermi2D::Operation::BlendPremult, }; const VkPipeline pipeline = FindOrEmplaceClearColorPipeline(key); @@ -850,7 +850,7 @@ void BlitImageHelper::ClearDepthStencil(const Framebuffer* dst_framebuffer, bool f32 clear_depth, u8 stencil_mask, u32 stencil_ref, u32 stencil_compare_mask, const Region2D& dst_region) { const BlitDepthStencilPipelineKey key{ - .renderpass = dst_framebuffer->RenderPass(), + .formats = dst_framebuffer->Formats(), .depth_clear = depth_clear, .stencil_mask = stencil_mask, .stencil_compare_mask = stencil_compare_mask, @@ -870,7 +870,7 @@ void BlitImageHelper::ClearDepthStencil(const Framebuffer* dst_framebuffer, bool scheduler.InvalidateState(); } -void BlitImageHelper::CopyMSAAImpl(VkRenderPass renderpass, VkPipeline pipeline, +void BlitImageHelper::CopyMSAAImpl(const RenderingFormats& formats, VkPipeline pipeline, VkPipelineLayout layout, VkImage dst_image, VkFormat dst_vk_format, VkImage src_image, VkFormat src_vk_format, s32 scale_x, s32 scale_y, @@ -906,17 +906,10 @@ void BlitImageHelper::CopyMSAAImpl(VkRenderPass renderpass, VkPipeline pipeline, .offset = dst_offset, .extent = dst_extent, }; - vk::Framebuffer framebuffer = device.GetLogical().CreateFramebuffer(VkFramebufferCreateInfo{ - .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .renderPass = renderpass, - .attachmentCount = 1, - .pAttachments = dst_view.address(), - .width = static_cast(dst_offset.x) + dst_extent.width, - .height = static_cast(dst_offset.y) + dst_extent.height, - .layers = 1, - }); + const VkImageView dst_view_handle = *dst_view; + const RenderingAttachments attachments = + MakeRenderingAttachments(formats, std::span(&dst_view_handle, formats.num_colors), + dst_view_handle, render_area, 1); const MSAACopyPushConstants push_constants{ .dst_offset = {dst_offset.x, dst_offset.y}, .src_offset = {copy.src_offset.x, copy.src_offset.y}, @@ -927,10 +920,10 @@ void BlitImageHelper::CopyMSAAImpl(VkRenderPass renderpass, VkPipeline pipeline, src_stencil_handle = *src_stencil_view; } scheduler.RequestOutsideRenderPassOperationContext(); - scheduler.Record([this, pipeline, layout, sampler, renderpass, - framebuffer_handle = *framebuffer, src_view_handle = *src_view, - src_stencil_handle, src = src_image, dst = dst_image, render_area, - aspect_info, push_constants](vk::CommandBuffer cmdbuf) { + scheduler.Record([this, pipeline, layout, sampler, attachments, + src_view_handle = *src_view, src_stencil_handle, src = src_image, + dst = dst_image, render_area, aspect_info, + push_constants](vk::CommandBuffer cmdbuf) { const VkImageSubresourceRange barrier_range{ .aspectMask = aspect_info.barrier_aspect, .baseMipLevel = 0, @@ -969,16 +962,7 @@ void BlitImageHelper::CopyMSAAImpl(VkRenderPass renderpass, VkPipeline pipeline, }, }; cmdbuf.PipelineBarrier(0, {}, {}, pre_barriers); - const VkRenderPassBeginInfo renderpass_bi{ - .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, - .pNext = nullptr, - .renderPass = renderpass, - .framebuffer = framebuffer_handle, - .renderArea = render_area, - .clearValueCount = 0, - .pClearValues = nullptr, - }; - cmdbuf.BeginRenderPass(renderpass_bi, VK_SUBPASS_CONTENTS_INLINE); + BeginRendering(cmdbuf, attachments); VkDescriptorSet descriptor_set = VK_NULL_HANDLE; if (src_stencil_handle != VK_NULL_HANDLE) { descriptor_set = two_textures_descriptor_allocator.Commit(); @@ -1003,7 +987,7 @@ void BlitImageHelper::CopyMSAAImpl(VkRenderPass renderpass, VkPipeline pipeline, cmdbuf.SetScissor(0, render_area); cmdbuf.PushConstants(layout, VK_SHADER_STAGE_FRAGMENT_BIT, push_constants); cmdbuf.Draw(3, 1, 0, 0); - cmdbuf.EndRenderPass(); + cmdbuf.EndRendering(); const VkImageMemoryBarrier2 post_barrier{ .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2, .pNext = nullptr, @@ -1024,14 +1008,12 @@ void BlitImageHelper::CopyMSAAImpl(VkRenderPass renderpass, VkPipeline pipeline, .tick = scheduler.CurrentTick(), .src_view = std::move(src_view), .dst_view = std::move(dst_view), - .framebuffer = std::move(framebuffer), }); if (copy_stencil) { msaa_copy_resources.push_back(MSAACopyResources{ .tick = scheduler.CurrentTick(), .src_view = std::move(src_stencil_view), .dst_view = vk::ImageView{}, - .framebuffer = vk::Framebuffer{}, }); } } @@ -1039,10 +1021,9 @@ void BlitImageHelper::CopyMSAAImpl(VkRenderPass renderpass, VkPipeline pipeline, scheduler.InvalidateState(); } -void BlitImageHelper::CopyMSAA(RenderPassCache& render_pass_cache, VkImage dst_image, - VideoCore::Surface::PixelFormat dst_format, VkImage src_image, - VideoCore::Surface::PixelFormat src_format, u32 num_samples, - std::span copies, +void BlitImageHelper::CopyMSAA(VkImage dst_image, VideoCore::Surface::PixelFormat dst_format, + VkImage src_image, VideoCore::Surface::PixelFormat src_format, + u32 num_samples, std::span copies, bool msaa_to_non_msaa) { const auto [samples_x, samples_y] = VideoCommon::SamplesLog2(static_cast(num_samples)); const s32 scale_x = 1 << samples_x; @@ -1051,14 +1032,10 @@ void BlitImageHelper::CopyMSAA(RenderPassCache& render_pass_cache, VkImage dst_i if (msaa_to_non_msaa) { samples = VK_SAMPLE_COUNT_1_BIT; } - RenderPassKey renderpass_key{}; - renderpass_key.color_formats.fill(VideoCore::Surface::PixelFormat::Invalid); - renderpass_key.color_formats[0] = dst_format; - renderpass_key.depth_format = VideoCore::Surface::PixelFormat::Invalid; - renderpass_key.samples = samples; - const VkRenderPass renderpass = render_pass_cache.Get(renderpass_key); + const RenderingFormats formats = MakeRenderingFormats( + device, std::span(&dst_format, 1), VideoCore::Surface::PixelFormat::Invalid); const MSAACopyPipelineKey key{ - .renderpass = renderpass, + .formats = formats, .samples = samples, .msaa_to_non_msaa = msaa_to_non_msaa, .format_class = FormatClass(dst_format), @@ -1079,7 +1056,7 @@ void BlitImageHelper::CopyMSAA(RenderPassCache& render_pass_cache, VkImage dst_i MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, true, src_format).format; const VkFormat dst_vk_format = MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, true, dst_format).format; - CopyMSAAImpl(renderpass, FindOrEmplaceMSAACopyPipeline(key), *msaa_copy_pipeline_layout, + CopyMSAAImpl(formats, FindOrEmplaceMSAACopyPipeline(key), *msaa_copy_pipeline_layout, dst_image, dst_vk_format, src_image, src_vk_format, scale_x, scale_y, copies, aspect_info, false); } @@ -1205,9 +1182,10 @@ VkPipeline BlitImageHelper::FindOrEmplaceColorPipeline(const BlitImagePipelineKe .blendConstants = {0.0f, 0.0f, 0.0f, 0.0f}, }; const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device); + const VkPipelineRenderingCreateInfo rendering_ci = key.formats.CreateInfo(); blit_color_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({ .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, - .pNext = nullptr, + .pNext = &rendering_ci, .flags = 0, .stageCount = static_cast(stages.size()), .pStages = stages.data(), @@ -1221,7 +1199,6 @@ VkPipeline BlitImageHelper::FindOrEmplaceColorPipeline(const BlitImagePipelineKe .pColorBlendState = &color_blend_create_info, .pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO, .layout = *one_texture_pipeline_layout, - .renderPass = key.renderpass, .subpass = 0, .basePipelineHandle = VK_NULL_HANDLE, .basePipelineIndex = 0, @@ -1237,9 +1214,10 @@ VkPipeline BlitImageHelper::FindOrEmplaceDepthStencilPipeline(const BlitImagePip blit_depth_stencil_keys.push_back(key); const std::array stages = MakeStages(*full_screen_vert, *blit_depth_stencil_frag); const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device); + const VkPipelineRenderingCreateInfo rendering_ci = key.formats.CreateInfo(); blit_depth_stencil_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({ .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, - .pNext = nullptr, + .pNext = &rendering_ci, .flags = 0, .stageCount = static_cast(stages.size()), .pStages = stages.data(), @@ -1253,7 +1231,6 @@ VkPipeline BlitImageHelper::FindOrEmplaceDepthStencilPipeline(const BlitImagePip .pColorBlendState = &PIPELINE_COLOR_BLEND_STATE_EMPTY_CREATE_INFO, .pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO, .layout = *two_textures_pipeline_layout, - .renderPass = key.renderpass, .subpass = 0, .basePipelineHandle = VK_NULL_HANDLE, .basePipelineIndex = 0, @@ -1290,9 +1267,10 @@ VkPipeline BlitImageHelper::FindOrEmplaceClearColorPipeline(const BlitImagePipel .blendConstants = {0.0f, 0.0f, 0.0f, 0.0f}, }; const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device); + const VkPipelineRenderingCreateInfo rendering_ci = key.formats.CreateInfo(); clear_color_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({ .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, - .pNext = nullptr, + .pNext = &rendering_ci, .flags = 0, .stageCount = static_cast(stages.size()), .pStages = stages.data(), @@ -1306,7 +1284,6 @@ VkPipeline BlitImageHelper::FindOrEmplaceClearColorPipeline(const BlitImagePipel .pColorBlendState = &color_blend_state_generic_create_info, .pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO, .layout = *clear_color_pipeline_layout, - .renderPass = key.renderpass, .subpass = 0, .basePipelineHandle = VK_NULL_HANDLE, .basePipelineIndex = 0, @@ -1346,9 +1323,10 @@ VkPipeline BlitImageHelper::FindOrEmplaceClearStencilPipeline( .maxDepthBounds = 0.0f, }; const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device); + const VkPipelineRenderingCreateInfo rendering_ci = key.formats.CreateInfo(); clear_stencil_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({ .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, - .pNext = nullptr, + .pNext = &rendering_ci, .flags = 0, .stageCount = static_cast(stages.size()), .pStages = stages.data(), @@ -1362,7 +1340,6 @@ VkPipeline BlitImageHelper::FindOrEmplaceClearStencilPipeline( .pColorBlendState = &PIPELINE_COLOR_BLEND_STATE_GENERIC_CREATE_INFO, .pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO, .layout = *clear_color_pipeline_layout, - .renderPass = key.renderpass, .subpass = 0, .basePipelineHandle = VK_NULL_HANDLE, .basePipelineIndex = 0, @@ -1389,9 +1366,10 @@ VkPipeline BlitImageHelper::FindOrEmplaceBlitColorMSAAPipeline(const BlitMSAAPip .alphaToOneEnable = VK_FALSE, }; const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device); + const VkPipelineRenderingCreateInfo rendering_ci = key.formats.CreateInfo(); blit_msaa_color_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({ .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, - .pNext = nullptr, + .pNext = &rendering_ci, .flags = 0, .stageCount = static_cast(stages.size()), .pStages = stages.data(), @@ -1405,7 +1383,6 @@ VkPipeline BlitImageHelper::FindOrEmplaceBlitColorMSAAPipeline(const BlitMSAAPip .pColorBlendState = &PIPELINE_COLOR_BLEND_STATE_GENERIC_CREATE_INFO, .pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO, .layout = *one_texture_pipeline_layout, - .renderPass = key.renderpass, .subpass = 0, .basePipelineHandle = VK_NULL_HANDLE, .basePipelineIndex = 0, @@ -1437,9 +1414,10 @@ VkPipeline BlitImageHelper::FindOrEmplaceBlitDepthStencilMSAAPipeline( .alphaToOneEnable = VK_FALSE, }; const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device); + const VkPipelineRenderingCreateInfo rendering_ci = key.formats.CreateInfo(); pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({ .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, - .pNext = nullptr, + .pNext = &rendering_ci, .flags = 0, .stageCount = static_cast(stages.size()), .pStages = stages.data(), @@ -1454,7 +1432,6 @@ VkPipeline BlitImageHelper::FindOrEmplaceBlitDepthStencilMSAAPipeline( .pColorBlendState = &PIPELINE_COLOR_BLEND_STATE_EMPTY_CREATE_INFO, .pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO, .layout = blit_stencil ? *two_textures_pipeline_layout : *one_texture_pipeline_layout, - .renderPass = key.renderpass, .subpass = 0, .basePipelineHandle = VK_NULL_HANDLE, .basePipelineIndex = 0, @@ -1462,17 +1439,18 @@ VkPipeline BlitImageHelper::FindOrEmplaceBlitDepthStencilMSAAPipeline( return *pipelines.back(); } -VkPipeline BlitImageHelper::FindOrEmplaceBlitDepthPipeline(VkRenderPass renderpass) { - const auto it = std::ranges::find(blit_depth_keys, renderpass); +VkPipeline BlitImageHelper::FindOrEmplaceBlitDepthPipeline(const RenderingFormats& formats) { + const auto it = std::ranges::find(blit_depth_keys, formats); if (it != blit_depth_keys.end()) { return *blit_depth_pipelines[std::distance(blit_depth_keys.begin(), it)]; } - blit_depth_keys.push_back(renderpass); + blit_depth_keys.push_back(formats); const std::array stages = MakeStages(*full_screen_vert, *blit_depth_frag); const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device); + const VkPipelineRenderingCreateInfo rendering_ci = formats.CreateInfo(); blit_depth_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({ .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, - .pNext = nullptr, + .pNext = &rendering_ci, .flags = 0, .stageCount = static_cast(stages.size()), .pStages = stages.data(), @@ -1486,7 +1464,6 @@ VkPipeline BlitImageHelper::FindOrEmplaceBlitDepthPipeline(VkRenderPass renderpa .pColorBlendState = &PIPELINE_COLOR_BLEND_STATE_EMPTY_CREATE_INFO, .pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO, .layout = *one_texture_pipeline_layout, - .renderPass = renderpass, .subpass = 0, .basePipelineHandle = VK_NULL_HANDLE, .basePipelineIndex = 0, @@ -1494,22 +1471,23 @@ VkPipeline BlitImageHelper::FindOrEmplaceBlitDepthPipeline(VkRenderPass renderpa return *blit_depth_pipelines.back(); } -VkPipeline BlitImageHelper::FindOrEmplaceResolveDepthStencilPipeline(VkRenderPass renderpass, - bool resolve_stencil) { +VkPipeline BlitImageHelper::FindOrEmplaceResolveDepthStencilPipeline( + const RenderingFormats& formats, bool resolve_stencil) { auto& keys = resolve_stencil ? resolve_depth_stencil_keys : resolve_depth_keys; auto& pipelines = resolve_stencil ? resolve_depth_stencil_pipelines : resolve_depth_pipelines; - const auto it = std::ranges::find(keys, renderpass); + const auto it = std::ranges::find(keys, formats); if (it != keys.end()) { return *pipelines[std::distance(keys.begin(), it)]; } - keys.push_back(renderpass); + keys.push_back(formats); const std::array stages = MakeStages(*full_screen_vert, resolve_stencil ? *blit_depth_stencil_msaa_frag : *blit_depth_msaa_frag); const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device); + const VkPipelineRenderingCreateInfo rendering_ci = formats.CreateInfo(); pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({ .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, - .pNext = nullptr, + .pNext = &rendering_ci, .flags = 0, .stageCount = static_cast(stages.size()), .pStages = stages.data(), @@ -1524,7 +1502,6 @@ VkPipeline BlitImageHelper::FindOrEmplaceResolveDepthStencilPipeline(VkRenderPas .pColorBlendState = &PIPELINE_COLOR_BLEND_STATE_EMPTY_CREATE_INFO, .pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO, .layout = resolve_stencil ? *two_textures_pipeline_layout : *one_texture_pipeline_layout, - .renderPass = renderpass, .subpass = 0, .basePipelineHandle = VK_NULL_HANDLE, .basePipelineIndex = 0, @@ -1532,10 +1509,9 @@ VkPipeline BlitImageHelper::FindOrEmplaceResolveDepthStencilPipeline(VkRenderPas return *pipelines.back(); } -void BlitImageHelper::CopyMSAADepth(RenderPassCache& render_pass_cache, VkImage dst_image, - VideoCore::Surface::PixelFormat dst_format, VkImage src_image, - VideoCore::Surface::PixelFormat src_format, u32 num_samples, - std::span copies, +void BlitImageHelper::CopyMSAADepth(VkImage dst_image, VideoCore::Surface::PixelFormat dst_format, + VkImage src_image, VideoCore::Surface::PixelFormat src_format, + u32 num_samples, std::span copies, bool copy_stencil, bool msaa_to_non_msaa) { const auto [samples_x, samples_y] = VideoCommon::SamplesLog2(static_cast(num_samples)); const s32 scale_x = 1 << samples_x; @@ -1544,13 +1520,9 @@ void BlitImageHelper::CopyMSAADepth(RenderPassCache& render_pass_cache, VkImage if (msaa_to_non_msaa) { samples = VK_SAMPLE_COUNT_1_BIT; } - RenderPassKey renderpass_key{}; - renderpass_key.color_formats.fill(VideoCore::Surface::PixelFormat::Invalid); - renderpass_key.depth_format = dst_format; - renderpass_key.samples = samples; - const VkRenderPass renderpass = render_pass_cache.Get(renderpass_key); + const RenderingFormats formats = MakeRenderingFormats(device, {}, dst_format); const MSAACopyPipelineKey key{ - .renderpass = renderpass, + .formats = formats, .samples = samples, .msaa_to_non_msaa = msaa_to_non_msaa, .format_class = MSAACopyFormatClass::Float, @@ -1580,7 +1552,7 @@ void BlitImageHelper::CopyMSAADepth(RenderPassCache& render_pass_cache, VkImage MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, true, src_format).format; const VkFormat dst_vk_format = MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, true, dst_format).format; - CopyMSAAImpl(renderpass, FindOrEmplaceMSAACopyDepthPipeline(key, copy_stencil), layout, + CopyMSAAImpl(formats, FindOrEmplaceMSAACopyDepthPipeline(key, copy_stencil), layout, dst_image, dst_vk_format, src_image, src_vk_format, scale_x, scale_y, copies, aspect_info, copy_stencil); } @@ -1613,9 +1585,10 @@ VkPipeline BlitImageHelper::FindOrEmplaceMSAACopyPipeline(const MSAACopyPipeline .alphaToOneEnable = VK_FALSE, }; const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device); + const VkPipelineRenderingCreateInfo rendering_ci = key.formats.CreateInfo(); msaa_copy_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({ .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, - .pNext = nullptr, + .pNext = &rendering_ci, .flags = 0, .stageCount = static_cast(stages.size()), .pStages = stages.data(), @@ -1629,7 +1602,6 @@ VkPipeline BlitImageHelper::FindOrEmplaceMSAACopyPipeline(const MSAACopyPipeline .pColorBlendState = &PIPELINE_COLOR_BLEND_STATE_GENERIC_CREATE_INFO, .pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO, .layout = *msaa_copy_pipeline_layout, - .renderPass = key.renderpass, .subpass = 0, .basePipelineHandle = VK_NULL_HANDLE, .basePipelineIndex = 0, @@ -1691,9 +1663,10 @@ VkPipeline BlitImageHelper::FindOrEmplaceMSAACopyDepthPipeline(const MSAACopyPip }; const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device); + const VkPipelineRenderingCreateInfo rendering_ci = key.formats.CreateInfo(); pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({ .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, - .pNext = nullptr, + .pNext = &rendering_ci, .flags = 0, .stageCount = static_cast(stages.size()), .pStages = stages.data(), @@ -1708,7 +1681,6 @@ VkPipeline BlitImageHelper::FindOrEmplaceMSAACopyDepthPipeline(const MSAACopyPip .pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO, .layout = copy_stencil ? *msaa_copy_depth_stencil_pipeline_layout : *msaa_copy_pipeline_layout, - .renderPass = key.renderpass, .subpass = 0, .basePipelineHandle = VK_NULL_HANDLE, .basePipelineIndex = 0, @@ -1716,15 +1688,17 @@ VkPipeline BlitImageHelper::FindOrEmplaceMSAACopyDepthPipeline(const MSAACopyPip return *pipelines.back(); } -void BlitImageHelper::ConvertDepthToColorPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass) { - ConvertPipeline(pipeline, renderpass, false); +void BlitImageHelper::ConvertDepthToColorPipeline(vk::Pipeline& pipeline, + const RenderingFormats& formats) { + ConvertPipeline(pipeline, formats, false); } -void BlitImageHelper::ConvertColorToDepthPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass) { - ConvertPipeline(pipeline, renderpass, true); +void BlitImageHelper::ConvertColorToDepthPipeline(vk::Pipeline& pipeline, + const RenderingFormats& formats) { + ConvertPipeline(pipeline, formats, true); } -void BlitImageHelper::ConvertPipelineEx(vk::Pipeline& pipeline, VkRenderPass renderpass, +void BlitImageHelper::ConvertPipelineEx(vk::Pipeline& pipeline, const RenderingFormats& formats, vk::ShaderModule& module, bool single_texture, bool is_target_depth) { if (pipeline) { @@ -1732,9 +1706,10 @@ void BlitImageHelper::ConvertPipelineEx(vk::Pipeline& pipeline, VkRenderPass ren } const std::array stages = MakeStages(*full_screen_vert, *module); const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device); + const VkPipelineRenderingCreateInfo rendering_ci = formats.CreateInfo(); pipeline = device.GetLogical().CreateGraphicsPipeline(VkGraphicsPipelineCreateInfo{ .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, - .pNext = nullptr, + .pNext = &rendering_ci, .flags = 0, .stageCount = static_cast(stages.size()), .pStages = stages.data(), @@ -1749,24 +1724,25 @@ void BlitImageHelper::ConvertPipelineEx(vk::Pipeline& pipeline, VkRenderPass ren : &PIPELINE_COLOR_BLEND_STATE_GENERIC_CREATE_INFO, .pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO, .layout = single_texture ? *one_texture_pipeline_layout : *two_textures_pipeline_layout, - .renderPass = renderpass, .subpass = 0, .basePipelineHandle = VK_NULL_HANDLE, .basePipelineIndex = 0, }); } -void BlitImageHelper::ConvertPipelineColorTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass, +void BlitImageHelper::ConvertPipelineColorTargetEx(vk::Pipeline& pipeline, + const RenderingFormats& formats, vk::ShaderModule& module) { - ConvertPipelineEx(pipeline, renderpass, module, false, false); + ConvertPipelineEx(pipeline, formats, module, false, false); } -void BlitImageHelper::ConvertPipelineDepthTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass, +void BlitImageHelper::ConvertPipelineDepthTargetEx(vk::Pipeline& pipeline, + const RenderingFormats& formats, vk::ShaderModule& module) { - ConvertPipelineEx(pipeline, renderpass, module, true, true); + ConvertPipelineEx(pipeline, formats, module, true, true); } -void BlitImageHelper::ConvertPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass, +void BlitImageHelper::ConvertPipeline(vk::Pipeline& pipeline, const RenderingFormats& formats, bool is_target_depth) { if (pipeline) { return; @@ -1775,9 +1751,10 @@ void BlitImageHelper::ConvertPipeline(vk::Pipeline& pipeline, VkRenderPass rende 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); + const VkPipelineRenderingCreateInfo rendering_ci = formats.CreateInfo(); pipeline = device.GetLogical().CreateGraphicsPipeline(VkGraphicsPipelineCreateInfo{ .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, - .pNext = nullptr, + .pNext = &rendering_ci, .flags = 0, .stageCount = static_cast(stages.size()), .pStages = stages.data(), @@ -1792,7 +1769,6 @@ void BlitImageHelper::ConvertPipeline(vk::Pipeline& pipeline, VkRenderPass rende : &PIPELINE_COLOR_BLEND_STATE_GENERIC_CREATE_INFO, .pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO, .layout = *one_texture_pipeline_layout, - .renderPass = renderpass, .subpass = 0, .basePipelineHandle = VK_NULL_HANDLE, .basePipelineIndex = 0, diff --git a/src/video_core/renderer_vulkan/blit_image.h b/src/video_core/renderer_vulkan/blit_image.h index bf9bdfdc41..d4038c8dae 100644 --- a/src/video_core/renderer_vulkan/blit_image.h +++ b/src/video_core/renderer_vulkan/blit_image.h @@ -11,6 +11,7 @@ #include "video_core/engines/fermi_2d.h" #include "video_core/renderer_vulkan/vk_descriptor_pool.h" +#include "video_core/renderer_vulkan/vk_render_pass_cache.h" #include "video_core/surface.h" #include "video_core/texture_cache/types.h" #include "video_core/vulkan_common/vulkan_wrapper.h" @@ -24,21 +25,20 @@ using VideoCommon::Region2D; class Device; class Framebuffer; class ImageView; -class RenderPassCache; class StateTracker; class Scheduler; struct BlitImagePipelineKey { constexpr auto operator<=>(const BlitImagePipelineKey&) const noexcept = default; - VkRenderPass renderpass; + RenderingFormats formats; Tegra::Engines::Fermi2D::Operation operation; }; struct BlitDepthStencilPipelineKey { constexpr auto operator<=>(const BlitDepthStencilPipelineKey&) const noexcept = default; - VkRenderPass renderpass; + RenderingFormats formats; bool depth_clear; u8 stencil_mask; u32 stencil_compare_mask; @@ -54,7 +54,7 @@ enum class MSAACopyFormatClass : u32 { struct MSAACopyPipelineKey { constexpr auto operator<=>(const MSAACopyPipelineKey&) const noexcept = default; - VkRenderPass renderpass; + RenderingFormats formats; VkSampleCountFlagBits samples; bool msaa_to_non_msaa; MSAACopyFormatClass format_class; @@ -63,7 +63,7 @@ struct MSAACopyPipelineKey { struct BlitMSAAPipelineKey { constexpr auto operator<=>(const BlitMSAAPipelineKey&) const noexcept = default; - VkRenderPass renderpass; + RenderingFormats formats; VkSampleCountFlagBits samples; }; @@ -124,16 +124,14 @@ public: u8 stencil_mask, u32 stencil_ref, u32 stencil_compare_mask, const Region2D& dst_region); - void CopyMSAA(RenderPassCache& render_pass_cache, VkImage dst_image, - VideoCore::Surface::PixelFormat dst_format, VkImage src_image, + void CopyMSAA(VkImage dst_image, VideoCore::Surface::PixelFormat dst_format, VkImage src_image, VideoCore::Surface::PixelFormat src_format, u32 num_samples, std::span copies, bool msaa_to_non_msaa); - void CopyMSAADepth(RenderPassCache& render_pass_cache, VkImage dst_image, - VideoCore::Surface::PixelFormat dst_format, VkImage src_image, - VideoCore::Surface::PixelFormat src_format, u32 num_samples, - std::span copies, bool copy_stencil, - bool msaa_to_non_msaa); + void CopyMSAADepth(VkImage dst_image, VideoCore::Surface::PixelFormat dst_format, + VkImage src_image, VideoCore::Surface::PixelFormat src_format, + u32 num_samples, std::span copies, + bool copy_stencil, bool msaa_to_non_msaa); private: struct MSAACopyAspectInfo { @@ -152,7 +150,7 @@ private: VkSampler sampler, VkImageView src_view, VkImageView src_stencil_view, bool blit_stencil); - void CopyMSAAImpl(VkRenderPass renderpass, VkPipeline pipeline, VkPipelineLayout layout, + void CopyMSAAImpl(const RenderingFormats& formats, VkPipeline pipeline, VkPipelineLayout layout, VkImage dst_image, VkFormat dst_vk_format, VkImage src_image, VkFormat src_vk_format, s32 scale_x, s32 scale_y, std::span copies, @@ -178,23 +176,24 @@ private: [[nodiscard]] VkPipeline FindOrEmplaceBlitColorMSAAPipeline(const BlitMSAAPipelineKey& key); [[nodiscard]] VkPipeline FindOrEmplaceBlitDepthStencilMSAAPipeline( const BlitMSAAPipelineKey& key, bool blit_stencil); - [[nodiscard]] VkPipeline FindOrEmplaceBlitDepthPipeline(VkRenderPass renderpass); - [[nodiscard]] VkPipeline FindOrEmplaceResolveDepthStencilPipeline(VkRenderPass renderpass, - bool resolve_stencil); + [[nodiscard]] VkPipeline FindOrEmplaceBlitDepthPipeline(const RenderingFormats& formats); + [[nodiscard]] VkPipeline FindOrEmplaceResolveDepthStencilPipeline( + const RenderingFormats& formats, bool resolve_stencil); - void ConvertPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass, bool is_target_depth); + void ConvertPipeline(vk::Pipeline& pipeline, const RenderingFormats& formats, + bool is_target_depth); - void ConvertDepthToColorPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass); + void ConvertDepthToColorPipeline(vk::Pipeline& pipeline, const RenderingFormats& formats); - void ConvertColorToDepthPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass); + void ConvertColorToDepthPipeline(vk::Pipeline& pipeline, const RenderingFormats& formats); - void ConvertPipelineEx(vk::Pipeline& pipeline, VkRenderPass renderpass, + void ConvertPipelineEx(vk::Pipeline& pipeline, const RenderingFormats& formats, vk::ShaderModule& module, bool single_texture, bool is_target_depth); - void ConvertPipelineColorTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass, + void ConvertPipelineColorTargetEx(vk::Pipeline& pipeline, const RenderingFormats& formats, vk::ShaderModule& module); - void ConvertPipelineDepthTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass, + void ConvertPipelineDepthTargetEx(vk::Pipeline& pipeline, const RenderingFormats& formats, vk::ShaderModule& module); const Device& device; @@ -256,21 +255,20 @@ private: std::vector msaa_copy_depth_stencil_pipelines; std::vector blit_msaa_color_keys; std::vector blit_msaa_color_pipelines; - std::vector blit_depth_keys; + std::vector blit_depth_keys; std::vector blit_depth_pipelines; std::vector blit_msaa_depth_keys; std::vector blit_msaa_depth_pipelines; std::vector blit_msaa_depth_stencil_keys; std::vector blit_msaa_depth_stencil_pipelines; - std::vector resolve_depth_keys; + std::vector resolve_depth_keys; std::vector resolve_depth_pipelines; - std::vector resolve_depth_stencil_keys; + std::vector resolve_depth_stencil_keys; std::vector resolve_depth_stencil_pipelines; struct MSAACopyResources { u64 tick; vk::ImageView src_view; vk::ImageView dst_view; - vk::Framebuffer framebuffer; }; std::deque msaa_copy_resources; vk::Pipeline convert_d32_to_r32_pipeline; diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index 767099eea2..950757a502 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp @@ -125,22 +125,15 @@ PixelFormat DecodeFormat(u8 encoded_format) { return PixelFormatFromRenderTargetFormat(format); } -RenderPassKey MakeRenderPassKey(const FixedPipelineState& state, const Device& device) { - RenderPassKey key{}; - std::ranges::transform(state.color_formats, key.color_formats.begin(), DecodeFormat); +RenderingFormats PipelineFormats(const FixedPipelineState& state, const Device& device) { + std::array color_formats; + std::ranges::transform(state.color_formats, color_formats.begin(), DecodeFormat); + PixelFormat depth_format = PixelFormat::Invalid; if (state.depth_enabled != 0) { - const auto depth_format{static_cast(state.depth_format.Value())}; - key.depth_format = PixelFormatFromDepthFormat(depth_format); - } else { - key.depth_format = PixelFormat::Invalid; + depth_format = PixelFormatFromDepthFormat( + static_cast(state.depth_format.Value())); } - key.samples = MaxwellToVK::MsaaMode(state.msaa_mode); - const bool has_color = std::ranges::any_of(key.color_formats, [](PixelFormat format) { - return format != PixelFormat::Invalid; - }); - key.resolve_color = - key.samples != VK_SAMPLE_COUNT_1_BIT && has_color && device.IsTiler(); - return key; + return MakeRenderingFormats(device, color_formats, depth_format); } size_t NumAttachments(const FixedPipelineState& state) { @@ -253,8 +246,8 @@ GraphicsPipeline::GraphicsPipeline( const Device& device_, DescriptorPool& descriptor_pool, GuestDescriptorQueue& guest_descriptor_queue_, DescriptorBufferRing& descriptor_buffer_ring_, Common::ThreadWorker* worker_thread, - PipelineStatistics* pipeline_statistics, RenderPassCache& render_pass_cache, - const GraphicsPipelineCacheKey& key_, std::array stages, + PipelineStatistics* pipeline_statistics, const GraphicsPipelineCacheKey& key_, + std::array stages, const std::array& infos) : key{key_}, device{device_}, texture_cache{texture_cache_}, buffer_cache{buffer_cache_}, pipeline_cache(pipeline_cache_), scheduler{scheduler_}, @@ -309,11 +302,10 @@ GraphicsPipeline::GraphicsPipeline( } } - auto func{[this, shader_notify, &render_pass_cache, pipeline_statistics] { - const VkRenderPass render_pass{render_pass_cache.Get(MakeRenderPassKey(key.state, device))}; + auto func{[this, shader_notify, pipeline_statistics] { Validate(); try { - MakePipeline(render_pass); + MakePipeline(PipelineFormats(key.state, device)); } catch (const vk::Exception& exception) { LOG_CRITICAL(Render_Vulkan, "Graphics pipeline build failed: {}", exception.what()); std::scoped_lock lock{build_mutex}; @@ -684,7 +676,7 @@ bool GraphicsPipeline::ConfigureDraw(const RescalingPushConstant& rescaling, return true; } -void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) { +void GraphicsPipeline::MakePipeline(const RenderingFormats& formats) { FixedPipelineState::DynamicState dynamic{}; if (!key.state.extended_dynamic_state) { dynamic = key.state.dynamic_state; @@ -1078,9 +1070,10 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) { flags |= VK_PIPELINE_CREATE_DESCRIPTOR_BUFFER_BIT_EXT; } + const VkPipelineRenderingCreateInfo rendering_ci = formats.CreateInfo(); pipeline = device.GetLogical().CreateGraphicsPipeline({ .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, - .pNext = nullptr, + .pNext = &rendering_ci, .flags = flags, .stageCount = static_cast(shader_stages.size()), .pStages = shader_stages.data(), @@ -1094,7 +1087,6 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) { .pColorBlendState = &color_blend_ci, .pDynamicState = &dynamic_state_ci, .layout = *pipeline_layout, - .renderPass = render_pass, .subpass = 0, .basePipelineHandle = nullptr, .basePipelineIndex = 0, diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h index b1ac5a3fcc..1371e8ee06 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h @@ -67,7 +67,6 @@ namespace Vulkan { class Device; class PipelineStatistics; -class RenderPassCache; class RescalingPushConstant; class RenderAreaPushConstant; class Scheduler; @@ -82,8 +81,8 @@ public: const Device& device, DescriptorPool& descriptor_pool, GuestDescriptorQueue& guest_descriptor_queue, DescriptorBufferRing& descriptor_buffer_ring, Common::ThreadWorker* worker_thread, - PipelineStatistics* pipeline_statistics, RenderPassCache& render_pass_cache, - const GraphicsPipelineCacheKey& key, std::array stages, + PipelineStatistics* pipeline_statistics, const GraphicsPipelineCacheKey& key, + std::array stages, const std::array& infos); bool HasDynamicVertexInput() const noexcept { return key.state.dynamic_vertex_input; } @@ -140,7 +139,7 @@ private: bool ConfigureDraw(const RescalingPushConstant& rescaling, const RenderAreaPushConstant& render_are); - void MakePipeline(VkRenderPass render_pass); + void MakePipeline(const RenderingFormats& formats); void Validate(); diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index d04d36046e..ce661670d5 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -343,12 +343,11 @@ PipelineCache::PipelineCache(Tegra::MaxwellDeviceMemoryManager& device_memory_, DescriptorPool& descriptor_pool_, GuestDescriptorQueue& guest_descriptor_queue_, DescriptorBufferRing& descriptor_buffer_ring_, - RenderPassCache& render_pass_cache_, BufferCache& buffer_cache_, - TextureCache& texture_cache_, VideoCore::ShaderNotify& shader_notify_) + BufferCache& buffer_cache_, TextureCache& texture_cache_, + VideoCore::ShaderNotify& shader_notify_) : VideoCommon::ShaderCache{device_memory_}, device{device_}, scheduler{scheduler_}, descriptor_pool{descriptor_pool_}, guest_descriptor_queue{guest_descriptor_queue_}, - descriptor_buffer_ring{descriptor_buffer_ring_}, - render_pass_cache{render_pass_cache_}, buffer_cache{buffer_cache_}, + descriptor_buffer_ring{descriptor_buffer_ring_}, buffer_cache{buffer_cache_}, texture_cache{texture_cache_}, shader_notify{shader_notify_}, use_asynchronous_shaders{Settings::values.use_asynchronous_shaders.GetValue()}, use_vulkan_pipeline_cache{Settings::values.use_vulkan_driver_pipeline_cache.GetValue()}, @@ -896,7 +895,7 @@ std::unique_ptr PipelineCache::CreateGraphicsPipeline( return std::make_unique( scheduler, buffer_cache, texture_cache, vulkan_pipeline_cache, &shader_notify, device, descriptor_pool, guest_descriptor_queue, descriptor_buffer_ring, thread_worker, statistics, - render_pass_cache, key, std::move(modules), infos); + key, std::move(modules), infos); } catch (const Shader::Exception& exception) { auto hash = key.Hash(); diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.h b/src/video_core/renderer_vulkan/vk_pipeline_cache.h index 71dfb46e3d..bebac7cb15 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.h +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.h @@ -85,7 +85,6 @@ class ComputePipeline; class DescriptorPool; class Device; class PipelineStatistics; -class RenderPassCache; class Scheduler; using VideoCommon::ShaderInfo; @@ -107,8 +106,7 @@ public: explicit PipelineCache(Tegra::MaxwellDeviceMemoryManager& device_memory_, const Device& device, Scheduler& scheduler, DescriptorPool& descriptor_pool, GuestDescriptorQueue& guest_descriptor_queue, - DescriptorBufferRing& descriptor_buffer_ring, - RenderPassCache& render_pass_cache, BufferCache& buffer_cache, + DescriptorBufferRing& descriptor_buffer_ring, BufferCache& buffer_cache, TextureCache& texture_cache, VideoCore::ShaderNotify& shader_notify_); ~PipelineCache(); @@ -153,7 +151,6 @@ private: DescriptorPool& descriptor_pool; GuestDescriptorQueue& guest_descriptor_queue; DescriptorBufferRing& descriptor_buffer_ring; - RenderPassCache& render_pass_cache; BufferCache& buffer_cache; TextureCache& texture_cache; VideoCore::ShaderNotify& shader_notify; diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index a1dc2259a5..37b8774f18 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -211,10 +211,10 @@ RasterizerVulkan::RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra device.IsExtDescriptorBufferSupported()), compute_pass_descriptor_queue(device, UpdateDescriptorQueue::COMPUTE_FRAME_PAYLOAD_SIZE), descriptor_buffer_ring(device, memory_allocator), - blit_image(device, scheduler, state_tracker, descriptor_pool), render_pass_cache(device), - texture_cache_runtime{ - device, scheduler, memory_allocator, staging_pool, - blit_image, render_pass_cache, descriptor_pool, compute_pass_descriptor_queue}, + blit_image(device, scheduler, state_tracker, descriptor_pool), + texture_cache_runtime{device, scheduler, memory_allocator, + staging_pool, blit_image, descriptor_pool, + compute_pass_descriptor_queue}, texture_cache(texture_cache_runtime, device_memory), buffer_cache_runtime(device, memory_allocator, scheduler, staging_pool, guest_descriptor_queue, compute_pass_descriptor_queue, descriptor_pool), @@ -223,8 +223,7 @@ RasterizerVulkan::RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra staging_pool, compute_pass_descriptor_queue, descriptor_pool, texture_cache), query_cache(gpu, *this, device_memory, query_cache_runtime), pipeline_cache(device_memory, device, scheduler, descriptor_pool, guest_descriptor_queue, - descriptor_buffer_ring, render_pass_cache, buffer_cache, texture_cache, - gpu.ShaderNotify()), + descriptor_buffer_ring, buffer_cache, texture_cache, gpu.ShaderNotify()), accelerate_dma(buffer_cache, texture_cache, scheduler), fence_manager(*this, gpu, texture_cache, buffer_cache, query_cache, device, scheduler) { scheduler.SetQueryCache(query_cache); diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h index e47104783b..2c45c6c081 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.h +++ b/src/video_core/renderer_vulkan/vk_rasterizer.h @@ -22,7 +22,6 @@ #include "video_core/renderer_vulkan/vk_fence_manager.h" #include "video_core/renderer_vulkan/vk_pipeline_cache.h" #include "video_core/renderer_vulkan/vk_query_cache.h" -#include "video_core/renderer_vulkan/vk_render_pass_cache.h" #include "video_core/renderer_vulkan/vk_staging_buffer_pool.h" #include "video_core/renderer_vulkan/vk_texture_cache.h" #include "video_core/renderer_vulkan/vk_update_descriptor.h" @@ -209,7 +208,6 @@ private: ComputePassDescriptorQueue compute_pass_descriptor_queue; DescriptorBufferRing descriptor_buffer_ring; BlitImageHelper blit_image; - RenderPassCache render_pass_cache; TextureCacheRuntime texture_cache_runtime; TextureCache texture_cache; diff --git a/src/video_core/renderer_vulkan/vk_render_pass_cache.cpp b/src/video_core/renderer_vulkan/vk_render_pass_cache.cpp index 8c0921e9e8..b6be5317e0 100644 --- a/src/video_core/renderer_vulkan/vk_render_pass_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_render_pass_cache.cpp @@ -4,9 +4,7 @@ // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include "common/container/unordered_map.h" - -#include +#include #include "video_core/renderer_vulkan/maxwell_to_vk.h" #include "video_core/renderer_vulkan/vk_render_pass_cache.h" @@ -19,109 +17,90 @@ namespace { using VideoCore::Surface::PixelFormat; using VideoCore::Surface::SurfaceType; - constexpr SurfaceType GetSurfaceType(PixelFormat format) { - switch (format) { - // Depth formats - case PixelFormat::D16_UNORM: - case PixelFormat::D32_FLOAT: - case PixelFormat::X8_D24_UNORM: - return SurfaceType::Depth; +struct AttachmentAspects { + bool depth; + bool stencil; +}; - // Stencil formats - case PixelFormat::S8_UINT: - return SurfaceType::Stencil; +constexpr SurfaceType GetSurfaceType(PixelFormat format) { + switch (format) { + case PixelFormat::D16_UNORM: + case PixelFormat::D32_FLOAT: + case PixelFormat::X8_D24_UNORM: + return SurfaceType::Depth; + case PixelFormat::S8_UINT: + return SurfaceType::Stencil; + case PixelFormat::D24_UNORM_S8_UINT: + case PixelFormat::S8_UINT_D24_UNORM: + case PixelFormat::D32_FLOAT_S8_UINT: + return SurfaceType::DepthStencil; + default: + return SurfaceType::ColorTexture; + } +} - // Depth+Stencil formats - case PixelFormat::D24_UNORM_S8_UINT: - case PixelFormat::S8_UINT_D24_UNORM: - case PixelFormat::D32_FLOAT_S8_UINT: - return SurfaceType::DepthStencil; +constexpr AttachmentAspects GetAttachmentAspects(PixelFormat format) { + const SurfaceType surface_type = GetSurfaceType(format); + return AttachmentAspects{ + .depth = surface_type == SurfaceType::Depth || surface_type == SurfaceType::DepthStencil, + .stencil = + surface_type == SurfaceType::Stencil || surface_type == SurfaceType::DepthStencil, + }; +} - // Everything else is a color texture - default: - return SurfaceType::ColorTexture; - } - } +VkFormat AttachmentFormat(const Device& device, PixelFormat format) { + return MaxwellToVK::SurfaceFormat(device, FormatType::Optimal, true, format).format; +} - VkAttachmentDescription2 AttachmentDescription(const Device& device, PixelFormat format, - VkSampleCountFlagBits samples, - VkAttachmentLoadOp load_op, - VkAttachmentStoreOp store_op) { - using MaxwellToVK::SurfaceFormat; +VkRenderingAttachmentInfo MakeAttachment(VkImageView view) { + return { + .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO, + .pNext = nullptr, + .imageView = view, + .imageLayout = VK_IMAGE_LAYOUT_GENERAL, + .resolveMode = VK_RESOLVE_MODE_NONE, + .resolveImageView = VK_NULL_HANDLE, + .resolveImageLayout = VK_IMAGE_LAYOUT_GENERAL, + .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD, + .storeOp = VK_ATTACHMENT_STORE_OP_STORE, + .clearValue = {}, + }; +} +} // Anonymous namespace - const SurfaceType surface_type = GetSurfaceType(format); - const bool has_stencil = surface_type == SurfaceType::DepthStencil || - surface_type == SurfaceType::Stencil; +ResolveModes PickResolveModes(const Device& device, PixelFormat format) { + constexpr VkResolveModeFlagBits mode = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT; - return { - .sType = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, - .pNext = nullptr, - .flags = {}, - .format = SurfaceFormat(device, FormatType::Optimal, true, format).format, - .samples = samples, - .loadOp = load_op, - .storeOp = store_op, - .stencilLoadOp = has_stencil ? load_op : VK_ATTACHMENT_LOAD_OP_DONT_CARE, - .stencilStoreOp = has_stencil ? store_op : VK_ATTACHMENT_STORE_OP_DONT_CARE, - .initialLayout = VK_IMAGE_LAYOUT_GENERAL, - .finalLayout = VK_IMAGE_LAYOUT_GENERAL, - }; - } + const AttachmentAspects aspects = GetAttachmentAspects(format); + const bool depth_mode_supported = (device.GetDepthResolveModes() & mode) != 0; + const bool stencil_mode_supported = (device.GetStencilResolveModes() & mode) != 0; - struct ResolveAspects { - bool depth; - bool stencil; - }; - - struct ResolveModes { - VkResolveModeFlagBits depth; - VkResolveModeFlagBits stencil; - }; - - constexpr ResolveAspects GetResolveAspects(PixelFormat format) { - const SurfaceType surface_type = GetSurfaceType(format); - return ResolveAspects{ - .depth = surface_type == SurfaceType::Depth || - surface_type == SurfaceType::DepthStencil, - .stencil = surface_type == SurfaceType::Stencil || - surface_type == SurfaceType::DepthStencil, - }; - } - - ResolveModes PickResolveModes(const Device& device, PixelFormat format) { - constexpr VkResolveModeFlagBits mode = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT; - - const ResolveAspects aspects = GetResolveAspects(format); - const bool depth_mode_supported = (device.GetDepthResolveModes() & mode) != 0; - const bool stencil_mode_supported = (device.GetStencilResolveModes() & mode) != 0; - - ResolveModes modes{ - .depth = VK_RESOLVE_MODE_NONE, - .stencil = VK_RESOLVE_MODE_NONE, - }; - if (aspects.depth && depth_mode_supported) { - modes.depth = mode; - } - if (aspects.stencil && stencil_mode_supported) { - modes.stencil = mode; - } - if (modes.depth == modes.stencil || device.SupportsIndependentResolveNone()) { - return modes; - } - if (modes.depth != VK_RESOLVE_MODE_NONE && stencil_mode_supported) { - modes.stencil = mode; - } else if (modes.stencil != VK_RESOLVE_MODE_NONE && depth_mode_supported) { - modes.depth = mode; - } - return modes; - } - } // Anonymous namespace + ResolveModes modes{ + .depth = VK_RESOLVE_MODE_NONE, + .stencil = VK_RESOLVE_MODE_NONE, + }; + if (aspects.depth && depth_mode_supported) { + modes.depth = mode; + } + if (aspects.stencil && stencil_mode_supported) { + modes.stencil = mode; + } + if (modes.depth == modes.stencil || device.SupportsIndependentResolveNone()) { + return modes; + } + if (modes.depth != VK_RESOLVE_MODE_NONE && stencil_mode_supported) { + modes.stencil = mode; + } else if (modes.stencil != VK_RESOLVE_MODE_NONE && depth_mode_supported) { + modes.depth = mode; + } + return modes; +} bool SupportsDepthStencilResolve(const Device& device, PixelFormat depth_format) { if (depth_format == PixelFormat::Invalid || !device.IsKhrDepthStencilResolveSupported()) { return false; } - const ResolveAspects aspects = GetResolveAspects(depth_format); + const AttachmentAspects aspects = GetAttachmentAspects(depth_format); if (!aspects.depth && !aspects.stencil) { return false; } @@ -133,142 +112,65 @@ bool SupportsDepthStencilResolve(const Device& device, PixelFormat depth_format) return modes.depth == modes.stencil || device.SupportsIndependentResolveNone(); } -RenderPassCache::RenderPassCache(const Device& device_) : device{&device_} {} +RenderingFormats MakeRenderingFormats(const Device& device, std::span colors, + PixelFormat depth) { + RenderingFormats formats{}; + for (size_t index = 0; index < colors.size(); ++index) { + if (colors[index] == PixelFormat::Invalid) { + continue; + } + formats.colors[index] = AttachmentFormat(device, colors[index]); + formats.num_colors = static_cast(index + 1); + } + if (depth == PixelFormat::Invalid) { + return formats; + } + const VkFormat depth_format = AttachmentFormat(device, depth); + const AttachmentAspects aspects = GetAttachmentAspects(depth); + if (aspects.depth) { + formats.depth = depth_format; + } + if (aspects.stencil) { + formats.stencil = depth_format; + } + return formats; +} -VkRenderPass RenderPassCache::Get(const RenderPassKey& key) { - std::scoped_lock lock{mutex}; - const auto [pair, is_new] = cache.try_emplace(key); - if (!is_new) { - return *pair->second; - } - static constexpr size_t MAX_ATTACHMENTS = - 2 * std::tuple_size_v + 2; - boost::container::static_vector descriptions; - std::array references{}; - u32 num_attachments{}; - u32 num_colors{}; - for (size_t index = 0; index < key.color_formats.size(); ++index) { - const PixelFormat format{key.color_formats[index]}; - const bool is_valid{format != PixelFormat::Invalid}; - references[index] = VkAttachmentReference2{ - .sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, - .pNext = nullptr, - .attachment = is_valid ? num_colors : VK_ATTACHMENT_UNUSED, - .layout = VK_IMAGE_LAYOUT_GENERAL, - .aspectMask = 0, - }; - if (is_valid) { - const VkAttachmentLoadOp load_op = (key.color_clear_mask & (1u << index)) != 0 - ? VK_ATTACHMENT_LOAD_OP_CLEAR - : VK_ATTACHMENT_LOAD_OP_LOAD; - const VkAttachmentStoreOp store_op = (key.color_discard_mask & (1u << index)) != 0 - ? VK_ATTACHMENT_STORE_OP_DONT_CARE - : VK_ATTACHMENT_STORE_OP_STORE; - descriptions.push_back( - AttachmentDescription(*device, format, key.samples, load_op, store_op)); - num_attachments = static_cast(index + 1); - ++num_colors; - } - } - const bool has_depth{key.depth_format != PixelFormat::Invalid}; - VkAttachmentReference2 depth_reference{}; - if (has_depth) { - depth_reference = VkAttachmentReference2{ - .sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, - .pNext = nullptr, - .attachment = num_colors, - .layout = VK_IMAGE_LAYOUT_GENERAL, - .aspectMask = 0, - }; - const VkAttachmentLoadOp depth_load_op = key.depth_stencil_clear - ? VK_ATTACHMENT_LOAD_OP_CLEAR - : VK_ATTACHMENT_LOAD_OP_LOAD; - const VkAttachmentStoreOp depth_store_op = key.depth_stencil_discard - ? VK_ATTACHMENT_STORE_OP_DONT_CARE - : VK_ATTACHMENT_STORE_OP_STORE; - descriptions.push_back(AttachmentDescription(*device, key.depth_format, key.samples, - depth_load_op, depth_store_op)); - } - std::array resolve_references{}; - const bool do_resolve_color = - key.resolve_color && key.samples != VK_SAMPLE_COUNT_1_BIT && num_colors > 0; - if (do_resolve_color) { - for (size_t index = 0; index < key.color_formats.size(); ++index) { - const PixelFormat format{key.color_formats[index]}; - const bool is_valid{format != PixelFormat::Invalid}; - resolve_references[index] = VkAttachmentReference2{ - .sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, - .pNext = nullptr, - .attachment = is_valid ? static_cast(descriptions.size()) - : VK_ATTACHMENT_UNUSED, - .layout = VK_IMAGE_LAYOUT_GENERAL, - .aspectMask = 0, - }; - if (is_valid) { - VkAttachmentDescription2 resolve_desc = - AttachmentDescription(*device, format, VK_SAMPLE_COUNT_1_BIT, - VK_ATTACHMENT_LOAD_OP_DONT_CARE, - VK_ATTACHMENT_STORE_OP_STORE); - resolve_desc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - descriptions.push_back(resolve_desc); - } - } - } - const bool do_resolve_depth_stencil = key.resolve_depth_stencil && has_depth && - key.samples != VK_SAMPLE_COUNT_1_BIT && - SupportsDepthStencilResolve(*device, key.depth_format); - VkAttachmentReference2 depth_resolve_reference{}; - if (do_resolve_depth_stencil) { - depth_resolve_reference = VkAttachmentReference2{ - .sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, - .pNext = nullptr, - .attachment = static_cast(descriptions.size()), - .layout = VK_IMAGE_LAYOUT_GENERAL, - .aspectMask = 0, - }; - VkAttachmentDescription2 resolve_desc = - AttachmentDescription(*device, key.depth_format, VK_SAMPLE_COUNT_1_BIT, - VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_STORE); - resolve_desc.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - descriptions.push_back(resolve_desc); - } - const ResolveModes resolve_modes = PickResolveModes(*device, key.depth_format); - const VkSubpassDescriptionDepthStencilResolve depth_stencil_resolve{ - .sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE, - .pNext = nullptr, - .depthResolveMode = resolve_modes.depth, - .stencilResolveMode = resolve_modes.stencil, - .pDepthStencilResolveAttachment = &depth_resolve_reference, +RenderingAttachments MakeRenderingAttachments(const RenderingFormats& formats, + std::span colors, + VkImageView depth, const VkRect2D& render_area, + u32 layers) { + RenderingAttachments attachments{ + .render_area = render_area, + .num_colors = formats.num_colors, + .layers = layers, }; - const VkSubpassDescription2 subpass{ - .sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2, - .pNext = do_resolve_depth_stencil ? &depth_stencil_resolve : nullptr, + attachments.colors.fill(MakeAttachment(VK_NULL_HANDLE)); + std::ranges::transform(colors, attachments.colors.begin(), MakeAttachment); + attachments.depth = MakeAttachment(VK_NULL_HANDLE); + attachments.stencil = attachments.depth; + if (formats.depth != VK_FORMAT_UNDEFINED) { + attachments.depth.imageView = depth; + } + if (formats.stencil != VK_FORMAT_UNDEFINED) { + attachments.stencil.imageView = depth; + } + return attachments; +} + +void BeginRendering(vk::CommandBuffer cmdbuf, const RenderingAttachments& attachments) { + cmdbuf.BeginRendering(VkRenderingInfo{ + .sType = VK_STRUCTURE_TYPE_RENDERING_INFO, + .pNext = nullptr, .flags = 0, - .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, + .renderArea = attachments.render_area, + .layerCount = attachments.layers, .viewMask = 0, - .inputAttachmentCount = 0, - .pInputAttachments = nullptr, - .colorAttachmentCount = num_attachments, - .pColorAttachments = references.data(), - .pResolveAttachments = do_resolve_color ? resolve_references.data() : nullptr, - .pDepthStencilAttachment = has_depth ? &depth_reference : nullptr, - .preserveAttachmentCount = 0, - .pPreserveAttachments = nullptr, - }; - pair->second = device->GetLogical().CreateRenderPass2({ - .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2, - .pNext = nullptr, - .flags = 0, - .attachmentCount = static_cast(descriptions.size()), - .pAttachments = descriptions.empty() ? nullptr : descriptions.data(), - .subpassCount = 1, - .pSubpasses = &subpass, - .dependencyCount = 0, - .pDependencies = nullptr, - .correlatedViewMaskCount = 0, - .pCorrelatedViewMasks = nullptr, + .colorAttachmentCount = attachments.num_colors, + .pColorAttachments = attachments.colors.data(), + .pDepthAttachment = &attachments.depth, + .pStencilAttachment = &attachments.stencil, }); - return *pair->second; } } // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/vk_render_pass_cache.h b/src/video_core/renderer_vulkan/vk_render_pass_cache.h index 0edad4639e..a9c5b4e6a5 100644 --- a/src/video_core/renderer_vulkan/vk_render_pass_cache.h +++ b/src/video_core/renderer_vulkan/vk_render_pass_cache.h @@ -6,77 +6,67 @@ #pragma once -#include -#include "common/container/unordered_map.h" +#include +#include -#include "common/container_hash.h" #include "video_core/surface.h" #include "video_core/vulkan_common/vulkan_wrapper.h" namespace Vulkan { -struct RenderPassKey { - bool operator==(const RenderPassKey&) const noexcept = default; - - std::array color_formats; - VideoCore::Surface::PixelFormat depth_format; - VkSampleCountFlagBits samples; - bool resolve_color; - bool resolve_depth_stencil; - u32 color_clear_mask; - bool depth_stencil_clear; - u32 color_discard_mask; - bool depth_stencil_discard; -}; - -} // namespace Vulkan - -namespace std { -template <> -struct hash { - static_assert(std::tuple_size_v <= 8); - static_assert(static_cast(VideoCore::Surface::PixelFormat::Invalid) <= 0xFF); - static_assert(static_cast(VideoCore::Surface::PixelFormat::Max) <= 0xFF); - static_assert(VK_SAMPLE_COUNT_64_BIT <= 0xFF); - - [[nodiscard]] size_t operator()(const Vulkan::RenderPassKey& key) const noexcept { - u64 formats = 0; - for (size_t index = 0; index < key.color_formats.size(); ++index) { - formats |= static_cast(key.color_formats[index]) << (index * 8); - } - const u64 state = static_cast(key.depth_format) | - (static_cast(key.samples) << 8) | - (static_cast(key.color_clear_mask) << 16) | - (static_cast(key.color_discard_mask) << 24) | - (static_cast(key.resolve_color) << 32) | - (static_cast(key.depth_stencil_clear) << 33) | - (static_cast(key.resolve_depth_stencil) << 34) | - (static_cast(key.depth_stencil_discard) << 35); - size_t seed = 0; - Common::HashCombine(seed, formats); - Common::HashCombine(seed, state); - return seed; - } -}; -} // namespace std - -namespace Vulkan { - class Device; +struct RenderingFormats { + constexpr auto operator<=>(const RenderingFormats&) const noexcept = default; + + [[nodiscard]] VkPipelineRenderingCreateInfo CreateInfo() const noexcept { + return { + .sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO, + .pNext = nullptr, + .viewMask = 0, + .colorAttachmentCount = num_colors, + .pColorAttachmentFormats = colors.data(), + .depthAttachmentFormat = depth, + .stencilAttachmentFormat = stencil, + }; + } + + std::array colors{}; + u32 num_colors{}; + VkFormat depth{}; + VkFormat stencil{}; +}; + +struct RenderingAttachments { + std::array colors; + VkRenderingAttachmentInfo depth; + VkRenderingAttachmentInfo stencil; + VkRect2D render_area; + u32 num_colors; + u32 layers; +}; + +struct ResolveModes { + VkResolveModeFlagBits depth; + VkResolveModeFlagBits stencil; +}; + [[nodiscard]] bool SupportsDepthStencilResolve(const Device& device, VideoCore::Surface::PixelFormat depth_format); -class RenderPassCache { -public: - explicit RenderPassCache(const Device& device_); +[[nodiscard]] ResolveModes PickResolveModes(const Device& device, + VideoCore::Surface::PixelFormat format); - VkRenderPass Get(const RenderPassKey& key); +[[nodiscard]] RenderingFormats MakeRenderingFormats( + const Device& device, std::span colors, + VideoCore::Surface::PixelFormat depth); -private: - const Device* device{}; - ::Common::unordered_map cache; - std::mutex mutex; -}; +[[nodiscard]] RenderingAttachments MakeRenderingAttachments(const RenderingFormats& formats, + std::span colors, + VkImageView depth, + const VkRect2D& render_area, + u32 layers); + +void BeginRendering(vk::CommandBuffer cmdbuf, const RenderingAttachments& attachments); } // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/vk_scheduler.cpp b/src/video_core/renderer_vulkan/vk_scheduler.cpp index 42ecc9c3c6..ec01fbfcae 100644 --- a/src/video_core/renderer_vulkan/vk_scheduler.cpp +++ b/src/video_core/renderer_vulkan/vk_scheduler.cpp @@ -108,45 +108,22 @@ 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(); +void Scheduler::BeginRenderPassImpl(const Framebuffer* framebuffer, + const RenderingAttachments& attachments) { PublishComputeWrites(); - state.renderpass = renderpass; - state.framebuffer = framebuffer_handle; - state.render_area = render_area; + state.framebuffer_id = framebuffer->Id(); ++renderpass_serial; renderpass_depth_writes = false; if (GPU::Logging::IsActive() && Settings::values.gpu_log_vulkan_calls.GetValue()) { + const VkExtent2D render_area = attachments.render_area.extent; 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); } - std::array values{}; - for (u32 i = 0; i < clear_value_count && i < values.size(); ++i) { - values[i] = clear_values[i]; - } - Record([renderpass, framebuffer_handle, render_area, values, clear_value_count]( - vk::CommandBuffer cmdbuf) { - const VkRenderPassBeginInfo renderpass_bi{ - .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, - .pNext = nullptr, - .renderPass = renderpass, - .framebuffer = framebuffer_handle, - .renderArea = - { - .offset = {.x = 0, .y = 0}, - .extent = render_area, - }, - .clearValueCount = clear_value_count, - .pClearValues = clear_value_count != 0 ? values.data() : nullptr, - }; - cmdbuf.BeginRenderPass(renderpass_bi, VK_SUBPASS_CONTENTS_INLINE); - }); + Record([attachments](vk::CommandBuffer cmdbuf) { BeginRendering(cmdbuf, attachments); }); num_renderpass_images = framebuffer->NumImages(); renderpass_images = framebuffer->Images(); renderpass_image_ranges = framebuffer->ImageRanges(); @@ -160,26 +137,30 @@ void Scheduler::RealizeDeferredClear() { const DeferredClear dc = deferred_clear; deferred_clear = {}; - std::array clear_values{}; - u32 count = 0; - const RenderPassKey& base = dc.framebuffer->RenderPassKeyBase(); - for (u32 slot = 0; slot < 8; ++slot) { - if (base.color_formats[slot] == VideoCore::Surface::PixelFormat::Invalid) { + RenderingAttachments attachments = dc.framebuffer->Attachments(); + for (u32 slot = 0; slot < attachments.num_colors; ++slot) { + if ((dc.color_clear_mask & (1u << slot)) == 0) { continue; } - clear_values[count++] = dc.color_values[slot]; + VkRenderingAttachmentInfo& attachment = attachments.colors[slot]; + attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + attachment.clearValue = dc.color_values[slot]; + if (dc.framebuffer->DiscardsMsaaColor()) { + attachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + } } - if (base.depth_format != VideoCore::Surface::PixelFormat::Invalid) { - clear_values[count++] = dc.depth_stencil_value; + if (dc.depth_stencil) { + for (VkRenderingAttachmentInfo* const attachment : + {&attachments.depth, &attachments.stencil}) { + attachment->loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + attachment->clearValue = dc.depth_stencil_value; + if (dc.framebuffer->DiscardsMsaaDepthStencil()) { + attachment->storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + } + } } - const u32 color_discard_mask = - dc.framebuffer->DiscardsMsaaColor() ? dc.color_clear_mask : 0u; - const bool depth_stencil_discard = - dc.depth_stencil && dc.framebuffer->DiscardsMsaaDepthStencil(); - const VkRenderPass renderpass = dc.framebuffer->RenderPassVariant( - dc.color_clear_mask, dc.depth_stencil, color_discard_mask, depth_stencil_discard); EndRenderPass(); - BeginRenderPassImpl(dc.framebuffer, renderpass, clear_values.data(), count); + BeginRenderPassImpl(dc.framebuffer, attachments); renderpass_depth_writes = dc.depth_stencil; } @@ -225,17 +206,12 @@ void Scheduler::RequestRenderpass(const Framebuffer* framebuffer) { RealizeDeferredClear(); 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) { + if (framebuffer->Id() == state.framebuffer_id) { return; } // Ends any active pass and realizes a deferred clear EndRenderPass(); - BeginRenderPassImpl(framebuffer, renderpass, nullptr, 0); + BeginRenderPassImpl(framebuffer, framebuffer->Attachments()); } void Scheduler::RequestOutsideRenderPassOperationContext() { @@ -427,7 +403,7 @@ void Scheduler::EndPendingOperations() { void Scheduler::EndRenderPass() { RealizeDeferredClear(); - if (!state.renderpass) { + if (state.framebuffer_id == 0) { return; } @@ -484,12 +460,12 @@ void Scheduler::EndRenderPass() .subresourceRange = range, }; } - cmdbuf.EndRenderPass(); + cmdbuf.EndRendering(); cmdbuf.PipelineBarrier(0, vk::Span(write_barrier, num_memory_barriers), {}, vk::Span(barriers.data(), num_images)); }); - state.renderpass = VkRenderPass{}; + state.framebuffer_id = 0; 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 a7109e4a48..e4fa647132 100644 --- a/src/video_core/renderer_vulkan/vk_scheduler.h +++ b/src/video_core/renderer_vulkan/vk_scheduler.h @@ -36,6 +36,7 @@ class GraphicsPipeline; class StateTracker; struct QueryCacheParams; +struct RenderingAttachments; /// The scheduler abstracts command buffer and fence management with an interface that's able to do /// OpenGL-like operations on Vulkan command buffers. @@ -77,11 +78,11 @@ 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.framebuffer_id != 0; } u64 ActiveRenderPassSerial() const noexcept { - if (state.renderpass) { + if (state.framebuffer_id != 0) { return renderpass_serial; } return (std::numeric_limits::max)(); @@ -285,9 +286,7 @@ private: }; struct State { - VkRenderPass renderpass{}; - VkFramebuffer framebuffer{}; - VkExtent2D render_area = {0, 0}; + u64 framebuffer_id = 0; GraphicsPipeline* graphics_pipeline = nullptr; bool is_rescaling = false; bool rescaling_defined = false; @@ -305,8 +304,8 @@ private: }; /// Begins a render pass for the given framebuffer, optionally with clear values. - void BeginRenderPassImpl(const Framebuffer* framebuffer, VkRenderPass renderpass, - const VkClearValue* clear_values, u32 clear_value_count); + void BeginRenderPassImpl(const Framebuffer* framebuffer, + const RenderingAttachments& attachments); /// If a deferred clear is pending. void RealizeDeferredClear(); diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index 04b4eabc07..2d3934468a 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp @@ -994,18 +994,42 @@ void BlitScale(Scheduler& scheduler, VkImage src_image, VkImage dst_image, const cmdbuf.PipelineBarrier(0, {}, {}, write_barriers); }); } +void RecordInitialLayout(Scheduler& scheduler, VkImage image, VkImageAspectFlags aspect_mask) { + const VkImageMemoryBarrier2 barrier{ + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2, + .pNext = nullptr, + .srcStageMask = VK_PIPELINE_STAGE_2_NONE, + .srcAccessMask = VK_ACCESS_2_NONE, + .dstStageMask = vk::PIPELINE_STAGE_IMAGE_USERS, + .dstAccessMask = vk::ACCESS_IMAGE_USERS, + .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, + .newLayout = VK_IMAGE_LAYOUT_GENERAL, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = image, + .subresourceRange{ + .aspectMask = aspect_mask, + .baseMipLevel = 0, + .levelCount = VK_REMAINING_MIP_LEVELS, + .baseArrayLayer = 0, + .layerCount = VK_REMAINING_ARRAY_LAYERS, + }, + }; + scheduler.RecordWithUploadBuffer([barrier](vk::CommandBuffer, vk::CommandBuffer upload_cmdbuf) { + upload_cmdbuf.PipelineBarrier(barrier); + }); +} } // Anonymous namespace TextureCacheRuntime::TextureCacheRuntime(const Device& device_, Scheduler& scheduler_, MemoryAllocator& memory_allocator_, StagingBufferPool& staging_buffer_pool_, BlitImageHelper& blit_image_helper_, - RenderPassCache& render_pass_cache_, DescriptorPool& descriptor_pool, ComputePassDescriptorQueue& compute_pass_descriptor_queue) : device{device_}, scheduler{scheduler_}, memory_allocator{memory_allocator_}, staging_buffer_pool{staging_buffer_pool_}, blit_image_helper{blit_image_helper_}, - render_pass_cache{render_pass_cache_}, resolution{Settings::values.resolution_info} { + resolution{Settings::values.resolution_info} { if (Settings::values.accelerate_astc.GetValue() == Settings::AstcDecodeMode::Gpu) { astc_decoder_pass.emplace(device, scheduler, descriptor_pool, staging_buffer_pool, compute_pass_descriptor_queue, memory_allocator); @@ -1159,6 +1183,7 @@ VkImageView TextureCacheRuntime::GetOrCreateResolveShadow(VkImage msaa_image, Vk .layerCount = layers, }, }); + RecordInitialLayout(scheduler, *shadow.image, aspect_mask); shadow.format = format; shadow.extent = extent; shadow.layers = layers; @@ -1485,10 +1510,6 @@ void TextureCacheRuntime::BlitImage(Framebuffer* dst_framebuffer, ImageView& dst } void TextureCacheRuntime::ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view) { - if (!dst->RenderPass()) { - return; - } - switch (dst_view.format) { case PixelFormat::R16_UNORM: if (src_view.format == PixelFormat::D16_UNORM) { @@ -1824,17 +1845,17 @@ void TextureCacheRuntime::CopyImageMSAA(Image& dst, Image& src, if ((dst_aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT) != 0) { const bool copies_stencil = (dst_aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT) != 0 && device.IsExtShaderStencilExportSupported(); - blit_image_helper.CopyMSAADepth(render_pass_cache, dst.Handle(), dst.info.format, - src.Handle(), src.info.format, num_samples, copies, - copies_stencil, msaa_to_non_msaa); + blit_image_helper.CopyMSAADepth(dst.Handle(), dst.info.format, src.Handle(), + src.info.format, num_samples, copies, copies_stencil, + msaa_to_non_msaa); return; } if ((dst_aspect_mask & VK_IMAGE_ASPECT_COLOR_BIT) == 0) { UNIMPLEMENTED_MSG("Copying images with different samples is not supported."); return; } - blit_image_helper.CopyMSAA(render_pass_cache, dst.Handle(), dst.info.format, src.Handle(), - src.info.format, num_samples, copies, msaa_to_non_msaa); + blit_image_helper.CopyMSAA(dst.Handle(), dst.info.format, src.Handle(), src.info.format, + num_samples, copies, msaa_to_non_msaa); } u64 TextureCacheRuntime::GetDeviceLocalMemory() const { @@ -2032,14 +2053,13 @@ void Image::UploadMemory(VkBuffer buffer, VkDeviceSize offset, } if (msaa_upload_is_depth) { - runtime->blit_image_helper.CopyMSAADepth(runtime->render_pass_cache, Handle(), - info.format, temp_vk_image, info.format, - info.num_samples, + runtime->blit_image_helper.CopyMSAADepth(Handle(), info.format, temp_vk_image, + info.format, info.num_samples, {image_copies.data(), image_copies.size()}, msaa_upload_copies_stencil, false); } else { - runtime->blit_image_helper.CopyMSAA(runtime->render_pass_cache, Handle(), info.format, - temp_vk_image, info.format, info.num_samples, + runtime->blit_image_helper.CopyMSAA(Handle(), info.format, temp_vk_image, info.format, + info.num_samples, {image_copies.data(), image_copies.size()}, false); } initialized = true; @@ -2165,13 +2185,11 @@ void Image::DownloadMemory(std::span buffers_span, std::span o if (msaa_download_is_depth) { runtime->blit_image_helper.CopyMSAADepth( - runtime->render_pass_cache, temp_vk_image, info.format, Handle(), info.format, - info.num_samples, {image_copies.data(), image_copies.size()}, - msaa_download_copies_stencil, true); + temp_vk_image, info.format, Handle(), info.format, info.num_samples, + {image_copies.data(), image_copies.size()}, msaa_download_copies_stencil, true); } else { - runtime->blit_image_helper.CopyMSAA(runtime->render_pass_cache, temp_vk_image, - info.format, Handle(), info.format, - info.num_samples, + runtime->blit_image_helper.CopyMSAA(temp_vk_image, info.format, Handle(), + info.format, info.num_samples, {image_copies.data(), image_copies.size()}, true); } @@ -2981,9 +2999,6 @@ Framebuffer::Framebuffer(TextureCacheRuntime& runtime, std::span color_buffers, ImageView* depth_buffer, bool is_rescaled_) { - boost::container::small_vector attachments; - RenderPassKey renderpass_key{}; + std::array color_formats{}; + std::array color_views{}; + PixelFormat depth_format = PixelFormat::Invalid; + VkImageView depth_view = VK_NULL_HANDLE; s32 num_layers = 1; is_rescaled = is_rescaled_; @@ -3010,15 +3027,15 @@ void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime, for (size_t index = 0; index < NUM_RT; ++index) { const ImageView* const color_buffer = color_buffers[index]; if (!color_buffer) { - renderpass_key.color_formats[index] = PixelFormat::Invalid; + color_formats[index] = PixelFormat::Invalid; continue; } width = (std::min)(width, is_rescaled ? resolution.ScaleUp(color_buffer->size.width) : color_buffer->size.width); height = (std::min)(height, is_rescaled ? resolution.ScaleUp(color_buffer->size.height) : color_buffer->size.height); - attachments.push_back(color_buffer->RenderTarget()); - renderpass_key.color_formats[index] = color_buffer->format; + color_views[index] = color_buffer->RenderTarget(); + color_formats[index] = color_buffer->format; num_layers = (std::max)(num_layers, color_buffer->range.extent.layers); images[num_images] = color_buffer->ImageHandle(); image_ranges[num_images] = MakeSubresourceRange(color_buffer); @@ -3026,7 +3043,7 @@ void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime, samples = color_buffer->Samples(); ++num_images; } - const size_t num_colors = attachments.size(); + const size_t num_colors = num_images; VkImage depth_image = VK_NULL_HANDLE; VkImageAspectFlags depth_aspect_mask = 0; if (depth_buffer) { @@ -3034,8 +3051,8 @@ void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime, : depth_buffer->size.width); height = (std::min)(height, is_rescaled ? resolution.ScaleUp(depth_buffer->size.height) : depth_buffer->size.height); - attachments.push_back(depth_buffer->RenderTarget()); - renderpass_key.depth_format = depth_buffer->format; + depth_view = depth_buffer->RenderTarget(); + depth_format = depth_buffer->format; num_layers = (std::max)(num_layers, depth_buffer->range.extent.layers); images[num_images] = depth_buffer->ImageHandle(); const VkImageSubresourceRange subresource_range = MakeSubresourceRange(depth_buffer); @@ -3046,70 +3063,60 @@ void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime, has_stencil = (subresource_range.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) != 0; depth_image = depth_buffer->ImageHandle(); depth_aspect_mask = subresource_range.aspectMask; - } else { - renderpass_key.depth_format = PixelFormat::Invalid; } - renderpass_key.samples = samples; const bool do_resolve_color = ENABLE_MSAA_TILER_RESOLVE && samples != VK_SAMPLE_COUNT_1_BIT && num_colors > 0 && runtime.device.IsTiler(); - renderpass_key.resolve_color = do_resolve_color; const bool do_resolve_depth_stencil = ENABLE_MSAA_TILER_RESOLVE && samples != VK_SAMPLE_COUNT_1_BIT && depth_image != VK_NULL_HANDLE && - runtime.device.IsTiler() && - SupportsDepthStencilResolve(runtime.device, renderpass_key.depth_format); - renderpass_key.resolve_depth_stencil = do_resolve_depth_stencil; + runtime.device.IsTiler() && SupportsDepthStencilResolve(runtime.device, depth_format); discard_msaa_color = ENABLE_MSAA_RESOLVE_CONSUME && ENABLE_MSAA_COLOR_DISCARD && do_resolve_color; discard_msaa_depth_stencil = ENABLE_MSAA_RESOLVE_CONSUME && ENABLE_MSAA_DEPTH_STENCIL_DISCARD && do_resolve_depth_stencil; - renderpass = runtime.render_pass_cache.Get(renderpass_key); - render_pass_key = renderpass_key; - render_pass_cache = &runtime.render_pass_cache; runtime_ptr = &runtime; + id = ++runtime.framebuffer_serial; render_area.width = (std::min)(render_area.width, width); render_area.height = (std::min)(render_area.height, height); + const u32 layers = static_cast((std::max)(num_layers, 1)); + formats = MakeRenderingFormats(runtime.device, color_formats, depth_format); + attachments = MakeRenderingAttachments(formats, color_views, depth_view, + VkRect2D{.offset = {0, 0}, .extent = render_area}, + layers); + if (do_resolve_color) { - const u32 layers = static_cast((std::max)(num_layers, 1)); for (size_t index = 0; index < NUM_RT; ++index) { - const PixelFormat format = renderpass_key.color_formats[index]; - if (format == PixelFormat::Invalid) { + if (color_formats[index] == PixelFormat::Invalid) { continue; } - const VkFormat vk_format = - MaxwellToVK::SurfaceFormat(runtime.device, FormatType::Optimal, true, format).format; const VkImage msaa_image = images[rt_map[index]]; - attachments.push_back(runtime.GetOrCreateResolveShadow( - msaa_image, vk_format, render_area, layers, VK_IMAGE_ASPECT_COLOR_BIT)); + VkRenderingAttachmentInfo& attachment = attachments.colors[index]; + attachment.resolveMode = VK_RESOLVE_MODE_AVERAGE_BIT; + if (VideoCore::Surface::IsPixelFormatInteger(color_formats[index])) { + attachment.resolveMode = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT; + } + attachment.resolveImageView = runtime.GetOrCreateResolveShadow( + msaa_image, formats.colors[index], render_area, layers, VK_IMAGE_ASPECT_COLOR_BIT); resolve_shadow_images[num_resolve_shadows++] = msaa_image; } } if (do_resolve_depth_stencil) { - const u32 layers = static_cast((std::max)(num_layers, 1)); const VkFormat vk_format = - MaxwellToVK::SurfaceFormat(runtime.device, FormatType::Optimal, true, - renderpass_key.depth_format) + MaxwellToVK::SurfaceFormat(runtime.device, FormatType::Optimal, true, depth_format) .format; - attachments.push_back(runtime.GetOrCreateResolveShadow(depth_image, vk_format, render_area, - layers, depth_aspect_mask)); + const VkImageView resolve_view = runtime.GetOrCreateResolveShadow( + depth_image, vk_format, render_area, layers, depth_aspect_mask); + const ResolveModes modes = PickResolveModes(runtime.device, depth_format); + attachments.depth.resolveMode = modes.depth; + attachments.depth.resolveImageView = resolve_view; + attachments.stencil.resolveMode = modes.stencil; + attachments.stencil.resolveImageView = resolve_view; resolve_shadow_images[num_resolve_shadows++] = depth_image; } - - framebuffer = runtime.device.GetLogical().CreateFramebuffer({ - .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .renderPass = renderpass, - .attachmentCount = static_cast(attachments.size()), - .pAttachments = attachments.data(), - .width = render_area.width, - .height = render_area.height, - .layers = static_cast((std::max)(num_layers, 1)), - }); } void Framebuffer::MarkResolveShadowsUpToDate() const { @@ -3121,36 +3128,6 @@ void Framebuffer::MarkResolveShadowsUpToDate() const { } } -VkRenderPass Framebuffer::RenderPassVariant(u32 color_clear_mask, bool depth_stencil_clear, - u32 color_discard_mask, - bool depth_stencil_discard) const { - if (color_clear_mask == 0 && !depth_stencil_clear && color_discard_mask == 0 && - !depth_stencil_discard) { - return renderpass; - } - static_assert(NUM_RT <= 8); - const u32 variant_key = color_clear_mask | (color_discard_mask << 8) | - (static_cast(depth_stencil_clear) << 16) | - (static_cast(depth_stencil_discard) << 17); - for (u32 index = 0; index < num_memoized_variants; ++index) { - if (variant_keys[index] == variant_key) { - return variant_render_passes[index]; - } - } - RenderPassKey key = render_pass_key; - key.color_clear_mask = color_clear_mask; - key.depth_stencil_clear = depth_stencil_clear; - key.color_discard_mask = color_discard_mask; - key.depth_stencil_discard = depth_stencil_discard; - const VkRenderPass variant = render_pass_cache->Get(key); - if (num_memoized_variants < variant_keys.size()) { - variant_keys[num_memoized_variants] = variant_key; - variant_render_passes[num_memoized_variants] = variant; - ++num_memoized_variants; - } - return variant; -} - void TextureCacheRuntime::AccelerateImageUpload( Image& image, const StagingBufferRef& map, std::span swizzles) { @@ -3174,29 +3151,7 @@ void TextureCacheRuntime::AccelerateImageUpload( void TextureCacheRuntime::TransitionImageLayout(Image& image) { if (!image.ExchangeInitialization()) { - VkImageMemoryBarrier2 barrier{ - .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2, - .pNext = nullptr, - .srcStageMask = VK_PIPELINE_STAGE_2_NONE, - .srcAccessMask = VK_ACCESS_2_NONE, - .dstStageMask = vk::PIPELINE_STAGE_IMAGE_USERS, - .dstAccessMask = vk::ACCESS_IMAGE_USERS, - .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, - .newLayout = VK_IMAGE_LAYOUT_GENERAL, - .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .image = image.Handle(), - .subresourceRange{ - .aspectMask = image.AspectMask(), - .baseMipLevel = 0, - .levelCount = VK_REMAINING_MIP_LEVELS, - .baseArrayLayer = 0, - .layerCount = VK_REMAINING_ARRAY_LAYERS, - }, - }; - scheduler.RecordWithUploadBuffer([barrier](vk::CommandBuffer, vk::CommandBuffer upload_cmdbuf) { - upload_cmdbuf.PipelineBarrier(barrier); - }); + RecordInitialLayout(scheduler, image.Handle(), image.AspectMask()); } } diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h index 06ce5a5c32..c41583dcb4 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.h +++ b/src/video_core/renderer_vulkan/vk_texture_cache.h @@ -36,7 +36,6 @@ class Device; class Image; class ImageView; class Framebuffer; -class RenderPassCache; class StagingBufferPool; class Scheduler; @@ -46,7 +45,6 @@ public: MemoryAllocator& memory_allocator_, StagingBufferPool& staging_buffer_pool_, BlitImageHelper& blit_image_helper_, - RenderPassCache& render_pass_cache_, DescriptorPool& descriptor_pool, ComputePassDescriptorQueue& compute_pass_descriptor_queue); @@ -150,7 +148,6 @@ public: MemoryAllocator& memory_allocator; StagingBufferPool& staging_buffer_pool; BlitImageHelper& blit_image_helper; - RenderPassCache& render_pass_cache; std::optional astc_decoder_pass; std::optional bl_unswizzle_2d_pass; std::optional bl_unswizzle_3d_pass; @@ -184,6 +181,7 @@ public: std::vector msaa_scratch_images; ::Common::unordered_map resolve_shadows; std::vector> pending_resolve_shadows; + u64 framebuffer_serial{}; }; class Framebuffer { @@ -206,22 +204,18 @@ public: std::span color_buffers, ImageView* depth_buffer, bool is_rescaled = false); - [[nodiscard]] VkFramebuffer Handle() const noexcept { - return *framebuffer; + [[nodiscard]] u64 Id() const noexcept { + return id; } - [[nodiscard]] VkRenderPass RenderPass() const noexcept { - return renderpass; + [[nodiscard]] const RenderingFormats& Formats() const noexcept { + return formats; } - [[nodiscard]] const RenderPassKey& RenderPassKeyBase() const noexcept { - return render_pass_key; + [[nodiscard]] const RenderingAttachments& Attachments() const noexcept { + return attachments; } - [[nodiscard]] VkRenderPass RenderPassVariant(u32 color_clear_mask, bool depth_stencil_clear, - u32 color_discard_mask, - bool depth_stencil_discard) const; - [[nodiscard]] VkExtent2D RenderArea() const noexcept { return render_area; } @@ -271,10 +265,9 @@ public: void MarkResolveShadowsUpToDate() const; private: - static constexpr size_t NUM_MEMOIZED_RENDER_PASS_VARIANTS = 8; - - vk::Framebuffer framebuffer; - VkRenderPass renderpass{}; + RenderingFormats formats{}; + RenderingAttachments attachments{}; + u64 id{}; VkExtent2D render_area{}; VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT; u32 num_images = 0; @@ -287,13 +280,8 @@ private: std::array resolve_shadow_images{}; u32 num_resolve_shadows = 0; TextureCacheRuntime* runtime_ptr{nullptr}; - RenderPassKey render_pass_key{}; - RenderPassCache* render_pass_cache{nullptr}; bool discard_msaa_color{}; bool discard_msaa_depth_stencil{}; - mutable std::array variant_keys{}; - mutable std::array variant_render_passes{}; - mutable u32 num_memoized_variants{}; }; class Image : public VideoCommon::ImageBase { diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index 639552341e..756e6a49a2 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp @@ -1411,7 +1411,9 @@ void Device::RemoveUnsuitableExtensions() { extensions.synchronization2 = features.synchronization2.synchronization2; - if (!extensions.synchronization2 || !IsKhrCreateRenderPass2Supported()) { + extensions.dynamic_rendering = features.dynamic_rendering.dynamicRendering; + if (!extensions.synchronization2 || !extensions.dynamic_rendering || + !IsKhrCreateRenderPass2Supported()) { throw vk::Exception(VK_ERROR_FEATURE_NOT_PRESENT); } } diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index 12d2267876..a23f9b6334 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(KHR, VulkanMemoryModel, VULKAN_MEMORY_MODEL, vulkan_memory_model) #define FOR_EACH_VK_FEATURE_1_3(FEATURE) \ + FEATURE(KHR, DynamicRendering, DYNAMIC_RENDERING, dynamic_rendering) \ FEATURE(EXT, ImageRobustness, IMAGE_ROBUSTNESS, robust_image_access) \ FEATURE(EXT, ShaderDemoteToHelperInvocation, SHADER_DEMOTE_TO_HELPER_INVOCATION, \ shader_demote_to_helper_invocation) \ diff --git a/src/video_core/vulkan_common/vulkan_wrapper.cpp b/src/video_core/vulkan_common/vulkan_wrapper.cpp index 44e519a3fa..c4d99d08f4 100644 --- a/src/video_core/vulkan_common/vulkan_wrapper.cpp +++ b/src/video_core/vulkan_common/vulkan_wrapper.cpp @@ -89,6 +89,7 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept { X(vkCmdBeginConditionalRenderingEXT); X(vkCmdBeginQuery); X(vkCmdBeginRenderPass); + X(vkCmdBeginRendering); X(vkCmdBeginTransformFeedbackEXT); X(vkCmdBindDescriptorSets); X(vkCmdBindIndexBuffer); @@ -116,6 +117,7 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept { X(vkCmdEndConditionalRenderingEXT); X(vkCmdEndQuery); X(vkCmdEndRenderPass); + X(vkCmdEndRendering); X(vkCmdEndTransformFeedbackEXT); X(vkCmdFillBuffer); X(vkCmdPipelineBarrier2); @@ -257,6 +259,13 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept { Proc(dld.vkQueueSubmit2, dld, "vkQueueSubmit2KHR", device); } + if (!dld.vkCmdBeginRendering) { + Proc(dld.vkCmdBeginRendering, dld, "vkCmdBeginRenderingKHR", device); + } + if (!dld.vkCmdEndRendering) { + Proc(dld.vkCmdEndRendering, dld, "vkCmdEndRenderingKHR", device); + } + if (!dld.vkCreateRenderPass2) { Proc(dld.vkCreateRenderPass2, dld, "vkCreateRenderPass2KHR", device); } diff --git a/src/video_core/vulkan_common/vulkan_wrapper.h b/src/video_core/vulkan_common/vulkan_wrapper.h index 824b567e7f..2007658c35 100644 --- a/src/video_core/vulkan_common/vulkan_wrapper.h +++ b/src/video_core/vulkan_common/vulkan_wrapper.h @@ -238,6 +238,7 @@ struct DeviceDispatch : InstanceDispatch { PFN_vkCmdBeginConditionalRenderingEXT vkCmdBeginConditionalRenderingEXT{}; PFN_vkCmdBeginQuery vkCmdBeginQuery{}; PFN_vkCmdBeginRenderPass vkCmdBeginRenderPass{}; + PFN_vkCmdBeginRendering vkCmdBeginRendering{}; PFN_vkCmdBeginTransformFeedbackEXT vkCmdBeginTransformFeedbackEXT{}; PFN_vkCmdBindDescriptorSets vkCmdBindDescriptorSets{}; PFN_vkCmdBindIndexBuffer vkCmdBindIndexBuffer{}; @@ -266,6 +267,7 @@ struct DeviceDispatch : InstanceDispatch { PFN_vkCmdEndConditionalRenderingEXT vkCmdEndConditionalRenderingEXT{}; PFN_vkCmdEndQuery vkCmdEndQuery{}; PFN_vkCmdEndRenderPass vkCmdEndRenderPass{}; + PFN_vkCmdEndRendering vkCmdEndRendering{}; PFN_vkCmdEndTransformFeedbackEXT vkCmdEndTransformFeedbackEXT{}; PFN_vkCmdFillBuffer vkCmdFillBuffer{}; PFN_vkCmdPipelineBarrier2 vkCmdPipelineBarrier2{}; @@ -1194,6 +1196,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); }