Some corrections towards HCR + Discard MSAA

This commit is contained in:
CamilleLaVey
2026-09-30 12:05:15 -04:00
parent 4f5fc58b6e
commit dd1c024efc
9 changed files with 185 additions and 209 deletions
@@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -7,8 +10,10 @@ layout (push_constant) uniform PushConstants {
vec4 clear_color;
};
layout(location = 0) out vec4 color;
layout(location = 0) out vec4 colors[8];
void main() {
color = clear_color;
for (int index = 0; index < 8; ++index) {
colors[index] = clear_color;
}
}
+114 -133
View File
@@ -279,6 +279,44 @@ constexpr VkPipelineDepthStencilStateCreateInfo PIPELINE_DEPTH_ONLY_STATE_CREATE
.maxDepthBounds = 0.0f,
};
constexpr VkPipelineDepthStencilStateCreateInfo PIPELINE_DEPTH_STENCIL_STATE_DISABLED_CREATE_INFO{
.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.depthTestEnable = VK_FALSE,
.depthWriteEnable = VK_FALSE,
.depthCompareOp = VK_COMPARE_OP_ALWAYS,
.depthBoundsTestEnable = VK_FALSE,
.stencilTestEnable = VK_FALSE,
.front = VkStencilOpState{},
.back = VkStencilOpState{},
.minDepthBounds = 0.0f,
.maxDepthBounds = 0.0f,
};
using BlendAttachments = std::array<VkPipelineColorBlendAttachmentState, 8>;
[[nodiscard]] VkPipelineColorBlendStateCreateInfo MakeColorBlendState(
const BlendAttachments& attachments, const RenderingFormats& formats) {
return VkPipelineColorBlendStateCreateInfo{
.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.logicOpEnable = VK_FALSE,
.logicOp = VK_LOGIC_OP_CLEAR,
.attachmentCount = formats.num_colors,
.pAttachments = attachments.data(),
.blendConstants = {0.0f, 0.0f, 0.0f, 0.0f},
};
}
[[nodiscard]] VkPipelineMultisampleStateCreateInfo MakeMultisampleState(
VkSampleCountFlagBits samples) {
VkPipelineMultisampleStateCreateInfo multisample_ci = PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
multisample_ci.rasterizationSamples = samples;
return multisample_ci;
}
template <VkFilter filter>
inline constexpr VkSamplerCreateInfo SAMPLER_CREATE_INFO{
.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
@@ -628,6 +666,8 @@ void BlitImageHelper::BlitColor(const Framebuffer* dst_framebuffer, const ImageV
const BlitImagePipelineKey key{
.formats = dst_framebuffer->Formats(),
.operation = operation,
.samples = dst_framebuffer->Samples(),
.target = 0,
};
VkSampler sampler = *nearest_sampler;
if (is_linear) {
@@ -645,6 +685,8 @@ void BlitImageHelper::BlitColor(const Framebuffer* dst_framebuffer, VkImageView
const BlitImagePipelineKey key{
.formats = dst_framebuffer->Formats(),
.operation = Tegra::Engines::Fermi2D::Operation::SrcCopy,
.samples = dst_framebuffer->Samples(),
.target = 0,
};
const VkPipelineLayout layout = *one_texture_pipeline_layout;
const VkPipeline pipeline = FindOrEmplaceColorPipeline(key);
@@ -763,6 +805,8 @@ void BlitImageHelper::BlitDepthStencil(const Framebuffer* dst_framebuffer,
const BlitImagePipelineKey key{
.formats = dst_framebuffer->Formats(),
.operation = operation,
.samples = dst_framebuffer->Samples(),
.target = 0,
};
VkPipeline pipeline{};
VkImageView src_stencil_view = VK_NULL_HANDLE;
@@ -778,26 +822,22 @@ 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->Formats());
Convert(*convert_d32_to_r32_pipeline, dst_framebuffer, src_image_view);
Convert(*convert_depth_to_float_frag, 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->Formats());
Convert(*convert_r32_to_d32_pipeline, dst_framebuffer, src_image_view);
Convert(*convert_float_to_depth_frag, 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->Formats());
Convert(*convert_d16_to_r16_pipeline, dst_framebuffer, src_image_view);
Convert(*convert_depth_to_float_frag, 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->Formats());
Convert(*convert_r16_to_d16_pipeline, dst_framebuffer, src_image_view);
Convert(*convert_float_to_depth_frag, dst_framebuffer, src_image_view);
}
void BlitImageHelper::ConvertABGR8ToD24S8(const Framebuffer* dst_framebuffer,
@@ -807,45 +847,37 @@ 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->Formats(),
convert_abgr8_to_d24s8_frag);
Convert(*convert_abgr8_to_d24s8_pipeline, dst_framebuffer, src_image_view);
Convert(*convert_abgr8_to_d24s8_frag, 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->Formats(),
convert_abgr8_to_d32f_frag);
Convert(*convert_abgr8_to_d32f_pipeline, dst_framebuffer, src_image_view);
Convert(*convert_abgr8_to_d32f_frag, dst_framebuffer, src_image_view);
}
void BlitImageHelper::ConvertD32FToABGR8(const Framebuffer* dst_framebuffer,
ImageView& src_image_view) {
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);
ConvertDepthStencil(*convert_d32f_to_abgr8_frag, dst_framebuffer, src_image_view);
}
void BlitImageHelper::ConvertD24S8ToABGR8(const Framebuffer* dst_framebuffer,
ImageView& src_image_view) {
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);
ConvertDepthStencil(*convert_d24s8_to_abgr8_frag, dst_framebuffer, src_image_view);
}
void BlitImageHelper::ConvertS8D24ToABGR8(const Framebuffer* dst_framebuffer,
ImageView& src_image_view) {
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);
ConvertDepthStencil(*convert_s8d24_to_abgr8_frag, dst_framebuffer, src_image_view);
}
void BlitImageHelper::ClearColor(const Framebuffer* dst_framebuffer, u8 color_mask,
void BlitImageHelper::ClearColor(const Framebuffer* dst_framebuffer, u32 target, u8 color_mask,
const std::array<f32, 4>& clear_color,
const Region2D& dst_region) {
const BlitImagePipelineKey key{
.formats = dst_framebuffer->Formats(),
.operation = Tegra::Engines::Fermi2D::Operation::BlendPremult,
.samples = dst_framebuffer->Samples(),
.target = target,
};
const VkPipeline pipeline = FindOrEmplaceClearColorPipeline(key);
const VkPipelineLayout layout = *clear_color_pipeline_layout;
@@ -873,6 +905,7 @@ void BlitImageHelper::ClearDepthStencil(const Framebuffer* dst_framebuffer, bool
.stencil_mask = stencil_mask,
.stencil_compare_mask = stencil_compare_mask,
.stencil_ref = stencil_ref,
.samples = dst_framebuffer->Samples(),
};
const VkPipeline pipeline = FindOrEmplaceClearStencilPipeline(key);
const VkPipelineLayout layout = *clear_color_pipeline_layout;
@@ -1079,9 +1112,11 @@ void BlitImageHelper::CopyMSAA(VkImage dst_image, VideoCore::Surface::PixelForma
aspect_info, false);
}
void BlitImageHelper::Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer,
void BlitImageHelper::Convert(VkShaderModule module, const Framebuffer* dst_framebuffer,
const ImageView& src_image_view) {
const VkPipelineLayout layout = *one_texture_pipeline_layout;
const VkPipeline pipeline =
FindOrEmplaceConvertPipeline(dst_framebuffer->Formats(), module, layout);
const VkImageView src_view = src_image_view.Handle(Shader::TextureType::Color2D);
const VkSampler sampler = *nearest_sampler;
const VkExtent2D extent = GetConversionExtent(src_image_view);
@@ -1128,9 +1163,12 @@ void BlitImageHelper::Convert(VkPipeline pipeline, const Framebuffer* dst_frameb
scheduler.InvalidateState();
}
void BlitImageHelper::ConvertDepthStencil(VkPipeline pipeline, const Framebuffer* dst_framebuffer,
void BlitImageHelper::ConvertDepthStencil(VkShaderModule module,
const Framebuffer* dst_framebuffer,
ImageView& src_image_view) {
const VkPipelineLayout layout = *two_textures_pipeline_layout;
const VkPipeline pipeline =
FindOrEmplaceConvertPipeline(dst_framebuffer->Formats(), module, layout);
const VkImageView src_depth_view = src_image_view.DepthView();
const VkImageView src_stencil_view = src_image_view.StencilView();
const VkSampler sampler = *nearest_sampler;
@@ -1187,28 +1225,12 @@ VkPipeline BlitImageHelper::FindOrEmplaceColorPipeline(const BlitImagePipelineKe
blit_color_keys.push_back(key);
const std::array stages = MakeStages(*full_screen_vert, *blit_color_to_color_frag);
const VkPipelineColorBlendAttachmentState blend_attachment{
.blendEnable = VK_FALSE,
.srcColorBlendFactor = VK_BLEND_FACTOR_ZERO,
.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO,
.colorBlendOp = VK_BLEND_OP_ADD,
.srcAlphaBlendFactor = VK_BLEND_FACTOR_ZERO,
.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO,
.alphaBlendOp = VK_BLEND_OP_ADD,
.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT,
};
BlendAttachments blend_attachments{};
blend_attachments[key.target] = PIPELINE_COLOR_BLEND_ATTACHMENT_STATE;
// TODO: programmable blending
const VkPipelineColorBlendStateCreateInfo color_blend_create_info{
.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.logicOpEnable = VK_FALSE,
.logicOp = VK_LOGIC_OP_CLEAR,
.attachmentCount = 1,
.pAttachments = &blend_attachment,
.blendConstants = {0.0f, 0.0f, 0.0f, 0.0f},
};
const VkPipelineColorBlendStateCreateInfo color_blend_create_info =
MakeColorBlendState(blend_attachments, key.formats);
const VkPipelineMultisampleStateCreateInfo multisample_ci = MakeMultisampleState(key.samples);
const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device);
const VkPipelineRenderingCreateInfo rendering_ci = key.formats.CreateInfo();
blit_color_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({
@@ -1222,8 +1244,8 @@ VkPipeline BlitImageHelper::FindOrEmplaceColorPipeline(const BlitImagePipelineKe
.pTessellationState = nullptr,
.pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO,
.pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
.pMultisampleState = &PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
.pDepthStencilState = nullptr,
.pMultisampleState = &multisample_ci,
.pDepthStencilState = &PIPELINE_DEPTH_STENCIL_STATE_DISABLED_CREATE_INFO,
.pColorBlendState = &color_blend_create_info,
.pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO,
.layout = *one_texture_pipeline_layout,
@@ -1241,6 +1263,7 @@ 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 VkPipelineMultisampleStateCreateInfo multisample_ci = MakeMultisampleState(key.samples);
const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device);
const VkPipelineRenderingCreateInfo rendering_ci = key.formats.CreateInfo();
blit_depth_stencil_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({
@@ -1254,7 +1277,7 @@ VkPipeline BlitImageHelper::FindOrEmplaceDepthStencilPipeline(const BlitImagePip
.pTessellationState = nullptr,
.pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO,
.pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
.pMultisampleState = &PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
.pMultisampleState = &multisample_ci,
.pDepthStencilState = &PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
.pColorBlendState = &PIPELINE_COLOR_BLEND_STATE_EMPTY_CREATE_INFO,
.pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO,
@@ -1284,16 +1307,11 @@ VkPipeline BlitImageHelper::FindOrEmplaceClearColorPipeline(const BlitImagePipel
.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT,
};
const VkPipelineColorBlendStateCreateInfo color_blend_state_generic_create_info{
.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.logicOpEnable = VK_FALSE,
.logicOp = VK_LOGIC_OP_CLEAR,
.attachmentCount = 1,
.pAttachments = &color_blend_attachment_state,
.blendConstants = {0.0f, 0.0f, 0.0f, 0.0f},
};
BlendAttachments blend_attachments{};
blend_attachments[key.target] = color_blend_attachment_state;
const VkPipelineColorBlendStateCreateInfo color_blend_create_info =
MakeColorBlendState(blend_attachments, key.formats);
const VkPipelineMultisampleStateCreateInfo multisample_ci = MakeMultisampleState(key.samples);
const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device);
const VkPipelineRenderingCreateInfo rendering_ci = key.formats.CreateInfo();
clear_color_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({
@@ -1307,9 +1325,9 @@ VkPipeline BlitImageHelper::FindOrEmplaceClearColorPipeline(const BlitImagePipel
.pTessellationState = nullptr,
.pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO,
.pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
.pMultisampleState = &PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
.pDepthStencilState = &PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
.pColorBlendState = &color_blend_state_generic_create_info,
.pMultisampleState = &multisample_ci,
.pDepthStencilState = &PIPELINE_DEPTH_STENCIL_STATE_DISABLED_CREATE_INFO,
.pColorBlendState = &color_blend_create_info,
.pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO,
.layout = *clear_color_pipeline_layout,
.subpass = 0,
@@ -1350,6 +1368,10 @@ VkPipeline BlitImageHelper::FindOrEmplaceClearStencilPipeline(
.minDepthBounds = 0.0f,
.maxDepthBounds = 0.0f,
};
const BlendAttachments blend_attachments{};
const VkPipelineColorBlendStateCreateInfo color_blend_create_info =
MakeColorBlendState(blend_attachments, key.formats);
const VkPipelineMultisampleStateCreateInfo multisample_ci = MakeMultisampleState(key.samples);
const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device);
const VkPipelineRenderingCreateInfo rendering_ci = key.formats.CreateInfo();
clear_stencil_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({
@@ -1363,9 +1385,9 @@ VkPipeline BlitImageHelper::FindOrEmplaceClearStencilPipeline(
.pTessellationState = nullptr,
.pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO,
.pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
.pMultisampleState = &PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
.pMultisampleState = &multisample_ci,
.pDepthStencilState = &depth_stencil_ci,
.pColorBlendState = &PIPELINE_COLOR_BLEND_STATE_GENERIC_CREATE_INFO,
.pColorBlendState = &color_blend_create_info,
.pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO,
.layout = *clear_color_pipeline_layout,
.subpass = 0,
@@ -1716,26 +1738,30 @@ VkPipeline BlitImageHelper::FindOrEmplaceMSAACopyDepthPipeline(const MSAACopyPip
return *pipelines.back();
}
void BlitImageHelper::ConvertDepthToColorPipeline(vk::Pipeline& pipeline,
const RenderingFormats& formats) {
ConvertPipeline(pipeline, formats, false);
}
void BlitImageHelper::ConvertColorToDepthPipeline(vk::Pipeline& pipeline,
const RenderingFormats& formats) {
ConvertPipeline(pipeline, formats, true);
}
void BlitImageHelper::ConvertPipelineEx(vk::Pipeline& pipeline, const RenderingFormats& formats,
vk::ShaderModule& module, bool single_texture,
bool is_target_depth) {
if (pipeline) {
return;
VkPipeline BlitImageHelper::FindOrEmplaceConvertPipeline(const RenderingFormats& formats,
VkShaderModule module,
VkPipelineLayout layout) {
const ConvertPipelineKey key{
.formats = formats,
.module = module,
};
const auto it = std::ranges::find(convert_keys, key);
if (it != convert_keys.end()) {
return *convert_pipelines[std::distance(convert_keys.begin(), it)];
}
const std::array stages = MakeStages(*full_screen_vert, *module);
const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device);
convert_keys.push_back(key);
const VkPipelineDepthStencilStateCreateInfo* depth_stencil_ci = nullptr;
const VkPipelineColorBlendStateCreateInfo* color_blend_ci =
&PIPELINE_COLOR_BLEND_STATE_GENERIC_CREATE_INFO;
if (formats.num_colors == 0) {
depth_stencil_ci = &PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
color_blend_ci = &PIPELINE_COLOR_BLEND_STATE_EMPTY_CREATE_INFO;
}
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{
convert_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.pNext = &rendering_ci,
.flags = 0,
@@ -1747,60 +1773,15 @@ void BlitImageHelper::ConvertPipelineEx(vk::Pipeline& pipeline, const RenderingF
.pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO,
.pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
.pMultisampleState = &PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
.pDepthStencilState = is_target_depth ? &PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO : nullptr,
.pColorBlendState = is_target_depth ? &PIPELINE_COLOR_BLEND_STATE_EMPTY_CREATE_INFO
: &PIPELINE_COLOR_BLEND_STATE_GENERIC_CREATE_INFO,
.pDepthStencilState = depth_stencil_ci,
.pColorBlendState = color_blend_ci,
.pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO,
.layout = single_texture ? *one_texture_pipeline_layout : *two_textures_pipeline_layout,
.layout = layout,
.subpass = 0,
.basePipelineHandle = VK_NULL_HANDLE,
.basePipelineIndex = 0,
});
}
void BlitImageHelper::ConvertPipelineColorTargetEx(vk::Pipeline& pipeline,
const RenderingFormats& formats,
vk::ShaderModule& module) {
ConvertPipelineEx(pipeline, formats, module, false, false);
}
void BlitImageHelper::ConvertPipelineDepthTargetEx(vk::Pipeline& pipeline,
const RenderingFormats& formats,
vk::ShaderModule& module) {
ConvertPipelineEx(pipeline, formats, module, true, true);
}
void BlitImageHelper::ConvertPipeline(vk::Pipeline& pipeline, const RenderingFormats& formats,
bool is_target_depth) {
if (pipeline) {
return;
}
VkShaderModule frag_shader =
is_target_depth ? *convert_float_to_depth_frag : *convert_depth_to_float_frag;
const std::array stages = MakeStages(*full_screen_vert, frag_shader);
const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device);
const VkPipelineRenderingCreateInfo rendering_ci = formats.CreateInfo();
pipeline = device.GetLogical().CreateGraphicsPipeline(VkGraphicsPipelineCreateInfo{
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.pNext = &rendering_ci,
.flags = 0,
.stageCount = static_cast<u32>(stages.size()),
.pStages = stages.data(),
.pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
.pInputAssemblyState = &input_assembly_ci,
.pTessellationState = nullptr,
.pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO,
.pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
.pMultisampleState = &PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
.pDepthStencilState = is_target_depth ? &PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO : nullptr,
.pColorBlendState = is_target_depth ? &PIPELINE_COLOR_BLEND_STATE_EMPTY_CREATE_INFO
: &PIPELINE_COLOR_BLEND_STATE_GENERIC_CREATE_INFO,
.pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO,
.layout = *one_texture_pipeline_layout,
.subpass = 0,
.basePipelineHandle = VK_NULL_HANDLE,
.basePipelineIndex = 0,
});
}));
return *convert_pipelines.back();
}
} // namespace Vulkan
+18 -28
View File
@@ -33,6 +33,8 @@ struct BlitImagePipelineKey {
RenderingFormats formats;
Tegra::Engines::Fermi2D::Operation operation;
VkSampleCountFlagBits samples;
u32 target;
};
struct BlitDepthStencilPipelineKey {
@@ -43,6 +45,14 @@ struct BlitDepthStencilPipelineKey {
u8 stencil_mask;
u32 stencil_compare_mask;
u32 stencil_ref;
VkSampleCountFlagBits samples;
};
struct ConvertPipelineKey {
constexpr auto operator<=>(const ConvertPipelineKey&) const noexcept = default;
RenderingFormats formats;
VkShaderModule module;
};
enum class MSAACopyFormatClass : u32 {
@@ -117,7 +127,7 @@ public:
void ConvertS8D24ToABGR8(const Framebuffer* dst_framebuffer, ImageView& src_image_view);
void ClearColor(const Framebuffer* dst_framebuffer, u8 color_mask,
void ClearColor(const Framebuffer* dst_framebuffer, u32 target, u8 color_mask,
const std::array<f32, 4>& clear_color, const Region2D& dst_region);
void ClearDepthStencil(const Framebuffer* dst_framebuffer, bool depth_clear, f32 clear_depth,
@@ -156,10 +166,10 @@ private:
std::span<const VideoCommon::ImageCopy> copies,
const MSAACopyAspectInfo& aspect_info, bool copy_stencil);
void Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer,
void Convert(VkShaderModule module, const Framebuffer* dst_framebuffer,
const ImageView& src_image_view);
void ConvertDepthStencil(VkPipeline pipeline, const Framebuffer* dst_framebuffer,
void ConvertDepthStencil(VkShaderModule module, const Framebuffer* dst_framebuffer,
ImageView& src_image_view);
[[nodiscard]] VkPipeline FindOrEmplaceColorPipeline(const BlitImagePipelineKey& key);
@@ -179,22 +189,9 @@ private:
[[nodiscard]] VkPipeline FindOrEmplaceBlitDepthPipeline(const RenderingFormats& formats);
[[nodiscard]] VkPipeline FindOrEmplaceResolveDepthStencilPipeline(
const RenderingFormats& formats, bool resolve_stencil);
void ConvertPipeline(vk::Pipeline& pipeline, const RenderingFormats& formats,
bool is_target_depth);
void ConvertDepthToColorPipeline(vk::Pipeline& pipeline, const RenderingFormats& formats);
void ConvertColorToDepthPipeline(vk::Pipeline& pipeline, const RenderingFormats& formats);
void ConvertPipelineEx(vk::Pipeline& pipeline, const RenderingFormats& formats,
vk::ShaderModule& module, bool single_texture, bool is_target_depth);
void ConvertPipelineColorTargetEx(vk::Pipeline& pipeline, const RenderingFormats& formats,
vk::ShaderModule& module);
void ConvertPipelineDepthTargetEx(vk::Pipeline& pipeline, const RenderingFormats& formats,
vk::ShaderModule& module);
[[nodiscard]] VkPipeline FindOrEmplaceConvertPipeline(const RenderingFormats& formats,
VkShaderModule module,
VkPipelineLayout layout);
const Device& device;
Scheduler& scheduler;
@@ -271,15 +268,8 @@ private:
vk::ImageView dst_view;
};
std::deque<MSAACopyResources> msaa_copy_resources;
vk::Pipeline convert_d32_to_r32_pipeline;
vk::Pipeline convert_r32_to_d32_pipeline;
vk::Pipeline convert_d16_to_r16_pipeline;
vk::Pipeline convert_r16_to_d16_pipeline;
vk::Pipeline convert_abgr8_to_d24s8_pipeline;
vk::Pipeline convert_abgr8_to_d32f_pipeline;
vk::Pipeline convert_d32f_to_abgr8_pipeline;
vk::Pipeline convert_d24s8_to_abgr8_pipeline;
vk::Pipeline convert_s8d24_to_abgr8_pipeline;
std::vector<ConvertPipelineKey> convert_keys;
std::vector<vk::Pipeline> convert_pipelines;
};
} // namespace Vulkan
@@ -1421,24 +1421,19 @@ void QueryCacheRuntime::HostConditionalRenderingCompareValueImpl(VideoCommon::Lo
impl->hcr_buffer = buffer->Handle();
impl->hcr_offset = offset;
}
if (impl->hcr_is_set) {
if (impl->hcr_setup.buffer == impl->hcr_buffer &&
impl->hcr_setup.offset == impl->hcr_offset) {
return;
}
VkConditionalRenderingFlagsEXT flags = 0;
if (is_equal) {
flags = VK_CONDITIONAL_RENDERING_INVERTED_BIT_EXT;
}
bool was_running = impl->is_hcr_running;
if (was_running) {
PauseHostConditionalRendering();
if (impl->hcr_is_set && impl->hcr_setup.buffer == impl->hcr_buffer &&
impl->hcr_setup.offset == impl->hcr_offset && impl->hcr_setup.flags == flags) {
return;
}
PauseHostConditionalRendering();
impl->hcr_setup.buffer = impl->hcr_buffer;
impl->hcr_setup.offset = impl->hcr_offset;
impl->hcr_setup.flags = is_equal ? VK_CONDITIONAL_RENDERING_INVERTED_BIT_EXT : 0;
impl->hcr_setup.flags = flags;
impl->hcr_is_set = true;
impl->is_hcr_running = false;
if (was_running) {
ResumeHostConditionalRendering();
}
}
void QueryCacheRuntime::HostConditionalRenderingCompareBCImpl(DAddr address, bool is_equal,
@@ -1455,20 +1450,16 @@ void QueryCacheRuntime::HostConditionalRenderingCompareBCImpl(DAddr address, boo
to_resolve = buffer->Handle();
to_resolve_offset = static_cast<u32>(offset);
}
bool was_running = impl->is_hcr_running;
if (was_running) {
PauseHostConditionalRendering();
}
PauseHostConditionalRendering();
impl->conditional_resolve_pass->Resolve(*impl->hcr_resolve_buffer, to_resolve,
to_resolve_offset, compare_to_zero);
impl->hcr_setup.buffer = *impl->hcr_resolve_buffer;
impl->hcr_setup.offset = 0;
impl->hcr_setup.flags = is_equal ? 0 : VK_CONDITIONAL_RENDERING_INVERTED_BIT_EXT;
impl->hcr_is_set = true;
impl->is_hcr_running = false;
if (was_running) {
ResumeHostConditionalRendering();
impl->hcr_setup.flags = 0;
if (!is_equal) {
impl->hcr_setup.flags = VK_CONDITIONAL_RENDERING_INVERTED_BIT_EXT;
}
impl->hcr_is_set = true;
}
bool QueryCacheRuntime::HostConditionalRenderingCompareValue(VideoCommon::LookupData object_1,
@@ -550,7 +550,8 @@ void RasterizerVulkan::Clear(u32 layer_count) {
Offset2D{.x = clear_rect.rect.offset.x + s32(clear_rect.rect.extent.width),
.y = clear_rect.rect.offset.y + s32(clear_rect.rect.extent.height)}};
request_renderpass();
blit_image.ClearColor(framebuffer, color_mask, regs.clear_color, dst_region);
blit_image.ClearColor(framebuffer, color_attachment, color_mask, regs.clear_color,
dst_region);
} else if (!clear_on_load ||
!scheduler.OverrideLoadOps(framebuffer, 1u << color_attachment,
VK_ATTACHMENT_LOAD_OP_CLEAR, clear_value)) {
@@ -4,8 +4,10 @@
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <algorithm>
#include <memory>
#include <mutex>
#include <span>
#include <thread>
#include <utility>
@@ -116,6 +118,7 @@ void Scheduler::DispatchWork() {
}
event_cv.notify_all();
recorded_attachments = nullptr;
ended_attachments = nullptr;
AcquireNewChunk();
}
}
@@ -169,29 +172,41 @@ bool Scheduler::OverrideLoadOps(const Framebuffer* framebuffer, u32 attachments,
if (!renderpass_pristine || recorded_attachments == nullptr) {
return false;
}
const auto set_load_op = [&](VkRenderingAttachmentInfo& attachment, bool discards_msaa) {
const auto set_load_op = [&](VkRenderingAttachmentInfo& attachment) {
attachment.loadOp = load_op;
attachment.clearValue = value;
if (discards_msaa && load_op == VK_ATTACHMENT_LOAD_OP_CLEAR) {
attachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
}
};
for (u32 slot = 0; slot < recorded_attachments->num_colors; ++slot) {
if ((attachments & (1u << slot)) != 0) {
set_load_op(recorded_attachments->colors[slot], framebuffer->DiscardsMsaaColor());
set_load_op(recorded_attachments->colors[slot]);
}
}
if ((attachments & DEPTH_ATTACHMENT_BIT) != 0) {
set_load_op(recorded_attachments->depth, framebuffer->DiscardsMsaaDepthStencil());
set_load_op(recorded_attachments->depth);
}
if ((attachments & STENCIL_ATTACHMENT_BIT) != 0) {
set_load_op(recorded_attachments->stencil, framebuffer->DiscardsMsaaDepthStencil());
set_load_op(recorded_attachments->stencil);
}
attachments_touched |= attachments;
attachments_written |= attachments;
return true;
}
void Scheduler::DiscardResolvedAttachments(VkImageView resolve_view) {
if (ended_attachments == nullptr) {
return;
}
const auto discard = [resolve_view](VkRenderingAttachmentInfo& attachment) {
if (attachment.resolveImageView == resolve_view) {
attachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
}
};
std::ranges::for_each(std::span(ended_attachments->colors).first(ended_attachments->num_colors),
discard);
discard(ended_attachments->depth);
discard(ended_attachments->stencil);
}
void Scheduler::RequestOutsideRenderPassOperationContext() {
EndRenderPass();
PublishComputeWrites();
@@ -420,8 +435,8 @@ void Scheduler::EndRenderPass()
}
if (recorded_attachments != nullptr) {
RelaxAttachmentOps(*recorded_attachments);
recorded_attachments = nullptr;
}
ended_attachments = std::exchange(recorded_attachments, nullptr);
query_cache->CounterClose(VideoCommon::QueryType::StreamingByteCount);
@@ -69,6 +69,8 @@ public:
bool OverrideLoadOps(const Framebuffer* framebuffer, u32 attachments,
VkAttachmentLoadOp load_op, const VkClearValue& value);
void DiscardResolvedAttachments(VkImageView resolve_view);
/// Requests the current execution context to be able to execute operations only allowed outside
/// of a renderpass.
void RequestOutsideRenderPassOperationContext();
@@ -338,6 +340,7 @@ private:
u32 attachments_touched = 0;
u32 attachments_written = 0;
RenderingAttachments* recorded_attachments = nullptr;
RenderingAttachments* ended_attachments = nullptr;
VkMemoryBarrier2 renderpass_write_barrier{};
VkMemoryBarrier2 compute_write_barrier{};
VkMemoryBarrier2 upload_write_barrier{};
@@ -1838,6 +1838,11 @@ void TextureCacheRuntime::CopyImageMSAA(Image& dst, Image& src,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, region);
cmdbuf.PipelineBarrier(0, {}, {}, post_barriers);
});
const bool is_color = aspect_mask == VK_IMAGE_ASPECT_COLOR_BIT;
if ((is_color && ENABLE_MSAA_COLOR_DISCARD) ||
(!is_color && ENABLE_MSAA_DEPTH_STENCIL_DISCARD)) {
scheduler.DiscardResolvedAttachments(*shadow->view);
}
return;
}
}
@@ -3076,11 +3081,6 @@ void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime,
samples != VK_SAMPLE_COUNT_1_BIT && depth_image != VK_NULL_HANDLE &&
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;
runtime_ptr = &runtime;
id = ++runtime.framebuffer_serial;
render_area.width = (std::min)(render_area.width, width);
@@ -250,14 +250,6 @@ public:
return is_rescaled;
}
[[nodiscard]] bool DiscardsMsaaColor() const noexcept {
return discard_msaa_color;
}
[[nodiscard]] bool DiscardsMsaaDepthStencil() const noexcept {
return discard_msaa_depth_stencil;
}
/// Records that a render pass has begun, so its resolve attachments will hold valid contents
/// once it ends.
void MarkResolveShadowsUpToDate() const;
@@ -278,8 +270,6 @@ private:
std::array<VkImage, 9> resolve_shadow_images{};
u32 num_resolve_shadows = 0;
TextureCacheRuntime* runtime_ptr{nullptr};
bool discard_msaa_color{};
bool discard_msaa_depth_stencil{};
};
class Image : public VideoCommon::ImageBase {