From 165648017e4716f52c57fd3a152eaa512d064724 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Wed, 17 Aug 2022 17:41:07 +0200 Subject: [PATCH] [dxbc] Remove fallback path for discards --- src/dxbc/dxbc_compiler.cpp | 178 +++--------------------------- src/dxbc/dxbc_compiler.h | 9 -- src/dxbc/dxbc_options.cpp | 6 - src/dxbc/dxbc_options.h | 7 -- tests/dxbc/test_dxbc_compiler.cpp | 1 - 5 files changed, 14 insertions(+), 187 deletions(-) diff --git a/src/dxbc/dxbc_compiler.cpp b/src/dxbc/dxbc_compiler.cpp index c3028fbe..3cf2da35 100644 --- a/src/dxbc/dxbc_compiler.cpp +++ b/src/dxbc/dxbc_compiler.cpp @@ -2273,9 +2273,6 @@ namespace dxvk { && bufferInfo.type != DxbcResourceType::Typed && isUav; - // Perform atomic operations on UAVs only if the invocation is alive - DxbcConditional cond = emitBeginPsKillTest(); - // Retrieve destination pointer for the atomic operation> const DxbcRegisterPointer pointer = emitGetAtomicPointer( ins.dst[ins.dstCount - 1], ins.src[0]); @@ -2399,8 +2396,6 @@ namespace dxvk { // register if this is an imm_atomic_* opcode. if (isImm) emitRegisterStore(ins.dst[0], value); - - emitEndPsKillTest(cond); } @@ -2413,9 +2408,6 @@ namespace dxvk { if (m_uavs.at(registerId).ctrId == 0) m_uavs.at(registerId).ctrId = emitDclUavCounter(registerId); - // Only perform the operation if the invocation is alive - DxbcConditional cond = emitBeginPsKillTest(); - // Only use subgroup ops on compute to avoid having to // deal with helper invocations or hardware limitations bool useSubgroupOps = m_moduleInfo.options.useSubgroupOpsForAtomicCounters @@ -2537,7 +2529,6 @@ namespace dxvk { // Store the result emitRegisterStore(ins.dst[0], value); - emitEndPsKillTest(cond); } @@ -3656,9 +3647,6 @@ namespace dxvk { // (src1) The value to store const DxbcBufferInfo uavInfo = getBufferInfo(ins.dst[0]); - // Execute write op only if the invocation is active - DxbcConditional cond = emitBeginPsKillTest(); - // Load texture coordinates DxbcRegisterValue texCoord = emitLoadTexCoord(ins.src[0], uavInfo.image); @@ -3672,8 +3660,6 @@ namespace dxvk { m_module.opImageWrite( m_module.opLoad(uavInfo.typeId, uavInfo.varId), texCoord.id, texValue.id, SpirvImageOperands()); - - emitEndPsKillTest(cond); } @@ -4031,80 +4017,20 @@ namespace dxvk { const DxbcRegisterValue zeroTest = emitRegisterZeroTest( condition, ins.controls.zeroTest()); - if (m_ps.killState == 0) { - DxbcConditional cond; - cond.labelIf = m_module.allocateId(); - cond.labelEnd = m_module.allocateId(); - - m_module.opSelectionMerge(cond.labelEnd, spv::SelectionControlMaskNone); - m_module.opBranchConditional(zeroTest.id, cond.labelIf, cond.labelEnd); - - m_module.opLabel(cond.labelIf); + DxbcConditional cond; + cond.labelIf = m_module.allocateId(); + cond.labelEnd = m_module.allocateId(); + + m_module.opSelectionMerge(cond.labelEnd, spv::SelectionControlMaskNone); + m_module.opBranchConditional(zeroTest.id, cond.labelIf, cond.labelEnd); + + m_module.opLabel(cond.labelIf); + m_module.opDemoteToHelperInvocation(); + m_module.opBranch(cond.labelEnd); + + m_module.opLabel(cond.labelEnd); - if (m_moduleInfo.options.useDemoteToHelperInvocation) { - m_module.opDemoteToHelperInvocation(); - m_module.opBranch(cond.labelEnd); - } else { - // OpKill terminates the block - m_module.opKill(); - } - - m_module.opLabel(cond.labelEnd); - } else { - uint32_t typeId = m_module.defBoolType(); - - uint32_t killState = m_module.opLoad (typeId, m_ps.killState); - killState = m_module.opLogicalOr(typeId, killState, zeroTest.id); - m_module.opStore(m_ps.killState, killState); - - if (m_moduleInfo.options.useSubgroupOpsForEarlyDiscard) { - uint32_t ballot = m_module.opGroupNonUniformBallot( - getVectorTypeId({ DxbcScalarType::Uint32, 4 }), - m_module.constu32(spv::ScopeSubgroup), - killState); - - uint32_t laneId = m_module.opLoad( - getScalarTypeId(DxbcScalarType::Uint32), - m_ps.builtinLaneId); - - uint32_t laneIdPart = m_module.opShiftRightLogical( - getScalarTypeId(DxbcScalarType::Uint32), - laneId, m_module.constu32(5)); - - uint32_t laneMask = m_module.opVectorExtractDynamic( - getScalarTypeId(DxbcScalarType::Uint32), - ballot, laneIdPart); - - uint32_t laneIdQuad = m_module.opBitwiseAnd( - getScalarTypeId(DxbcScalarType::Uint32), - laneId, m_module.constu32(0x1c)); - - laneMask = m_module.opShiftRightLogical( - getScalarTypeId(DxbcScalarType::Uint32), - laneMask, laneIdQuad); - - laneMask = m_module.opBitwiseAnd( - getScalarTypeId(DxbcScalarType::Uint32), - laneMask, m_module.constu32(0xf)); - - uint32_t killSubgroup = m_module.opIEqual( - m_module.defBoolType(), - laneMask, m_module.constu32(0xf)); - - DxbcConditional cond; - cond.labelIf = m_module.allocateId(); - cond.labelEnd = m_module.allocateId(); - - m_module.opSelectionMerge(cond.labelEnd, spv::SelectionControlMaskNone); - m_module.opBranchConditional(killSubgroup, cond.labelIf, cond.labelEnd); - - // OpKill terminates the block - m_module.opLabel(cond.labelIf); - m_module.opKill(); - - m_module.opLabel(cond.labelEnd); - } - } + m_module.enableCapability(spv::CapabilityDemoteToHelperInvocation); } @@ -5120,9 +5046,6 @@ namespace dxvk { bool isSsbo = m_moduleInfo.options.minSsboAlignment <= bufferInfo.align && !isTgsm; - // Perform UAV writes only if the invocation is active - DxbcConditional cond = emitBeginPsKillTest(); - // Perform the actual write operation uint32_t bufferId = isTgsm || isSsbo ? 0 : m_module.opLoad(bufferInfo.typeId, bufferInfo.varId); @@ -5183,8 +5106,6 @@ namespace dxvk { m_module.constu32(spv::MemorySemanticsWorkgroupMemoryMask | spv::MemorySemanticsAcquireReleaseMask)); } - - emitEndPsKillTest(cond); } @@ -6434,35 +6355,6 @@ namespace dxvk { } - DxbcConditional DxbcCompiler::emitBeginPsKillTest() { - if (!m_ps.killState) - return DxbcConditional(); - - uint32_t boolId = m_module.defBoolType(); - uint32_t killState = m_module.opLoad(boolId, m_ps.killState); - uint32_t testId = m_module.opLogicalNot(boolId, killState); - - DxbcConditional cond; - cond.labelIf = m_module.allocateId(); - cond.labelEnd = m_module.allocateId(); - - m_module.opSelectionMerge(cond.labelEnd, spv::SelectionControlMaskNone); - m_module.opBranchConditional(testId, cond.labelIf, cond.labelEnd); - - m_module.opLabel(cond.labelIf); - return cond; - } - - - void DxbcCompiler::emitEndPsKillTest(const DxbcConditional& cond) { - if (!m_ps.killState) - return; - - m_module.opBranch(cond.labelEnd); - m_module.opLabel(cond.labelEnd); - } - - void DxbcCompiler::emitInit() { // Set up common capabilities for all shaders m_module.enableCapability(spv::CapabilityShader); @@ -6704,32 +6596,6 @@ namespace dxvk { m_module.defFunctionType( m_module.defVoidType(), 0, nullptr)); this->emitFunctionLabel(); - - if (m_analysis->usesKill && m_moduleInfo.options.useDemoteToHelperInvocation) { - // This extension basically implements D3D-style discard - m_module.enableCapability(spv::CapabilityDemoteToHelperInvocation); - } else if (m_analysis->usesKill && m_analysis->usesDerivatives) { - // We may have to defer kill operations to the end of - // the shader in order to keep derivatives correct. - m_ps.killState = m_module.newVarInit( - m_module.defPointerType(m_module.defBoolType(), spv::StorageClassPrivate), - spv::StorageClassPrivate, m_module.constBool(false)); - - m_module.setDebugName(m_ps.killState, "ps_kill"); - - if (m_moduleInfo.options.useSubgroupOpsForEarlyDiscard) { - m_module.enableCapability(spv::CapabilityGroupNonUniform); - m_module.enableCapability(spv::CapabilityGroupNonUniformBallot); - - DxbcRegisterInfo laneId; - laneId.type = { DxbcScalarType::Uint32, 1, 0 }; - laneId.sclass = spv::StorageClassInput; - - m_ps.builtinLaneId = emitNewBuiltinVariable( - laneId, spv::BuiltInSubgroupLocalInvocationId, - "fLaneId"); - } - } } @@ -6823,23 +6689,7 @@ namespace dxvk { m_module.opFunctionCall( m_module.defVoidType(), m_ps.functionId, 0, nullptr); - - if (m_ps.killState != 0) { - DxbcConditional cond; - cond.labelIf = m_module.allocateId(); - cond.labelEnd = m_module.allocateId(); - - uint32_t killTest = m_module.opLoad(m_module.defBoolType(), m_ps.killState); - - m_module.opSelectionMerge(cond.labelEnd, spv::SelectionControlMaskNone); - m_module.opBranchConditional(killTest, cond.labelIf, cond.labelEnd); - - m_module.opLabel(cond.labelIf); - m_module.opKill(); - - m_module.opLabel(cond.labelEnd); - } - + this->emitOutputSetup(); if (m_moduleInfo.options.useDepthClipWorkaround) diff --git a/src/dxbc/dxbc_compiler.h b/src/dxbc/dxbc_compiler.h index 29d410c7..46afc806 100644 --- a/src/dxbc/dxbc_compiler.h +++ b/src/dxbc/dxbc_compiler.h @@ -181,9 +181,6 @@ namespace dxvk { uint32_t builtinLayer = 0; uint32_t builtinViewportId = 0; - uint32_t builtinLaneId = 0; - uint32_t killState = 0; - uint32_t pushConstantId = 0; }; @@ -1061,12 +1058,6 @@ namespace dxvk { DxbcSystemValue sv, uint32_t srcArray); - /////////////////////////////// - // Some state checking methods - DxbcConditional emitBeginPsKillTest(); - - void emitEndPsKillTest(const DxbcConditional& cond); - ////////////////////////////////////// // Common function definition methods void emitInit(); diff --git a/src/dxbc/dxbc_options.cpp b/src/dxbc/dxbc_options.cpp index f6b111a1..b0235163 100644 --- a/src/dxbc/dxbc_options.cpp +++ b/src/dxbc/dxbc_options.cpp @@ -20,12 +20,6 @@ namespace dxvk { useSubgroupOpsForAtomicCounters = (devInfo.vk11.subgroupSupportedStages & VK_SHADER_STAGE_COMPUTE_BIT) && (devInfo.vk11.subgroupSupportedOperations & VK_SUBGROUP_FEATURE_BALLOT_BIT); - useDemoteToHelperInvocation - = (devFeatures.vk13.shaderDemoteToHelperInvocation); - useSubgroupOpsForEarlyDiscard - = (devInfo.vk11.subgroupSize >= 4) - && (devInfo.vk11.subgroupSupportedStages & VK_SHADER_STAGE_FRAGMENT_BIT) - && (devInfo.vk11.subgroupSupportedOperations & VK_SUBGROUP_FEATURE_BALLOT_BIT); supportsTypedUavLoadR32 = true; supportsTypedUavLoadExtended = true; diff --git a/src/dxbc/dxbc_options.h b/src/dxbc/dxbc_options.h index 3d13ad6a..336526da 100644 --- a/src/dxbc/dxbc_options.h +++ b/src/dxbc/dxbc_options.h @@ -32,13 +32,6 @@ namespace dxvk { /// atomic operations for append/consume buffers. bool useSubgroupOpsForAtomicCounters = false; - /// Use a SPIR-V extension to implement D3D-style discards - bool useDemoteToHelperInvocation = false; - - /// Use subgroup operations to discard fragment - /// shader invocations if derivatives remain valid. - bool useSubgroupOpsForEarlyDiscard = false; - /// Enables NaN fixup for render target outputs bool enableRtOutputNanFixup = false; diff --git a/tests/dxbc/test_dxbc_compiler.cpp b/tests/dxbc/test_dxbc_compiler.cpp index 735604d7..0469c92e 100644 --- a/tests/dxbc/test_dxbc_compiler.cpp +++ b/tests/dxbc/test_dxbc_compiler.cpp @@ -43,7 +43,6 @@ int WINAPI WinMain(HINSTANCE hInstance, DxbcModuleInfo moduleInfo; moduleInfo.options.useSubgroupOpsForAtomicCounters = true; - moduleInfo.options.useDemoteToHelperInvocation = true; moduleInfo.options.minSsboAlignment = 4; moduleInfo.xfb = nullptr;