1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-02-22 07:54:15 +01:00

[dxbc] Fix UAV write test

We broke this during the null descriptor refactor. Also make it so that
we don't generate conditionals when there's nothing to test.
This commit is contained in:
Philip Rebohle 2022-07-20 22:54:09 +02:00
parent 779f8b39cd
commit ec813e036c
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
2 changed files with 47 additions and 90 deletions

View File

@ -2273,21 +2273,8 @@ namespace dxvk {
&& bufferInfo.type != DxbcResourceType::Typed && bufferInfo.type != DxbcResourceType::Typed
&& isUav; && isUav;
// Perform atomic operations on UAVs only if the UAV // Perform atomic operations on UAVs only if the invocation is alive
// is bound and if there is nothing else stopping us. DxbcConditional cond = emitBeginPsKillTest();
DxbcConditional cond;
if (isUav) {
uint32_t writeTest = emitUavWriteTest(bufferInfo);
cond.labelIf = m_module.allocateId();
cond.labelEnd = m_module.allocateId();
m_module.opSelectionMerge(cond.labelEnd, spv::SelectionControlMaskNone);
m_module.opBranchConditional(writeTest, cond.labelIf, cond.labelEnd);
m_module.opLabel(cond.labelIf);
}
// Retrieve destination pointer for the atomic operation> // Retrieve destination pointer for the atomic operation>
const DxbcRegisterPointer pointer = emitGetAtomicPointer( const DxbcRegisterPointer pointer = emitGetAtomicPointer(
@ -2413,11 +2400,7 @@ namespace dxvk {
if (isImm) if (isImm)
emitRegisterStore(ins.dst[0], value); emitRegisterStore(ins.dst[0], value);
// End conditional block emitEndPsKillTest(cond);
if (isUav) {
m_module.opBranch(cond.labelEnd);
m_module.opLabel (cond.labelEnd);
}
} }
@ -2425,30 +2408,22 @@ namespace dxvk {
// imm_atomic_alloc and imm_atomic_consume have the following operands: // imm_atomic_alloc and imm_atomic_consume have the following operands:
// (dst0) The register that will hold the old counter value // (dst0) The register that will hold the old counter value
// (dst1) The UAV whose counter is going to be modified // (dst1) The UAV whose counter is going to be modified
const DxbcBufferInfo bufferInfo = getBufferInfo(ins.dst[1]);
const uint32_t registerId = ins.dst[1].idx[0].offset; const uint32_t registerId = ins.dst[1].idx[0].offset;
if (m_uavs.at(registerId).ctrId == 0) if (m_uavs.at(registerId).ctrId == 0)
m_uavs.at(registerId).ctrId = emitDclUavCounter(registerId); m_uavs.at(registerId).ctrId = emitDclUavCounter(registerId);
// Only perform the operation if the UAV is bound // Only perform the operation if the invocation is alive
uint32_t writeTest = emitUavWriteTest(bufferInfo); DxbcConditional cond = emitBeginPsKillTest();
DxbcConditional cond;
cond.labelIf = m_module.allocateId();
cond.labelEnd = m_module.allocateId();
m_module.opSelectionMerge(cond.labelEnd, spv::SelectionControlMaskNone);
m_module.opBranchConditional(writeTest, cond.labelIf, cond.labelEnd);
m_module.opLabel(cond.labelIf);
// Only use subgroup ops on compute to avoid having to // Only use subgroup ops on compute to avoid having to
// deal with helper invocations or hardware limitations // deal with helper invocations or hardware limitations
bool useSubgroupOps = m_moduleInfo.options.useSubgroupOpsForAtomicCounters bool useSubgroupOps = m_moduleInfo.options.useSubgroupOpsForAtomicCounters
&& m_programInfo.type() == DxbcProgramType::ComputeShader; && m_programInfo.type() == DxbcProgramType::ComputeShader;
// Current block ID used in a phi later on
uint32_t baseBlockId = m_module.getBlockId();
// In case we have subgroup ops enabled, we need to // In case we have subgroup ops enabled, we need to
// count the number of active lanes, the lane index, // count the number of active lanes, the lane index,
// and we need to perform the atomic op conditionally // and we need to perform the atomic op conditionally
@ -2550,7 +2525,7 @@ namespace dxvk {
std::array<SpirvPhiLabel, 2> phiLabels = {{ std::array<SpirvPhiLabel, 2> phiLabels = {{
{ value.id, elect.labelIf }, { value.id, elect.labelIf },
{ undef, cond.labelIf }, { undef, baseBlockId },
}}; }};
value.id = m_module.opPhi(typeId, value.id = m_module.opPhi(typeId,
@ -2562,10 +2537,7 @@ namespace dxvk {
// Store the result // Store the result
emitRegisterStore(ins.dst[0], value); emitRegisterStore(ins.dst[0], value);
emitEndPsKillTest(cond);
// End conditional block
m_module.opBranch(cond.labelEnd);
m_module.opLabel (cond.labelEnd);
} }
@ -3677,17 +3649,8 @@ namespace dxvk {
// (src1) The value to store // (src1) The value to store
const DxbcBufferInfo uavInfo = getBufferInfo(ins.dst[0]); const DxbcBufferInfo uavInfo = getBufferInfo(ins.dst[0]);
// Execute write op only if the UAV is bound // Execute write op only if the invocation is active
uint32_t writeTest = emitUavWriteTest(uavInfo); DxbcConditional cond = emitBeginPsKillTest();
DxbcConditional cond;
cond.labelIf = m_module.allocateId();
cond.labelEnd = m_module.allocateId();
m_module.opSelectionMerge (cond.labelEnd, spv::SelectionControlMaskNone);
m_module.opBranchConditional(writeTest, cond.labelIf, cond.labelEnd);
m_module.opLabel(cond.labelIf);
// Load texture coordinates // Load texture coordinates
DxbcRegisterValue texCoord = emitLoadTexCoord(ins.src[0], uavInfo.image); DxbcRegisterValue texCoord = emitLoadTexCoord(ins.src[0], uavInfo.image);
@ -3703,9 +3666,7 @@ namespace dxvk {
m_module.opLoad(uavInfo.typeId, uavInfo.varId), m_module.opLoad(uavInfo.typeId, uavInfo.varId),
texCoord.id, texValue.id, SpirvImageOperands()); texCoord.id, texValue.id, SpirvImageOperands());
// End conditional block emitEndPsKillTest(cond);
m_module.opBranch(cond.labelEnd);
m_module.opLabel (cond.labelEnd);
} }
@ -5152,21 +5113,8 @@ namespace dxvk {
bool isSsbo = m_moduleInfo.options.minSsboAlignment <= bufferInfo.align bool isSsbo = m_moduleInfo.options.minSsboAlignment <= bufferInfo.align
&& !isTgsm; && !isTgsm;
// Perform UAV writes only if the UAV is bound and if there // Perform UAV writes only if the invocation is active
// is nothing else preventing us from writing to it. DxbcConditional cond = emitBeginPsKillTest();
DxbcConditional cond;
if (!isTgsm) {
uint32_t writeTest = emitUavWriteTest(bufferInfo);
cond.labelIf = m_module.allocateId();
cond.labelEnd = m_module.allocateId();
m_module.opSelectionMerge(cond.labelEnd, spv::SelectionControlMaskNone);
m_module.opBranchConditional(writeTest, cond.labelIf, cond.labelEnd);
m_module.opLabel(cond.labelIf);
}
// Perform the actual write operation // Perform the actual write operation
uint32_t bufferId = isTgsm || isSsbo ? 0 : m_module.opLoad(bufferInfo.typeId, bufferInfo.varId); uint32_t bufferId = isTgsm || isSsbo ? 0 : m_module.opLoad(bufferInfo.typeId, bufferInfo.varId);
@ -5229,11 +5177,7 @@ namespace dxvk {
| spv::MemorySemanticsAcquireReleaseMask)); | spv::MemorySemanticsAcquireReleaseMask));
} }
// End conditional block emitEndPsKillTest(cond);
if (!isTgsm) {
m_module.opBranch(cond.labelEnd);
m_module.opLabel (cond.labelEnd);
}
} }
@ -6483,20 +6427,32 @@ namespace dxvk {
} }
uint32_t DxbcCompiler::emitUavWriteTest(const DxbcBufferInfo& uav) { DxbcConditional DxbcCompiler::emitBeginPsKillTest() {
uint32_t typeId = m_module.defBoolType(); if (!m_ps.killState)
uint32_t testId = 0; return DxbcConditional();
if (m_ps.killState != 0) { uint32_t boolId = m_module.defBoolType();
uint32_t killState = m_module.opLoad(typeId, m_ps.killState); uint32_t killState = m_module.opLoad(boolId, m_ps.killState);
uint32_t testId = m_module.opLogicalNot(boolId, killState);
testId = m_module.opLogicalAnd(typeId, testId, DxbcConditional cond;
m_module.opLogicalNot(typeId, killState)); cond.labelIf = m_module.allocateId();
} else { cond.labelEnd = m_module.allocateId();
testId = m_module.constBool(true);
m_module.opSelectionMerge(cond.labelEnd, spv::SelectionControlMaskNone);
m_module.opBranchConditional(testId, cond.labelIf, cond.labelEnd);
m_module.opLabel(cond.labelIf);
return cond;
} }
return testId;
void DxbcCompiler::emitEndPsKillTest(const DxbcConditional& cond) {
if (!m_ps.killState)
return;
m_module.opBranch(cond.labelEnd);
m_module.opLabel(cond.labelEnd);
} }

View File

@ -1063,8 +1063,9 @@ namespace dxvk {
/////////////////////////////// ///////////////////////////////
// Some state checking methods // Some state checking methods
uint32_t emitUavWriteTest( DxbcConditional emitBeginPsKillTest();
const DxbcBufferInfo& uav);
void emitEndPsKillTest(const DxbcConditional& cond);
////////////////////////////////////// //////////////////////////////////////
// Common function definition methods // Common function definition methods