[TEST] Ensure resolve shadow reads on msaa + shader extencil fallback

This commit is contained in:
CamilleLaVey
2026-08-19 22:40:54 -04:00
parent a4c37b5117
commit b754fcc49c
4 changed files with 52 additions and 16 deletions
+22 -10
View File
@@ -844,28 +844,40 @@ void BlitImageHelper::BlitDepthStencil(const Framebuffer* dst_framebuffer,
const Region2D& dst_region, const Region2D& src_region,
Tegra::Engines::Fermi2D::Filter filter,
Tegra::Engines::Fermi2D::Operation operation) {
if (!device.IsExtShaderStencilExportSupported()) {
return;
}
ASSERT(filter == Tegra::Engines::Fermi2D::Filter::Point);
ASSERT(operation == Tegra::Engines::Fermi2D::Operation::SrcCopy);
const bool blit_stencil = device.IsExtShaderStencilExportSupported();
const BlitImagePipelineKey key{
.renderpass = dst_framebuffer->RenderPass(),
.operation = operation,
};
const VkPipelineLayout layout = *two_textures_pipeline_layout;
VkPipelineLayout layout{};
VkPipeline pipeline{};
VkImageView src_stencil_view = VK_NULL_HANDLE;
if (blit_stencil) {
layout = *two_textures_pipeline_layout;
pipeline = FindOrEmplaceDepthStencilPipeline(key);
src_stencil_view = src_image_view.StencilView();
} else {
layout = *one_texture_pipeline_layout;
pipeline = FindOrEmplaceBlitDepthPipeline(key.renderpass);
}
const VkSampler sampler = *nearest_sampler;
const VkPipeline pipeline = FindOrEmplaceDepthStencilPipeline(key);
const VkImageView src_depth_view = src_image_view.DepthView();
const VkImageView src_stencil_view = src_image_view.StencilView();
RecordShaderReadBarrier(scheduler, src_image_view);
scheduler.RequestRenderpass(dst_framebuffer);
scheduler.Record([dst_region, src_region, pipeline, layout, sampler, src_depth_view,
src_stencil_view, this](vk::CommandBuffer cmdbuf) {
const VkDescriptorSet descriptor_set = two_textures_descriptor_allocator.Commit();
UpdateTwoTexturesDescriptorSet(device, descriptor_set, sampler, src_depth_view,
src_stencil_view);
src_stencil_view, blit_stencil, this](vk::CommandBuffer cmdbuf) {
VkDescriptorSet descriptor_set{};
if (blit_stencil) {
descriptor_set = two_textures_descriptor_allocator.Commit();
UpdateTwoTexturesDescriptorSet(device, descriptor_set, sampler, src_depth_view,
src_stencil_view);
} else {
descriptor_set = one_texture_descriptor_allocator.Commit();
UpdateOneTextureDescriptorSet(device, descriptor_set, sampler, src_depth_view);
}
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, descriptor_set,
nullptr);
@@ -132,6 +132,7 @@ void Scheduler::BeginRenderPassImpl(const Framebuffer* framebuffer, VkRenderPass
num_renderpass_images = framebuffer->NumImages();
renderpass_images = framebuffer->Images();
renderpass_image_ranges = framebuffer->ImageRanges();
framebuffer->MarkResolveShadowsUpToDate();
}
void Scheduler::RealizeDeferredClear() {
@@ -1019,7 +1019,6 @@ VkImageView TextureCacheRuntime::GetOrCreateResolveShadow(VkImage msaa_image, Vk
if (shadow.image && shadow.format == format && shadow.extent.width == extent.width &&
shadow.extent.height == extent.height && shadow.layers == layers &&
shadow.aspect_mask == aspect_mask) {
shadow.up_to_date = true;
return *shadow.view;
}
VkImageUsageFlags shadow_usage =
@@ -1069,7 +1068,7 @@ VkImageView TextureCacheRuntime::GetOrCreateResolveShadow(VkImage msaa_image, Vk
shadow.extent = extent;
shadow.layers = layers;
shadow.aspect_mask = aspect_mask;
shadow.up_to_date = true;
shadow.up_to_date = false;
return *shadow.view;
}
@@ -1082,6 +1081,13 @@ const TextureCacheRuntime::ResolveShadow* TextureCacheRuntime::GetValidResolveSh
return &it->second;
}
void TextureCacheRuntime::MarkResolveShadowUpToDate(VkImage msaa_image) {
const auto it = resolve_shadows.find(msaa_image);
if (it != resolve_shadows.end()) {
it->second.up_to_date = true;
}
}
void TextureCacheRuntime::InvalidateResolveShadow(VkImage msaa_image) {
const auto it = resolve_shadows.find(msaa_image);
if (it != resolve_shadows.end()) {
@@ -1753,10 +1759,6 @@ 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();
if ((dst_aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT) != 0 && !copies_stencil) {
UNIMPLEMENTED_MSG("Copying images with different samples is not supported.");
return;
}
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);
@@ -3059,6 +3061,7 @@ void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime,
renderpass = runtime.render_pass_cache.Get(renderpass_key);
render_pass_key = renderpass_key;
render_pass_cache = &runtime.render_pass_cache;
runtime_ptr = &runtime;
render_area.width = (std::min)(render_area.width, width);
render_area.height = (std::min)(render_area.height, height);
@@ -3075,6 +3078,7 @@ void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime,
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));
resolve_shadow_images[num_resolve_shadows++] = msaa_image;
continue;
}
VkImageCreateInfo resolve_ci{
@@ -3127,6 +3131,7 @@ void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime,
.format;
attachments.push_back(runtime.GetOrCreateResolveShadow(depth_image, vk_format, render_area,
layers, depth_aspect_mask));
resolve_shadow_images[num_resolve_shadows++] = depth_image;
}
num_color_buffers = static_cast<u32>(num_colors);
@@ -3143,6 +3148,15 @@ void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime,
});
}
void Framebuffer::MarkResolveShadowsUpToDate() const {
if (runtime_ptr == nullptr) {
return;
}
for (u32 index = 0; index < num_resolve_shadows; ++index) {
runtime_ptr->MarkResolveShadowUpToDate(resolve_shadow_images[index]);
}
}
VkRenderPass Framebuffer::RenderPassVariant(u32 color_clear_mask, bool depth_stencil_clear,
u32 color_discard_mask,
bool depth_stencil_discard) const {
@@ -131,6 +131,8 @@ public:
void InvalidateResolveShadow(VkImage msaa_image);
void MarkResolveShadowUpToDate(VkImage msaa_image);
void EraseResolveShadow(VkImage msaa_image);
std::span<const VkFormat> ViewFormats(PixelFormat format) {
@@ -257,6 +259,10 @@ public:
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;
private:
static constexpr size_t NUM_MEMOIZED_RENDER_PASS_VARIANTS = 8;
@@ -274,6 +280,9 @@ private:
bool is_rescaled{};
std::vector<vk::Image> resolve_images;
std::vector<vk::ImageView> resolve_image_views;
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{};