mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-10-06 14:09:58 +00:00
Rework dynamic rendering impl
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user