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:
parent
779f8b39cd
commit
ec813e036c
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user