From b0b481716270a04c2d76c4515f4e830a9fbc58c7 Mon Sep 17 00:00:00 2001 From: CamilleLaVey Date: Sat, 22 Aug 2026 02:49:06 -0400 Subject: [PATCH] [TEST] Adjustments on MSAA --- .../service/nvdrv/devices/nvhost_ctrl_gpu.cpp | 25 +++++++---- src/video_core/host_shaders/CMakeLists.txt | 42 +++++++++++++++++-- .../convert_msaa_to_non_msaa.frag | 11 ++++- .../convert_msaa_to_non_msaa_sint.frag | 22 ---------- .../convert_msaa_to_non_msaa_uint.frag | 22 ---------- .../convert_non_msaa_to_msaa.frag | 11 ++++- .../convert_non_msaa_to_msaa_sint.frag | 21 ---------- .../convert_non_msaa_to_msaa_uint.frag | 21 ---------- src/video_core/renderer_vulkan/blit_image.cpp | 1 + .../renderer_vulkan/vk_compute_pass.cpp | 32 ++++---------- .../renderer_vulkan/vk_compute_pass.h | 2 +- .../renderer_vulkan/vk_render_pass_cache.cpp | 41 ++++++++++++++++-- src/video_core/texture_cache/texture_cache.h | 12 ++++-- 13 files changed, 128 insertions(+), 135 deletions(-) delete mode 100644 src/video_core/host_shaders/convert_msaa_to_non_msaa_sint.frag delete mode 100644 src/video_core/host_shaders/convert_msaa_to_non_msaa_uint.frag delete mode 100644 src/video_core/host_shaders/convert_non_msaa_to_msaa_sint.frag delete mode 100644 src/video_core/host_shaders/convert_non_msaa_to_msaa_uint.frag diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp index b5a4e6a670..11f73d5130 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp @@ -295,7 +295,7 @@ NvResult nvhost_ctrl_gpu::ZBCSetTable(IoctlZbcSetTable& params) { break; } - if (zbc_used_color_entries >= zbc_table_size) { + if (zbc_used_color_entries >= ZBC_TABLE_SIZE) { LOG_WARNING(Service_NVDRV, "ZBCSetTable: color table is full, fmt={:#x}", params.format); return NvResult::InsufficientMemory; @@ -324,7 +324,7 @@ NvResult nvhost_ctrl_gpu::ZBCSetTable(IoctlZbcSetTable& params) { break; } - if (zbc_used_depth_entries >= zbc_table_size) { + if (zbc_used_depth_entries >= ZBC_TABLE_SIZE) { LOG_WARNING(Service_NVDRV, "ZBCSetTable: depth table is full, fmt={:#x}", depth_entry.format); return NvResult::InsufficientMemory; @@ -350,32 +350,41 @@ NvResult nvhost_ctrl_gpu::ZBCQueryTable(IoctlZbcQueryTable& params) { std::scoped_lock lk(zbc_mutex); if (params.type == 0) { - params.index_size = zbc_table_size; + params.index_size = ZBC_TABLE_SIZE; return NvResult::Success; } - if (params.index_size >= zbc_table_size) { - LOG_ERROR(Service_NVDRV, "ZBCQueryTable: invalid index {:#x}", params.index_size); - return NvResult::BadParameter; - } - switch (static_cast(params.type)) { case ZBCTypes::color: { + if (params.index_size >= zbc_used_color_entries) { + LOG_ERROR(Service_NVDRV, "ZBCQueryTable: invalid color index {:#x}", + params.index_size); + return NvResult::BadParameter; + } + const auto& colors = zbc_colors[params.index_size]; std::copy_n(colors.color_ds.begin(), colors.color_ds.size(), std::begin(params.color_ds)); std::copy_n(colors.color_l2.begin(), colors.color_l2.size(), std::begin(params.color_l2)); params.depth = 0; params.ref_cnt = colors.ref_cnt; params.format = colors.format; + params.index_size = zbc_used_color_entries; break; } case ZBCTypes::depth: { + if (params.index_size >= zbc_used_depth_entries) { + LOG_ERROR(Service_NVDRV, "ZBCQueryTable: invalid depth index {:#x}", + params.index_size); + return NvResult::BadParameter; + } + const auto& depth_entry = zbc_depths[params.index_size]; std::fill(std::begin(params.color_ds), std::end(params.color_ds), 0); std::fill(std::begin(params.color_l2), std::end(params.color_l2), 0); params.depth = depth_entry.depth; params.ref_cnt = depth_entry.ref_cnt; params.format = depth_entry.format; + params.index_size = zbc_used_depth_entries; break; } } diff --git a/src/video_core/host_shaders/CMakeLists.txt b/src/video_core/host_shaders/CMakeLists.txt index 2cfdbf5d97..f8b64c57e8 100644 --- a/src/video_core/host_shaders/CMakeLists.txt +++ b/src/video_core/host_shaders/CMakeLists.txt @@ -35,12 +35,8 @@ set(SHADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/convert_msaa_to_non_msaa.frag ${CMAKE_CURRENT_SOURCE_DIR}/convert_msaa_to_non_msaa_depth.frag ${CMAKE_CURRENT_SOURCE_DIR}/convert_msaa_to_non_msaa_depth_stencil.frag - ${CMAKE_CURRENT_SOURCE_DIR}/convert_msaa_to_non_msaa_sint.frag - ${CMAKE_CURRENT_SOURCE_DIR}/convert_msaa_to_non_msaa_uint.frag ${CMAKE_CURRENT_SOURCE_DIR}/convert_non_msaa_to_msaa.comp ${CMAKE_CURRENT_SOURCE_DIR}/convert_non_msaa_to_msaa.frag - ${CMAKE_CURRENT_SOURCE_DIR}/convert_non_msaa_to_msaa_sint.frag - ${CMAKE_CURRENT_SOURCE_DIR}/convert_non_msaa_to_msaa_uint.frag ${CMAKE_CURRENT_SOURCE_DIR}/convert_non_msaa_to_msaa_depth.frag ${CMAKE_CURRENT_SOURCE_DIR}/convert_non_msaa_to_msaa_depth_stencil.frag ${CMAKE_CURRENT_SOURCE_DIR}/convert_s8d24_to_abgr8.frag @@ -174,6 +170,44 @@ foreach(SOURCE_FILE IN ITEMS ${SHADER_FILES}) endif() endforeach() +# Integer variants of the MSAA conversion shaders. They only differ from the float +# source in the sampler and output types, so they are generated from it via defines. +set(SHADER_TYPE_VARIANTS + "convert_msaa_to_non_msaa.frag|sint|isampler2DMS|ivec4" + "convert_msaa_to_non_msaa.frag|uint|usampler2DMS|uvec4" + "convert_non_msaa_to_msaa.frag|sint|isampler2D|ivec4" + "convert_non_msaa_to_msaa.frag|uint|usampler2D|uvec4" +) + +foreach(VARIANT IN ITEMS ${SHADER_TYPE_VARIANTS}) + string(REPLACE "|" ";" VARIANT_PARTS ${VARIANT}) + list(GET VARIANT_PARTS 0 VARIANT_FILENAME) + list(GET VARIANT_PARTS 1 VARIANT_SUFFIX) + list(GET VARIANT_PARTS 2 VARIANT_SAMPLER) + list(GET VARIANT_PARTS 3 VARIANT_TEXEL) + + set(VARIANT_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/${VARIANT_FILENAME}) + get_filename_component(VARIANT_STEM ${VARIANT_FILENAME} NAME_WE) + get_filename_component(VARIANT_EXT ${VARIANT_FILENAME} EXT) + string(REPLACE "." "" VARIANT_EXT ${VARIANT_EXT}) + set(VARIANT_NAME ${VARIANT_STEM}_${VARIANT_SUFFIX}_${VARIANT_EXT}) + + string(TOUPPER ${VARIANT_NAME}_SPV VARIANT_VARIABLE_NAME) + set(VARIANT_HEADER_FILE ${SHADER_DIR}/${VARIANT_NAME}_spv.h) + add_custom_command( + OUTPUT + ${VARIANT_HEADER_FILE} + COMMAND + ${GLSLANGVALIDATOR} -V ${QUIET_FLAG} -I"${FIDELITYFX_INCLUDE_DIR}" ${GLSL_FLAGS} + -DSAMPLER_TYPE=${VARIANT_SAMPLER} -DTEXEL_TYPE=${VARIANT_TEXEL} + --variable-name ${VARIANT_VARIABLE_NAME} -o ${VARIANT_HEADER_FILE} ${VARIANT_SOURCE} + --target-env ${SPIR_V_VERSION} + MAIN_DEPENDENCY + ${VARIANT_SOURCE} + ) + set(SHADER_HEADERS ${SHADER_HEADERS} ${VARIANT_HEADER_FILE}) +endforeach() + foreach(FILEPATH IN ITEMS ${FIDELITYFX_FILES}) get_filename_component(FILENAME ${FILEPATH} NAME) string(REPLACE "." "_" HEADER_NAME ${FILENAME}) diff --git a/src/video_core/host_shaders/convert_msaa_to_non_msaa.frag b/src/video_core/host_shaders/convert_msaa_to_non_msaa.frag index 6c4aac3c82..8f7ec34d1a 100644 --- a/src/video_core/host_shaders/convert_msaa_to_non_msaa.frag +++ b/src/video_core/host_shaders/convert_msaa_to_non_msaa.frag @@ -3,7 +3,14 @@ #version 450 core -layout(binding = 0) uniform sampler2DMS msaa_in; +#ifndef SAMPLER_TYPE +#define SAMPLER_TYPE sampler2DMS +#endif +#ifndef TEXEL_TYPE +#define TEXEL_TYPE vec4 +#endif + +layout(binding = 0) uniform SAMPLER_TYPE msaa_in; layout(push_constant) uniform PushConstants { ivec2 dst_offset; @@ -11,7 +18,7 @@ layout(push_constant) uniform PushConstants { ivec2 scale; }; -layout(location = 0) out vec4 frag_color; +layout(location = 0) out TEXEL_TYPE frag_color; void main() { const ivec2 coord = ivec2(gl_FragCoord.xy) - dst_offset + src_offset; diff --git a/src/video_core/host_shaders/convert_msaa_to_non_msaa_sint.frag b/src/video_core/host_shaders/convert_msaa_to_non_msaa_sint.frag deleted file mode 100644 index fedd064cb0..0000000000 --- a/src/video_core/host_shaders/convert_msaa_to_non_msaa_sint.frag +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#version 450 core - -layout(binding = 0) uniform isampler2DMS msaa_in; - -layout(push_constant) uniform PushConstants { - ivec2 dst_offset; - ivec2 src_offset; - ivec2 scale; -}; - -layout(location = 0) out ivec4 frag_color; - -void main() { - const ivec2 coord = ivec2(gl_FragCoord.xy) - dst_offset + src_offset; - const ivec2 msaa_coord = coord / scale; - const ivec2 sample_offset = coord % scale; - const int sample_id = sample_offset.x + scale.x * sample_offset.y; - frag_color = texelFetch(msaa_in, msaa_coord, sample_id); -} diff --git a/src/video_core/host_shaders/convert_msaa_to_non_msaa_uint.frag b/src/video_core/host_shaders/convert_msaa_to_non_msaa_uint.frag deleted file mode 100644 index ec692752a0..0000000000 --- a/src/video_core/host_shaders/convert_msaa_to_non_msaa_uint.frag +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#version 450 core - -layout(binding = 0) uniform usampler2DMS msaa_in; - -layout(push_constant) uniform PushConstants { - ivec2 dst_offset; - ivec2 src_offset; - ivec2 scale; -}; - -layout(location = 0) out uvec4 frag_color; - -void main() { - const ivec2 coord = ivec2(gl_FragCoord.xy) - dst_offset + src_offset; - const ivec2 msaa_coord = coord / scale; - const ivec2 sample_offset = coord % scale; - const int sample_id = sample_offset.x + scale.x * sample_offset.y; - frag_color = texelFetch(msaa_in, msaa_coord, sample_id); -} diff --git a/src/video_core/host_shaders/convert_non_msaa_to_msaa.frag b/src/video_core/host_shaders/convert_non_msaa_to_msaa.frag index 19e23849d2..b5a93068a9 100644 --- a/src/video_core/host_shaders/convert_non_msaa_to_msaa.frag +++ b/src/video_core/host_shaders/convert_non_msaa_to_msaa.frag @@ -3,7 +3,14 @@ #version 450 core -layout(binding = 0) uniform sampler2D img_in; +#ifndef SAMPLER_TYPE +#define SAMPLER_TYPE sampler2D +#endif +#ifndef TEXEL_TYPE +#define TEXEL_TYPE vec4 +#endif + +layout(binding = 0) uniform SAMPLER_TYPE img_in; layout(push_constant) uniform PushConstants { ivec2 dst_offset; @@ -11,7 +18,7 @@ layout(push_constant) uniform PushConstants { ivec2 scale; }; -layout(location = 0) out vec4 frag_color; +layout(location = 0) out TEXEL_TYPE frag_color; void main() { const ivec2 msaa_coord = ivec2(gl_FragCoord.xy) - dst_offset; diff --git a/src/video_core/host_shaders/convert_non_msaa_to_msaa_sint.frag b/src/video_core/host_shaders/convert_non_msaa_to_msaa_sint.frag deleted file mode 100644 index 491c1bf5cc..0000000000 --- a/src/video_core/host_shaders/convert_non_msaa_to_msaa_sint.frag +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#version 450 core - -layout(binding = 0) uniform isampler2D img_in; - -layout(push_constant) uniform PushConstants { - ivec2 dst_offset; - ivec2 src_offset; - ivec2 scale; -}; - -layout(location = 0) out ivec4 frag_color; - -void main() { - const ivec2 msaa_coord = ivec2(gl_FragCoord.xy) - dst_offset; - const ivec2 sample_offset = ivec2(gl_SampleID % scale.x, gl_SampleID / scale.x); - const ivec2 coord = msaa_coord * scale + sample_offset + src_offset; - frag_color = texelFetch(img_in, coord, 0); -} diff --git a/src/video_core/host_shaders/convert_non_msaa_to_msaa_uint.frag b/src/video_core/host_shaders/convert_non_msaa_to_msaa_uint.frag deleted file mode 100644 index 08eb0cc843..0000000000 --- a/src/video_core/host_shaders/convert_non_msaa_to_msaa_uint.frag +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#version 450 core - -layout(binding = 0) uniform usampler2D img_in; - -layout(push_constant) uniform PushConstants { - ivec2 dst_offset; - ivec2 src_offset; - ivec2 scale; -}; - -layout(location = 0) out uvec4 frag_color; - -void main() { - const ivec2 msaa_coord = ivec2(gl_FragCoord.xy) - dst_offset; - const ivec2 sample_offset = ivec2(gl_SampleID % scale.x, gl_SampleID / scale.x); - const ivec2 coord = msaa_coord * scale + sample_offset + src_offset; - frag_color = texelFetch(img_in, coord, 0); -} diff --git a/src/video_core/renderer_vulkan/blit_image.cpp b/src/video_core/renderer_vulkan/blit_image.cpp index 09ffa4df12..b4500f34f8 100644 --- a/src/video_core/renderer_vulkan/blit_image.cpp +++ b/src/video_core/renderer_vulkan/blit_image.cpp @@ -1815,6 +1815,7 @@ void BlitImageHelper::CopyMSAADepth(RenderPassCache& render_pass_cache, VkImage } } } + scheduler.InvalidateState(); } VkPipeline BlitImageHelper::FindOrEmplaceMSAACopyPipeline(const MSAACopyPipelineKey& key) { diff --git a/src/video_core/renderer_vulkan/vk_compute_pass.cpp b/src/video_core/renderer_vulkan/vk_compute_pass.cpp index d1effe2c6c..f5c0c50768 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pass.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pass.cpp @@ -615,7 +615,6 @@ void ASTCDecoderPass::Assemble(Image& image, const StagingBufferRef& map, cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, 0, image_barrier); }); - scheduler.Finish(); } constexpr u32 BL3D_BINDING_INPUT_BUFFER = 0; @@ -720,17 +719,14 @@ void BlockLinearUnswizzle3DPass::Unswizzle( const u32 blocks_x = (image.info.size.width + 3) / 4; const u32 blocks_y = (image.info.size.height + 3) / 4; - const bool is_initialized = image.ExchangeInitialization(); - scheduler.RequestOutsideRenderPassOperationContext(); for (u32 z_offset = 0; z_offset < z_count; z_offset += MAX_BATCH_SLICES) { const u32 current_chunk_slices = (std::min)(MAX_BATCH_SLICES, z_count - z_offset); const u32 current_z_start = z_start + z_offset; UnswizzleChunk(image, swizzled, sw, params, blocks_x, blocks_y, - current_z_start, current_chunk_slices, is_initialized); + current_z_start, current_chunk_slices); } - scheduler.Finish(); } void BlockLinearUnswizzle3DPass::UnswizzleChunk( @@ -739,7 +735,7 @@ void BlockLinearUnswizzle3DPass::UnswizzleChunk( const VideoCommon::SwizzleParameters& sw, const BlockLinearSwizzle3DParams& params, u32 blocks_x, u32 blocks_y, - u32 z_start, u32 z_count, bool is_initialized) + u32 z_start, u32 z_count) { BlockLinearUnswizzle3DPushConstants pc{}; pc.origin[0] = params.origin[0]; @@ -783,7 +779,6 @@ void BlockLinearUnswizzle3DPass::UnswizzleChunk( const VkDeviceSize barrier_size = output_slice_size * z_count; const bool is_first_chunk = (z_start == 0); - const bool use_undefined_layout = !is_initialized && is_first_chunk; const VkBuffer out_buffer = *image.compute_unswizzle_buffer; const VkImage dst_image = image.Handle(); @@ -792,7 +787,7 @@ void BlockLinearUnswizzle3DPass::UnswizzleChunk( const u32 image_height = image.info.size.height; scheduler.Record([this, set, descriptor_data, pc, gx, gy, gz, z_start, z_count, - barrier_size, use_undefined_layout, out_buffer, dst_image, aspect, + barrier_size, is_first_chunk, out_buffer, dst_image, aspect, image_width, image_height ](vk::CommandBuffer cmdbuf) { @@ -819,23 +814,14 @@ void BlockLinearUnswizzle3DPass::UnswizzleChunk( .size = barrier_size, }; - VkAccessFlags pre_barrier_src_access = VK_ACCESS_SHADER_READ_BIT; - VkImageLayout pre_barrier_old_layout = VK_IMAGE_LAYOUT_GENERAL; - VkPipelineStageFlags pre_barrier_src_stages = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; - if (use_undefined_layout) { - pre_barrier_src_access = VkAccessFlags{}; - pre_barrier_old_layout = VK_IMAGE_LAYOUT_UNDEFINED; - pre_barrier_src_stages |= VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; - } else { - pre_barrier_src_stages |= vk::PIPELINE_STAGE_GRAPHICS_COMPUTE; - } - const VkImageMemoryBarrier pre_barrier{ .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .pNext = nullptr, - .srcAccessMask = pre_barrier_src_access, + .srcAccessMask = is_first_chunk ? VkAccessFlags{} : + static_cast(VK_ACCESS_TRANSFER_WRITE_BIT), .dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, - .oldLayout = pre_barrier_old_layout, + .oldLayout = is_first_chunk ? VK_IMAGE_LAYOUT_UNDEFINED : + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, .newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, @@ -845,7 +831,7 @@ void BlockLinearUnswizzle3DPass::UnswizzleChunk( // Single barrier handles both buffer and image cmdbuf.PipelineBarrier( - pre_barrier_src_stages, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, nullptr, buffer_barrier, pre_barrier @@ -1122,7 +1108,6 @@ void BlockLinearUnswizzle2DPass::Unswizzle( cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, 0, {}, {}, post_copy); }); - scheduler.Finish(); } namespace { @@ -1374,7 +1359,6 @@ void BlockLinearUnswizzle3DBufferPass::Unswizzle( cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, 0, {}, {}, post_copy); }); - scheduler.Finish(); } } // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/vk_compute_pass.h b/src/video_core/renderer_vulkan/vk_compute_pass.h index f3dc4b7697..5150e95b90 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pass.h +++ b/src/video_core/renderer_vulkan/vk_compute_pass.h @@ -156,7 +156,7 @@ public: const VideoCommon::SwizzleParameters& sw, const BlockLinearSwizzle3DParams& params, u32 blocks_x, u32 blocks_y, - u32 z_start, u32 z_count, bool is_initialized); + u32 z_start, u32 z_count); private: Scheduler& scheduler; diff --git a/src/video_core/renderer_vulkan/vk_render_pass_cache.cpp b/src/video_core/renderer_vulkan/vk_render_pass_cache.cpp index a514ac9022..a00d147db5 100644 --- a/src/video_core/renderer_vulkan/vk_render_pass_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_render_pass_cache.cpp @@ -229,6 +229,18 @@ VkRenderPass RenderPassCache::Get(const RenderPassKey& key) { .preserveAttachmentCount = 0, .pPreserveAttachments = nullptr, }; + const VkSubpassDependency feedback_loop_dependency{ + .srcSubpass = 0, + .dstSubpass = 0, + .srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | + VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | + VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, + .dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + .srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | + VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + .dstAccessMask = VK_ACCESS_SHADER_READ_BIT, + .dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT, + }; const VkSubpassDependency counter_resume_dependency{ .srcSubpass = 0, .dstSubpass = 0, @@ -324,6 +336,23 @@ VkRenderPass RenderPassCache::Get(const RenderPassKey& key) { counter_resume_dependency2.srcAccessMask = 0; counter_resume_dependency2.dstAccessMask = 0; } + const VkSubpassDependency2 feedback_loop_dependency2{ + .sType = VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2, + .pNext = nullptr, + .srcSubpass = feedback_loop_dependency.srcSubpass, + .dstSubpass = feedback_loop_dependency.dstSubpass, + .srcStageMask = feedback_loop_dependency.srcStageMask, + .dstStageMask = feedback_loop_dependency.dstStageMask, + .srcAccessMask = feedback_loop_dependency.srcAccessMask, + .dstAccessMask = feedback_loop_dependency.dstAccessMask, + .dependencyFlags = feedback_loop_dependency.dependencyFlags, + .viewOffset = 0, + }; + boost::container::static_vector dependencies2{ + feedback_loop_dependency2}; + if (can_resume_transform_feedback) { + dependencies2.push_back(counter_resume_dependency2); + } pair->second = device->GetLogical().CreateRenderPass2({ .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2, .pNext = nullptr, @@ -332,14 +361,18 @@ VkRenderPass RenderPassCache::Get(const RenderPassKey& key) { .pAttachments = descriptions2.empty() ? nullptr : descriptions2.data(), .subpassCount = 1, .pSubpasses = &subpass2, - .dependencyCount = can_resume_transform_feedback ? 1u : 0u, - .pDependencies = can_resume_transform_feedback ? &counter_resume_dependency2 : nullptr, + .dependencyCount = static_cast(dependencies2.size()), + .pDependencies = dependencies2.data(), .correlatedViewMaskCount = 0, .pCorrelatedViewMasks = nullptr, }); return *pair->second; } + boost::container::static_vector dependencies{feedback_loop_dependency}; + if (can_resume_transform_feedback) { + dependencies.push_back(counter_resume_dependency); + } pair->second = device->GetLogical().CreateRenderPass({ .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, .pNext = nullptr, @@ -348,8 +381,8 @@ VkRenderPass RenderPassCache::Get(const RenderPassKey& key) { .pAttachments = descriptions.empty() ? nullptr : descriptions.data(), .subpassCount = 1, .pSubpasses = &subpass, - .dependencyCount = can_resume_transform_feedback ? 1u : 0u, - .pDependencies = can_resume_transform_feedback ? &counter_resume_dependency : nullptr, + .dependencyCount = static_cast(dependencies.size()), + .pDependencies = dependencies.data(), }); return *pair->second; } diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index e3e9e213a8..92c034d4cd 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -279,11 +279,12 @@ void TextureCache

::CheckFeedbackLoop(std::span views) { const ImageId view_image_id = slot_image_views[view.id].image_id; { - bool is_continue = false; + bool aliases_color_rt = false; for (size_t i = 0; i < 8; ++i) - is_continue |= (rt_active_mask & (1u << i)) && view_image_id == rt_image_id[i]; - if (is_continue) - continue; + aliases_color_rt |= + (rt_active_mask & (1u << i)) && view_image_id == rt_image_id[i]; + if (aliases_color_rt) + return true; } if (depth_active && view_image_id == rt_depth_image_id) { return true; @@ -1710,6 +1711,9 @@ ImageId TextureCache

::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, DA if (!overlap.IsSafeGpuCopy()) { continue; } + if (overlap.info.num_samples != new_image.info.num_samples) { + continue; + } const auto alias_pointer = join_alias_indices.find(copy_object.id); if (alias_pointer == join_alias_indices.end()) { continue;