[Vk] Improve Stencil Handling and Fix Read-After-Write Hazard #235

Merged
Shinmegumi merged 1 commit from wildcard/eden:fixRAWsyncerror into master 2025-08-23 20:04:48 +02:00

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@ -14,23 +17,55 @@
namespace Vulkan { namespace Vulkan {
namespace { namespace {
using VideoCore::Surface::PixelFormat; using VideoCore::Surface::PixelFormat;
using VideoCore::Surface::SurfaceType;
VkAttachmentDescription AttachmentDescription(const Device& device, PixelFormat format, constexpr SurfaceType GetSurfaceType(PixelFormat format) {
VkSampleCountFlagBits samples) { switch (format) {
using MaxwellToVK::SurfaceFormat; // Depth formats
return { case PixelFormat::D16_UNORM:
.flags = {}, case PixelFormat::D32_FLOAT:
.format = SurfaceFormat(device, FormatType::Optimal, true, format).format, case PixelFormat::X8_D24_UNORM:
.samples = samples, return SurfaceType::Depth;
.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
.storeOp = VK_ATTACHMENT_STORE_OP_STORE, // Stencil formats
.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD, case PixelFormat::S8_UINT:
.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE, return SurfaceType::Stencil;
.initialLayout = VK_IMAGE_LAYOUT_GENERAL,
.finalLayout = VK_IMAGE_LAYOUT_GENERAL, // Depth+Stencil formats
}; case PixelFormat::D24_UNORM_S8_UINT:
} case PixelFormat::S8_UINT_D24_UNORM:
} // Anonymous namespace case PixelFormat::D32_FLOAT_S8_UINT:
return SurfaceType::DepthStencil;
// Everything else is a color texture
default:
return SurfaceType::ColorTexture;
}
}
VkAttachmentDescription AttachmentDescription(const Device& device, PixelFormat format,
VkSampleCountFlagBits samples) {
using MaxwellToVK::SurfaceFormat;
const SurfaceType surface_type = GetSurfaceType(format);
const bool has_stencil = surface_type == SurfaceType::DepthStencil ||
surface_type == SurfaceType::Stencil;
return {
.flags = {},
.format = SurfaceFormat(device, FormatType::Optimal, true, format).format,
.samples = samples,
.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
.stencilLoadOp = has_stencil ? VK_ATTACHMENT_LOAD_OP_LOAD
: VK_ATTACHMENT_LOAD_OP_DONT_CARE,
.stencilStoreOp = has_stencil ? VK_ATTACHMENT_STORE_OP_STORE
: VK_ATTACHMENT_STORE_OP_DONT_CARE,
.initialLayout = VK_IMAGE_LAYOUT_GENERAL,
.finalLayout = VK_IMAGE_LAYOUT_GENERAL,
};
}
} // Anonymous namespace
RenderPassCache::RenderPassCache(const Device& device_) : device{&device_} {} RenderPassCache::RenderPassCache(const Device& device_) : device{&device_} {}
@ -78,6 +113,18 @@ VkRenderPass RenderPassCache::Get(const RenderPassKey& key) {
.preserveAttachmentCount = 0, .preserveAttachmentCount = 0,
.pPreserveAttachments = nullptr, .pPreserveAttachments = nullptr,
}; };
const VkSubpassDependency dependency{
.srcSubpass = 0, // Current subpass
.dstSubpass = 0, // Same subpass (self-dependency)
.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
};
pair->second = device->GetLogical().CreateRenderPass({ pair->second = device->GetLogical().CreateRenderPass({
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
.pNext = nullptr, .pNext = nullptr,
@ -86,8 +133,8 @@ VkRenderPass RenderPassCache::Get(const RenderPassKey& key) {
.pAttachments = descriptions.empty() ? nullptr : descriptions.data(), .pAttachments = descriptions.empty() ? nullptr : descriptions.data(),
.subpassCount = 1, .subpassCount = 1,
.pSubpasses = &subpass, .pSubpasses = &subpass,
.dependencyCount = 0, .dependencyCount = 1,
.pDependencies = nullptr, .pDependencies = &dependency,
}); });
return *pair->second; return *pair->second;
} }