Skip to content

Commit

Permalink
[dxbc] Track bindings with order-invariant atomic stores
Browse files Browse the repository at this point in the history
  • Loading branch information
doitsujin committed Feb 15, 2025
1 parent d749a06 commit d904c3b
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 12 deletions.
36 changes: 30 additions & 6 deletions src/dxbc/dxbc_analysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,26 +30,46 @@ namespace dxvk {
switch (ins.opClass) {
case DxbcInstClass::Atomic: {
const uint32_t operandId = ins.dstCount - 1;

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;

DxvkAtomicStore store = DxvkAtomicStore::None;

switch (ins.op) {
case DxbcOpcode::AtomicAnd: store = DxvkAtomicStore::And; break;
case DxbcOpcode::AtomicOr: store = DxvkAtomicStore::Or; break;
case DxbcOpcode::AtomicXor: store = DxvkAtomicStore::Xor; break;
case DxbcOpcode::AtomicIAdd: store = DxvkAtomicStore::Add; break;
case DxbcOpcode::AtomicIMax: store = DxvkAtomicStore::IMax; break;
case DxbcOpcode::AtomicIMin: store = DxvkAtomicStore::IMin; break;
case DxbcOpcode::AtomicUMax: store = DxvkAtomicStore::UMax; break;
case DxbcOpcode::AtomicUMin: store = DxvkAtomicStore::UMin; break;
default: break;
}

if (m_analysis->uavInfos[registerId].atomicStore == DxvkAtomicStore::None)
m_analysis->uavInfos[registerId].atomicStore = store;

if (store == DxvkAtomicStore::None || m_analysis->uavInfos[registerId].atomicStore != store)
m_analysis->uavInfos[registerId].nonInvariantAccess = true;
}
} break;

case DxbcInstClass::TextureSample:
case DxbcInstClass::TextureGather:
case DxbcInstClass::TextureQueryLod:
case DxbcInstClass::VectorDeriv: {
m_analysis->usesDerivatives = true;
} break;

case DxbcInstClass::ControlFlow: {
if (ins.op == DxbcOpcode::Discard)
m_analysis->usesKill = true;
} break;

case DxbcInstClass::BufferLoad: {
uint32_t operandId = ins.op == DxbcOpcode::LdStructured ? 2 : 1;
bool sparseFeedback = ins.dstCount == 2;
Expand All @@ -58,30 +78,34 @@ namespace dxvk {
const uint32_t registerId = ins.src[operandId].idx[0].offset;
m_analysis->uavInfos[registerId].accessFlags |= VK_ACCESS_SHADER_READ_BIT;
m_analysis->uavInfos[registerId].sparseFeedback |= sparseFeedback;
m_analysis->uavInfos[registerId].nonInvariantAccess = true;
} else if (ins.src[operandId].type == DxbcOperandType::Resource) {
const uint32_t registerId = ins.src[operandId].idx[0].offset;
m_analysis->srvInfos[registerId].sparseFeedback |= sparseFeedback;
}
} 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;
m_analysis->uavInfos[registerId].nonInvariantAccess = true;
}
} 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;
m_analysis->uavInfos[registerId].nonInvariantAccess = true;
} break;

case DxbcInstClass::TypedUavStore: {
const uint32_t registerId = ins.dst[0].idx[0].offset;
m_analysis->uavInfos[registerId].accessFlags |= VK_ACCESS_SHADER_WRITE_BIT;
m_analysis->uavInfos[registerId].nonInvariantAccess = true;
} break;

default:
break;
}
Expand Down
8 changes: 5 additions & 3 deletions src/dxbc/dxbc_analysis.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@ namespace dxvk {
* will be used to generate image types.
*/
struct DxbcUavInfo {
bool accessTypedLoad = false;
bool accessAtomicOp = false;
bool sparseFeedback = false;
bool accessTypedLoad = false;
bool accessAtomicOp = false;
bool sparseFeedback = false;
bool nonInvariantAccess = false;
DxvkAtomicStore atomicStore = DxvkAtomicStore::None;
VkAccessFlags accessFlags = 0;
};

Expand Down
14 changes: 11 additions & 3 deletions src/dxbc/dxbc_compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1098,6 +1098,9 @@ namespace dxvk {
: VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
binding.access = m_analysis->uavInfos[registerId].accessFlags;

if (!m_analysis->uavInfos[registerId].nonInvariantAccess)
binding.storeOp = m_analysis->uavInfos[registerId].atomicStore;

if (!(binding.access & VK_ACCESS_SHADER_WRITE_BIT))
m_module.decorate(varId, spv::DecorationNonWritable);
if (!(binding.access & VK_ACCESS_SHADER_READ_BIT))
Expand Down Expand Up @@ -1234,9 +1237,14 @@ namespace dxvk {
: (isUav ? VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER : VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER);
binding.viewType = VK_IMAGE_VIEW_TYPE_MAX_ENUM;
binding.resourceBinding = bindingId;
binding.access = isUav
? m_analysis->uavInfos[registerId].accessFlags
: VkAccessFlags(VK_ACCESS_SHADER_READ_BIT);
binding.access = VK_ACCESS_SHADER_READ_BIT;

if (isUav) {
binding.access = m_analysis->uavInfos[registerId].accessFlags;

if (!m_analysis->uavInfos[registerId].nonInvariantAccess)
binding.storeOp = m_analysis->uavInfos[registerId].atomicStore;
}

if (useRawSsbo || isUav) {
if (!(binding.access & VK_ACCESS_SHADER_WRITE_BIT))
Expand Down

0 comments on commit d904c3b

Please sign in to comment.