Rework dynamic rendering impl

This commit is contained in:
CamilleLaVey
2026-09-26 13:30:28 -04:00
parent be4bcbee85
commit 381d97639f
18 changed files with 458 additions and 668 deletions
+88 -112
View File
@@ -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<f32, 4>& 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<u32>(dst_offset.x) + dst_extent.width,
.height = static_cast<u32>(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<const VideoCommon::ImageCopy> 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<const VideoCommon::ImageCopy> copies,
bool msaa_to_non_msaa) {
const auto [samples_x, samples_y] = VideoCommon::SamplesLog2(static_cast<int>(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<u32>(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<u32>(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<u32>(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<u32>(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<u32>(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<u32>(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<u32>(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<u32>(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<const VideoCommon::ImageCopy> 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<const VideoCommon::ImageCopy> copies,
bool copy_stencil, bool msaa_to_non_msaa) {
const auto [samples_x, samples_y] = VideoCommon::SamplesLog2(static_cast<int>(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<u32>(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<u32>(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<u32>(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<u32>(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,
+24 -26
View File
@@ -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<const VideoCommon::ImageCopy> 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<const VideoCommon::ImageCopy> 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<const VideoCommon::ImageCopy> 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<const VideoCommon::ImageCopy> 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<vk::Pipeline> msaa_copy_depth_stencil_pipelines;
std::vector<BlitMSAAPipelineKey> blit_msaa_color_keys;
std::vector<vk::Pipeline> blit_msaa_color_pipelines;
std::vector<VkRenderPass> blit_depth_keys;
std::vector<RenderingFormats> blit_depth_keys;
std::vector<vk::Pipeline> blit_depth_pipelines;
std::vector<BlitMSAAPipelineKey> blit_msaa_depth_keys;
std::vector<vk::Pipeline> blit_msaa_depth_pipelines;
std::vector<BlitMSAAPipelineKey> blit_msaa_depth_stencil_keys;
std::vector<vk::Pipeline> blit_msaa_depth_stencil_pipelines;
std::vector<VkRenderPass> resolve_depth_keys;
std::vector<RenderingFormats> resolve_depth_keys;
std::vector<vk::Pipeline> resolve_depth_pipelines;
std::vector<VkRenderPass> resolve_depth_stencil_keys;
std::vector<RenderingFormats> resolve_depth_stencil_keys;
std::vector<vk::Pipeline> resolve_depth_stencil_pipelines;
struct MSAACopyResources {
u64 tick;
vk::ImageView src_view;
vk::ImageView dst_view;
vk::Framebuffer framebuffer;
};
std::deque<MSAACopyResources> msaa_copy_resources;
vk::Pipeline convert_d32_to_r32_pipeline;
@@ -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<PixelFormat, Maxwell::NumRenderTargets> 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<Tegra::DepthFormat>(state.depth_format.Value())};
key.depth_format = PixelFormatFromDepthFormat(depth_format);
} else {
key.depth_format = PixelFormat::Invalid;
depth_format = PixelFormatFromDepthFormat(
static_cast<Tegra::DepthFormat>(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<vk::ShaderModule, NUM_STAGES> stages,
PipelineStatistics* pipeline_statistics, const GraphicsPipelineCacheKey& key_,
std::array<vk::ShaderModule, NUM_STAGES> stages,
const std::array<const Shader::Info*, NUM_STAGES>& 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<u32>(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,
@@ -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<vk::ShaderModule, NUM_STAGES> stages,
PipelineStatistics* pipeline_statistics, const GraphicsPipelineCacheKey& key,
std::array<vk::ShaderModule, NUM_STAGES> stages,
const std::array<const Shader::Info*, NUM_STAGES>& 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();
@@ -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<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline(
return std::make_unique<GraphicsPipeline>(
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();
@@ -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;
@@ -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);
@@ -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;
@@ -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 <boost/container/static_vector.hpp>
#include <algorithm>
#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<const PixelFormat> 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<u32>(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<decltype(RenderPassKey::color_formats)> + 2;
boost::container::static_vector<VkAttachmentDescription2, MAX_ATTACHMENTS> descriptions;
std::array<VkAttachmentReference2, 8> 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<u32>(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<VkAttachmentReference2, 8> 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<u32>(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<u32>(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<const VkImageView> 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<u32>(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
@@ -6,77 +6,67 @@
#pragma once
#include <mutex>
#include "common/container/unordered_map.h"
#include <array>
#include <span>
#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<VideoCore::Surface::PixelFormat, 8> 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<Vulkan::RenderPassKey> {
static_assert(std::tuple_size_v<decltype(Vulkan::RenderPassKey::color_formats)> <= 8);
static_assert(static_cast<u32>(VideoCore::Surface::PixelFormat::Invalid) <= 0xFF);
static_assert(static_cast<u32>(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<u64>(key.color_formats[index]) << (index * 8);
}
const u64 state = static_cast<u64>(key.depth_format) |
(static_cast<u64>(key.samples) << 8) |
(static_cast<u64>(key.color_clear_mask) << 16) |
(static_cast<u64>(key.color_discard_mask) << 24) |
(static_cast<u64>(key.resolve_color) << 32) |
(static_cast<u64>(key.depth_stencil_clear) << 33) |
(static_cast<u64>(key.resolve_depth_stencil) << 34) |
(static_cast<u64>(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<VkFormat, 8> colors{};
u32 num_colors{};
VkFormat depth{};
VkFormat stencil{};
};
struct RenderingAttachments {
std::array<VkRenderingAttachmentInfo, 8> 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<const VideoCore::Surface::PixelFormat> colors,
VideoCore::Surface::PixelFormat depth);
private:
const Device* device{};
::Common::unordered_map<RenderPassKey, vk::RenderPass> cache;
std::mutex mutex;
};
[[nodiscard]] RenderingAttachments MakeRenderingAttachments(const RenderingFormats& formats,
std::span<const VkImageView> colors,
VkImageView depth,
const VkRect2D& render_area,
u32 layers);
void BeginRendering(vk::CommandBuffer cmdbuf, const RenderingAttachments& attachments);
} // namespace Vulkan
+29 -53
View File
@@ -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<VkClearValue, 9> 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<VkClearValue, 9> 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;
}
@@ -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<u64>::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();
@@ -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<VkBuffer> buffers_span, std::span<size_t> 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<ImageView*, NUM
.height = key.size.height,
}} {
CreateFramebuffer(runtime, color_buffers, depth_buffer, key.is_rescaled);
if (runtime.device.HasDebuggingToolAttached()) {
framebuffer.SetObjectNameEXT(VideoCommon::Name(key).c_str());
}
}
Framebuffer::Framebuffer(TextureCacheRuntime& runtime, ImageView* color_buffer,
@@ -2998,8 +3013,10 @@ Framebuffer::~Framebuffer() = default;
void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime,
std::span<ImageView*, NUM_RT> color_buffers,
ImageView* depth_buffer, bool is_rescaled_) {
boost::container::small_vector<VkImageView, NUM_RT * 2 + 2> attachments;
RenderPassKey renderpass_key{};
std::array<PixelFormat, NUM_RT> color_formats{};
std::array<VkImageView, NUM_RT> 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<u32>((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<u32>((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<u32>((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<u32>(attachments.size()),
.pAttachments = attachments.data(),
.width = render_area.width,
.height = render_area.height,
.layers = static_cast<u32>((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<u32>(depth_stencil_clear) << 16) |
(static_cast<u32>(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<const VideoCommon::SwizzleParameters> 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());
}
}
@@ -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<ASTCDecoderPass> astc_decoder_pass;
std::optional<BlockLinearUnswizzleImage2DPass> bl_unswizzle_2d_pass;
std::optional<BlockLinearUnswizzleImage3DPass> bl_unswizzle_3d_pass;
@@ -184,6 +181,7 @@ public:
std::vector<MsaaScratchImage> msaa_scratch_images;
::Common::unordered_map<VkImage, ResolveShadow> resolve_shadows;
std::vector<std::pair<u64, ResolveShadow>> pending_resolve_shadows;
u64 framebuffer_serial{};
};
class Framebuffer {
@@ -206,22 +204,18 @@ public:
std::span<ImageView*, NUM_RT> 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<VkImage, 9> 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<u32, NUM_MEMOIZED_RENDER_PASS_VARIANTS> variant_keys{};
mutable std::array<VkRenderPass, NUM_MEMOIZED_RENDER_PASS_VARIANTS> variant_render_passes{};
mutable u32 num_memoized_variants{};
};
class Image : public VideoCommon::ImageBase {
@@ -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);
}
}
@@ -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) \
@@ -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);
}
@@ -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);
}