From 5db76784bda67fc1e195616cd9035f96907ba62d Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Thu, 9 Sep 2021 15:39:35 +0200 Subject: [PATCH] [dxbc] Accurately determine access flags for UAVs --- src/dxbc/dxbc_analysis.cpp | 23 +++++++++++++++++++++++ src/dxbc/dxbc_analysis.h | 1 + src/dxbc/dxbc_compiler.cpp | 28 ++++++++++++++-------------- src/dxvk/dxvk_context.cpp | 4 ++-- 4 files changed, 40 insertions(+), 16 deletions(-) diff --git a/src/dxbc/dxbc_analysis.cpp b/src/dxbc/dxbc_analysis.cpp index 8e5cf697f..4d59b8c8d 100644 --- a/src/dxbc/dxbc_analysis.cpp +++ b/src/dxbc/dxbc_analysis.cpp @@ -34,6 +34,7 @@ namespace dxvk { if (ins.dst[operandId].type == DxbcOperandType::UnorderedAccessView) { const uint32_t registerId = ins.dst[operandId].idx[0].offset; m_analysis->uavInfos[registerId].accessAtomicOp = true; + m_analysis->uavInfos[registerId].accessFlags |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT; } } break; @@ -49,9 +50,31 @@ namespace dxvk { m_analysis->usesKill = true; } break; + case DxbcInstClass::BufferLoad: { + uint32_t operandId = ins.op == DxbcOpcode::LdStructured ? 2 : 1; + + if (ins.src[operandId].type == DxbcOperandType::UnorderedAccessView) { + const uint32_t registerId = ins.src[operandId].idx[0].offset; + m_analysis->uavInfos[registerId].accessFlags |= VK_ACCESS_SHADER_READ_BIT; + } + } break; + + case DxbcInstClass::BufferStore: { + if (ins.dst[0].type == DxbcOperandType::UnorderedAccessView) { + const uint32_t registerId = ins.dst[0].idx[0].offset; + m_analysis->uavInfos[registerId].accessFlags |= VK_ACCESS_SHADER_WRITE_BIT; + } + } break; + case DxbcInstClass::TypedUavLoad: { const uint32_t registerId = ins.src[1].idx[0].offset; m_analysis->uavInfos[registerId].accessTypedLoad = true; + m_analysis->uavInfos[registerId].accessFlags |= VK_ACCESS_SHADER_READ_BIT; + } break; + + case DxbcInstClass::TypedUavStore: { + const uint32_t registerId = ins.dst[0].idx[0].offset; + m_analysis->uavInfos[registerId].accessFlags |= VK_ACCESS_SHADER_WRITE_BIT; } break; default: diff --git a/src/dxbc/dxbc_analysis.h b/src/dxbc/dxbc_analysis.h index 1102756a4..1c09cc9cb 100644 --- a/src/dxbc/dxbc_analysis.h +++ b/src/dxbc/dxbc_analysis.h @@ -19,6 +19,7 @@ namespace dxvk { struct DxbcUavInfo { bool accessTypedLoad = false; bool accessAtomicOp = false; + VkAccessFlags accessFlags = 0; }; /** diff --git a/src/dxbc/dxbc_compiler.cpp b/src/dxbc/dxbc_compiler.cpp index 4330a241d..fc0f76c56 100644 --- a/src/dxbc/dxbc_compiler.cpp +++ b/src/dxbc/dxbc_compiler.cpp @@ -1003,12 +1003,6 @@ namespace dxvk { if (ins.controls.uavFlags().test(DxbcUavFlag::GloballyCoherent)) m_module.decorate(varId, spv::DecorationCoherent); - // On GPUs which don't support storageImageReadWithoutFormat, - // we have to decorate untyped UAVs as write-only - if (isUav && imageFormat == spv::ImageFormatUnknown - && !m_moduleInfo.options.useStorageImageReadWithoutFormat) - m_module.decorate(varId, spv::DecorationNonReadable); - // Declare a specialization constant which will // store whether or not the resource is bound. const uint32_t specConstId = m_module.specConstBool(true); @@ -1060,19 +1054,24 @@ namespace dxvk { DxvkResourceSlot resource; resource.slot = bindingId; resource.view = typeInfo.vtype; - resource.access = VK_ACCESS_SHADER_READ_BIT; if (isUav) { resource.type = resourceType == DxbcResourceDim::Buffer ? VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER : VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; - resource.access |= VK_ACCESS_SHADER_WRITE_BIT; + resource.access = m_analysis->uavInfos[registerId].accessFlags; } else { resource.type = resourceType == DxbcResourceDim::Buffer ? VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER : VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; + resource.access = VK_ACCESS_SHADER_READ_BIT; } + if (!(resource.access & VK_ACCESS_SHADER_WRITE_BIT)) + m_module.decorate(varId, spv::DecorationNonWritable); + if (!(resource.access & VK_ACCESS_SHADER_READ_BIT)) + m_module.decorate(varId, spv::DecorationNonReadable); + m_resourceSlots.push_back(resource); } @@ -1137,9 +1136,6 @@ namespace dxvk { m_module.setDebugName(structType, str::format(isUav ? "u" : "t", registerId, "_t").c_str()); m_module.setDebugMemberName(structType, 0, "m"); - - if (!isUav) - m_module.decorate(varId, spv::DecorationNonWritable); } else { // Structured and raw buffers are represented as // texel buffers consisting of 32-bit integers. @@ -1210,10 +1206,14 @@ namespace dxvk { ? VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER : VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER); resource.view = VK_IMAGE_VIEW_TYPE_MAX_ENUM; - resource.access = VK_ACCESS_SHADER_READ_BIT; + resource.access = isUav + ? m_analysis->uavInfos[registerId].accessFlags + : VK_ACCESS_SHADER_READ_BIT; - if (isUav) - resource.access |= VK_ACCESS_SHADER_WRITE_BIT; + if (!(resource.access & VK_ACCESS_SHADER_WRITE_BIT)) + m_module.decorate(varId, spv::DecorationNonWritable); + if (!(resource.access & VK_ACCESS_SHADER_READ_BIT)) + m_module.decorate(varId, spv::DecorationNonReadable); m_resourceSlots.push_back(resource); } diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index 971079cba..78897fe23 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -4939,7 +4939,7 @@ namespace dxvk { // Skip write-after-write barriers if explicitly requested if ((m_barrierControl.test(DxvkBarrierControl::IgnoreWriteAfterWrite)) && (m_execBarriers.getSrcStages() == VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT) - && (srcAccess == DxvkAccess::Write) && (dstAccess == DxvkAccess::Write)) + && ((srcAccess | dstAccess) == DxvkAccess::Write)) continue; requiresBarrier = (srcAccess | dstAccess).test(DxvkAccess::Write); @@ -5133,7 +5133,7 @@ namespace dxvk { // Skip write-after-write barriers if explicitly requested if ((m_barrierControl.test(DxvkBarrierControl::IgnoreWriteAfterWrite)) - && (srcAccess == DxvkAccess::Write) && (dstAccess == DxvkAccess::Write)) + && ((srcAccess | dstAccess) == DxvkAccess::Write)) continue; requiresBarrier = (srcAccess | dstAccess).test(DxvkAccess::Write);