diff --git a/src/dxbc/dxbc_compiler.cpp b/src/dxbc/dxbc_compiler.cpp index a054e837..649816ea 100644 --- a/src/dxbc/dxbc_compiler.cpp +++ b/src/dxbc/dxbc_compiler.cpp @@ -498,6 +498,11 @@ namespace dxvk { "oDepthLe"); } break; + case DxbcOperandType::OutputControlPointId: { + // The hull shader's invocation + // ID has been declared already + } break; + case DxbcOperandType::InputForkInstanceId: case DxbcOperandType::InputJoinInstanceId: { auto phase = this->getCurrentHsForkJoinPhase(); @@ -1074,6 +1079,8 @@ namespace dxvk { // dcl_input_control_points has the control point // count embedded within the opcode token. m_hs.vertexCountIn = ins.controls.controlPointCount; + + emitDclInputArray(m_hs.vertexCountIn); } @@ -2377,6 +2384,15 @@ namespace dxvk { m_hs.currPhaseType = DxbcCompilerHsPhase::Decl; } break; + case DxbcOpcode::HsControlPointPhase: { + m_hs.cpPhase = this->emitNewHullShaderControlPointPhase(); + + m_hs.currPhaseType = DxbcCompilerHsPhase::ControlPoint; + m_hs.currPhaseId = 0; + + m_module.setDebugName(m_hs.cpPhase.functionId, "hs_control_point"); + } break; + case DxbcOpcode::HsForkPhase: { auto phase = this->emitNewHullShaderForkJoinPhase(); m_hs.forkPhases.push_back(phase); @@ -4052,6 +4068,11 @@ namespace dxvk { { DxbcScalarType::Float32, 1 }, m_ps.builtinDepth }; + case DxbcOperandType::OutputControlPointId: + return DxbcRegisterPointer { + { DxbcScalarType::Uint32, 1 }, + m_hs.builtinInvocationId }; + case DxbcOperandType::InputForkInstanceId: return DxbcRegisterPointer { { DxbcScalarType::Uint32, 1 }, @@ -5000,6 +5021,13 @@ namespace dxvk { m_module.enableCapability(spv::CapabilityClipDistance); m_module.enableCapability(spv::CapabilityCullDistance); + m_hs.builtinInvocationId = emitNewBuiltinVariable( + DxbcRegisterInfo { + { DxbcScalarType::Uint32, 1, 0 }, + spv::StorageClassInput }, + spv::BuiltInInvocationId, + "vOutputControlPointId"); + m_hs.builtinTessLevelOuter = emitBuiltinTessLevelOuter(spv::StorageClassOutput); m_hs.builtinTessLevelInner = emitBuiltinTessLevelInner(spv::StorageClassOutput); } @@ -5119,6 +5147,8 @@ namespace dxvk { void DxbcCompiler::emitHsFinalize() { + emitInputSetup(m_hs.vertexCountIn); + this->emitHsControlPointPhase(m_hs.cpPhase); if (m_hs.forkPhases.size() != 0 @@ -5169,7 +5199,11 @@ namespace dxvk { void DxbcCompiler::emitHsControlPointPhase( const DxbcCompilerHsControlPointPhase& phase) { - + if (phase.functionId != 0) { + m_module.opFunctionCall( + m_module.defVoidType(), + phase.functionId, 0, nullptr); + } } @@ -5232,6 +5266,22 @@ namespace dxvk { } + DxbcCompilerHsControlPointPhase DxbcCompiler::emitNewHullShaderControlPointPhase() { + uint32_t funTypeId = m_module.defFunctionType( + m_module.defVoidType(), 0, nullptr); + + uint32_t funId = m_module.allocateId(); + + m_module.functionBegin(m_module.defVoidType(), + funId, funTypeId, spv::FunctionControlMaskNone); + m_module.opLabel(m_module.allocateId()); + + DxbcCompilerHsControlPointPhase result; + result.functionId = funId; + return result; + } + + DxbcCompilerHsForkJoinPhase DxbcCompiler::emitNewHullShaderForkJoinPhase() { uint32_t argTypeId = m_module.defIntType(32, 0); uint32_t funTypeId = m_module.defFunctionType( diff --git a/src/dxbc/dxbc_compiler.h b/src/dxbc/dxbc_compiler.h index 6480cb94..390463ef 100644 --- a/src/dxbc/dxbc_compiler.h +++ b/src/dxbc/dxbc_compiler.h @@ -173,7 +173,7 @@ namespace dxvk { * point phase program of a hull shader. */ struct DxbcCompilerHsControlPointPhase { - uint32_t functionId = 0; + uint32_t functionId = 0; }; @@ -202,6 +202,7 @@ namespace dxvk { uint32_t vertexCountIn = 0; uint32_t vertexCountOut = 0; + uint32_t builtinInvocationId = 0; uint32_t builtinTessLevelOuter = 0; uint32_t builtinTessLevelInner = 0; @@ -878,6 +879,8 @@ namespace dxvk { uint32_t vertexCount, const char* varName); + DxbcCompilerHsControlPointPhase emitNewHullShaderControlPointPhase(); + DxbcCompilerHsForkJoinPhase emitNewHullShaderForkJoinPhase(); ///////////////////////////////