diff --git a/src/dxbc/dxbc_compiler.cpp b/src/dxbc/dxbc_compiler.cpp index 00c74793..1a07e494 100644 --- a/src/dxbc/dxbc_compiler.cpp +++ b/src/dxbc/dxbc_compiler.cpp @@ -85,6 +85,9 @@ namespace dxvk { case DxbcInstClass::GeometryEmit: return this->emitGeometryEmit(ins); + case DxbcInstClass::HullShaderPhase: + return this->emitHullShaderPhase(ins); + case DxbcInstClass::Interpolate: return this->emitInterpolate(ins); @@ -162,10 +165,11 @@ namespace dxvk { // and write back the output registers. switch (m_version.type()) { case DxbcProgramType::VertexShader: this->emitVsFinalize(); break; + case DxbcProgramType::HullShader: this->emitHsFinalize(); break; + case DxbcProgramType::DomainShader: this->emitDsFinalize(); break; case DxbcProgramType::GeometryShader: this->emitGsFinalize(); break; case DxbcProgramType::PixelShader: this->emitPsFinalize(); break; case DxbcProgramType::ComputeShader: this->emitCsFinalize(); break; - default: throw DxvkError("DxbcCompiler: Unsupported program type"); } // End main function @@ -476,6 +480,12 @@ namespace dxvk { "oDepthLe"); } break; + case DxbcOperandType::InputForkInstanceId: + case DxbcOperandType::InputJoinInstanceId: { + // Nothing to do here, as these are part of the + // function signature for the fork and join phases. + } break; + default: Logger::err(str::format( "DxbcCompiler: Unsupported operand type declaration: ", @@ -2257,6 +2267,45 @@ namespace dxvk { } + void DxbcCompiler::emitHullShaderPhase(const DxbcShaderInstruction& ins) { + switch (ins.op) { + case DxbcOpcode::HsDecls: { + if (m_hs.currPhaseType != DxbcCompilerHsPhase::None) + Logger::err("DXBC: HsDecls not the first phase in hull shader"); + + m_hs.currPhaseType = DxbcCompilerHsPhase::Decl; + } break; + + case DxbcOpcode::HsForkPhase: { + auto phase = this->emitNewHullShaderForkJoinPhase(); + m_hs.forkPhases.push_back(phase); + + m_hs.currPhaseType = DxbcCompilerHsPhase::Fork; + m_hs.currPhaseId = m_hs.forkPhases.size() - 1; + + m_module.setDebugName(phase.functionId, + str::format("hs_fork_", m_hs.currPhaseId).c_str()); + } break; + + case DxbcOpcode::HsJoinPhase: { + auto phase = this->emitNewHullShaderForkJoinPhase(); + m_hs.joinPhases.push_back(phase); + + m_hs.currPhaseType = DxbcCompilerHsPhase::Join; + m_hs.currPhaseId = m_hs.joinPhases.size() - 1; + + m_module.setDebugName(phase.functionId, + str::format("hs_join_", m_hs.currPhaseId).c_str()); + } break; + + default: + Logger::warn(str::format( + "DxbcCompiler: Unhandled instruction: ", + ins.op)); + } + } + + void DxbcCompiler::emitInterpolate(const DxbcShaderInstruction& ins) { // The SPIR-V instructions operate on input variable pointers, // which are all declared as four-component float vectors. @@ -3879,6 +3928,16 @@ namespace dxvk { return DxbcRegisterPointer { { DxbcScalarType::Float32, 1 }, m_ps.builtinDepth }; + + case DxbcOperandType::InputForkInstanceId: + return DxbcRegisterPointer { + { DxbcScalarType::Uint32, 1 }, + m_hs.forkPhases.at(m_hs.currPhaseId).builtinInstanceId }; + + case DxbcOperandType::InputJoinInstanceId: + return DxbcRegisterPointer { + { DxbcScalarType::Uint32, 1 }, + m_hs.joinPhases.at(m_hs.currPhaseId).builtinInstanceId }; default: throw DxvkError(str::format( @@ -4769,10 +4828,11 @@ namespace dxvk { // etc. Each shader type has its own peculiarities. switch (m_version.type()) { case DxbcProgramType::VertexShader: emitVsInit(); break; + case DxbcProgramType::HullShader: emitHsInit(); break; + case DxbcProgramType::DomainShader: emitDsInit(); break; case DxbcProgramType::GeometryShader: emitGsInit(); break; case DxbcProgramType::PixelShader: emitPsInit(); break; case DxbcProgramType::ComputeShader: emitCsInit(); break; - default: throw DxvkError("DxbcCompiler: Unsupported program type"); } } @@ -4812,6 +4872,24 @@ namespace dxvk { } + void DxbcCompiler::emitHsInit() { + m_module.enableCapability(spv::CapabilityTessellation); + m_module.enableCapability(spv::CapabilityClipDistance); + m_module.enableCapability(spv::CapabilityCullDistance); + + // TODO implement + } + + + void DxbcCompiler::emitDsInit() { + m_module.enableCapability(spv::CapabilityTessellation); + m_module.enableCapability(spv::CapabilityClipDistance); + m_module.enableCapability(spv::CapabilityCullDistance); + + // TODO implement + } + + void DxbcCompiler::emitGsInit() { m_module.enableCapability(spv::CapabilityGeometry); m_module.enableCapability(spv::CapabilityClipDistance); @@ -4915,6 +4993,16 @@ namespace dxvk { } + void DxbcCompiler::emitHsFinalize() { + // TODO implement + } + + + void DxbcCompiler::emitDsFinalize() { + // TODO implement + } + + void DxbcCompiler::emitGsFinalize() { this->emitInputSetup( primitiveVertexCount(m_gs.inputPrimitive)); @@ -4991,6 +5079,28 @@ namespace dxvk { } + DxbcCompilerHsForkJoinPhase DxbcCompiler::emitNewHullShaderForkJoinPhase() { + uint32_t argTypeId = m_module.defPointerType( + m_module.defIntType(32, 0), + spv::StorageClassFunction); + uint32_t funTypeId = m_module.defFunctionType( + m_module.defVoidType(), 1, &argTypeId); + + uint32_t funId = m_module.allocateId(); + + m_module.functionBegin(m_module.defVoidType(), + funId, funTypeId, spv::FunctionControlMaskNone); + + uint32_t argId = m_module.functionParameter(argTypeId); + m_module.opLabel(m_module.allocateId()); + + DxbcCompilerHsForkJoinPhase result; + result.functionId = funId; + result.builtinInstanceId = argId; + return result; + } + + uint32_t DxbcCompiler::emitNewVariable(const DxbcRegisterInfo& info) { const uint32_t ptrTypeId = this->getPointerTypeId(info); return m_module.newVar(ptrTypeId, info.sclass); diff --git a/src/dxbc/dxbc_compiler.h b/src/dxbc/dxbc_compiler.h index ca146154..fab86726 100644 --- a/src/dxbc/dxbc_compiler.h +++ b/src/dxbc/dxbc_compiler.h @@ -527,6 +527,9 @@ namespace dxvk { void emitConvertFloat16( const DxbcShaderInstruction& ins); + void emitHullShaderPhase( + const DxbcShaderInstruction& ins); + void emitInterpolate( const DxbcShaderInstruction& ins); @@ -810,6 +813,7 @@ namespace dxvk { void emitVsInit(); void emitHsInit(); + void emitDsInit(); void emitGsInit(); void emitPsInit(); void emitCsInit(); @@ -818,6 +822,7 @@ namespace dxvk { // Shader finalization methods void emitVsFinalize(); void emitHsFinalize(); + void emitDsFinalize(); void emitGsFinalize(); void emitPsFinalize(); void emitCsFinalize(); @@ -831,6 +836,8 @@ namespace dxvk { uint32_t vertexCount, const char* varName); + DxbcCompilerHsForkJoinPhase emitNewHullShaderForkJoinPhase(); + /////////////////////////////// // Variable definition methods uint32_t emitNewVariable( diff --git a/src/dxbc/dxbc_defs.cpp b/src/dxbc/dxbc_defs.cpp index cae45c65..781369bc 100644 --- a/src/dxbc/dxbc_defs.cpp +++ b/src/dxbc/dxbc_defs.cpp @@ -562,13 +562,13 @@ namespace dxvk { /* Reserved1 */ { }, /* HsDecls */ - { }, + { 0, DxbcInstClass::HullShaderPhase }, /* HsControlPointPhase */ - { }, + { 0, DxbcInstClass::HullShaderPhase }, /* HsForkPhase */ - { }, + { 0, DxbcInstClass::HullShaderPhase }, /* HsJoinPhase */ - { }, + { 0, DxbcInstClass::HullShaderPhase }, /* EmitStream */ { 1, DxbcInstClass::GeometryEmit, { { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, diff --git a/src/dxbc/dxbc_defs.h b/src/dxbc/dxbc_defs.h index ae048780..4f9006a8 100644 --- a/src/dxbc/dxbc_defs.h +++ b/src/dxbc/dxbc_defs.h @@ -41,6 +41,7 @@ namespace dxvk { BufferLoad, ///< Structured or raw buffer load BufferStore, ///< Structured or raw buffer store ConvertFloat16, ///< 16-bit float packing/unpacking + HullShaderPhase, ///< Hull shader phase declaration Interpolate, ///< Input attribute interpolation TextureQuery, ///< Texture query instruction TextureQueryLod, ///< Texture LOD query instruction diff --git a/src/spirv/spirv_module.cpp b/src/spirv/spirv_module.cpp index 756a0441..3f177523 100644 --- a/src/spirv/spirv_module.cpp +++ b/src/spirv/spirv_module.cpp @@ -2752,7 +2752,8 @@ namespace dxvk { // we can use the code buffer to look up type IDs as // well. Result IDs are always stored as argument 1. for (auto ins : m_typeConstDefs) { - bool match = ins.opCode() == op; + bool match = ins.opCode() == op + && ins.length() == 2 + argCount; for (uint32_t i = 0; i < argCount && match; i++) match &= ins.arg(2 + i) == argIds[i];