From a2f66025f8f7b264c038c8dba85feb63d17a4187 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Fri, 8 Dec 2017 17:08:26 +0100 Subject: [PATCH] [dxbc] Implemented constant buffers --- src/dxbc/dxbc_compiler.cpp | 76 ++++++++++++++++++++++++++++++++ src/dxbc/dxbc_compiler.h | 13 ++++++ src/dxbc/gen/dxbc_gen_common.cpp | 49 ++++++++++++++++++++ src/dxbc/gen/dxbc_gen_common.h | 28 +++++++++++- src/spirv/spirv_module.cpp | 27 ++++++++++++ src/spirv/spirv_module.h | 10 +++++ 6 files changed, 202 insertions(+), 1 deletion(-) diff --git a/src/dxbc/dxbc_compiler.cpp b/src/dxbc/dxbc_compiler.cpp index c762ce9a..eb7e682b 100644 --- a/src/dxbc/dxbc_compiler.cpp +++ b/src/dxbc/dxbc_compiler.cpp @@ -21,6 +21,9 @@ namespace dxvk { case DxbcOpcode::DclGlobalFlags: return this->dclGlobalFlags(ins); + case DxbcOpcode::DclConstantBuffer: + return this->dclConstantBuffer(ins); + case DxbcOpcode::DclInput: case DxbcOpcode::DclInputSiv: case DxbcOpcode::DclInputSgv: @@ -41,6 +44,15 @@ namespace dxvk { case DxbcOpcode::Mov: return this->opMov(ins); + case DxbcOpcode::Dp2: + return this->opDpx(ins, 2); + + case DxbcOpcode::Dp3: + return this->opDpx(ins, 3); + + case DxbcOpcode::Dp4: + return this->opDpx(ins, 4); + case DxbcOpcode::Ret: return this->opRet(ins); @@ -58,7 +70,20 @@ namespace dxvk { void DxbcCompiler::dclGlobalFlags(const DxbcInstruction& ins) { + // TODO fill with life + } + + + void DxbcCompiler::dclConstantBuffer(const DxbcInstruction& ins) { + auto op = ins.operand(0); + if (op.token().indexDimension() != 2) + throw DxvkError("DxbcCompiler::dclConstantBuffer: Invalid index dimension"); + + const uint32_t index = op.index(0).immPart(); + const uint32_t size = op.index(1).immPart(); + + m_gen->dclConstantBuffer(index, size); } @@ -139,6 +164,22 @@ namespace dxvk { } + void DxbcCompiler::opDpx(const DxbcInstruction& ins, uint32_t n) { + auto dstOp = ins.operand(0); + auto srcOp1 = ins.operand(dstOp.length()); + auto srcOp2 = ins.operand(dstOp.length() + srcOp1.length()); + + DxbcComponentMask dstMask = this->getDstOperandMask(dstOp); + DxbcComponentMask srcMask(n >= 1, n >= 2, n >= 3, n == 4); + + DxbcValue src1 = this->loadOperand(srcOp1, srcMask, DxbcScalarType::Float32); + DxbcValue src2 = this->loadOperand(srcOp2, srcMask, DxbcScalarType::Float32); + DxbcValue val = m_gen->opDot(src1, src2); + val = this->applyResultModifiers(val, ins.token().control()); + this->storeOperand(dstOp, val, dstMask); + } + + void DxbcCompiler::opMov(const DxbcInstruction& ins) { auto dstOp = ins.operand(0); auto srcOp = ins.operand(dstOp.length()); @@ -155,6 +196,28 @@ namespace dxvk { } + DxbcValue DxbcCompiler::getDynamicIndexValue(const DxbcOperandIndex& index) { + DxbcValue immPart; + DxbcValue relPart; + + if (index.hasImmPart()) + immPart = m_gen->defConstScalar(index.immPart()); + + if (index.hasRelPart()) { + relPart = this->loadOperand(index.relPart(), + DxbcComponentMask(true, false, false, false), + DxbcScalarType::Uint32); + } + + if (immPart.valueId == 0) + return relPart; + else if (relPart.valueId == 0) + return immPart; + else + return m_gen->opAdd(relPart, immPart); + } + + DxbcComponentMask DxbcCompiler::getDstOperandMask(const DxbcOperand& operand) { const DxbcOperandToken token = operand.token(); @@ -225,6 +288,16 @@ namespace dxvk { } + DxbcPointer DxbcCompiler::getConstantBufferPtr(const DxbcOperand& operand) { + if (operand.token().indexDimension() != 2) + throw DxvkError("DxbcCompiler::getConstantBufferPtr: Invalid index dimension"); + + return m_gen->ptrConstantBuffer( + operand.index(0).immPart(), + this->getDynamicIndexValue(operand.index(1))); + } + + DxbcPointer DxbcCompiler::getOperandPtr(const DxbcOperand& operand) { switch (operand.token().type()) { case DxbcOperandType::Temp: @@ -234,6 +307,9 @@ namespace dxvk { case DxbcOperandType::Output: return this->getInterfaceOperandPtr(operand); + case DxbcOperandType::ConstantBuffer: + return this->getConstantBufferPtr(operand); + default: throw DxvkError(str::format( "DxbcCompiler::getOperandPtr: Unhandled operand type: ", diff --git a/src/dxbc/dxbc_compiler.h b/src/dxbc/dxbc_compiler.h index aa007640..701bb219 100644 --- a/src/dxbc/dxbc_compiler.h +++ b/src/dxbc/dxbc_compiler.h @@ -32,6 +32,9 @@ namespace dxvk { void dclGlobalFlags( const DxbcInstruction& ins); + void dclConstantBuffer( + const DxbcInstruction& ins); + void dclInterfaceVar( const DxbcInstruction& ins); @@ -41,12 +44,19 @@ namespace dxvk { void opAdd( const DxbcInstruction& ins); + void opDpx( + const DxbcInstruction& ins, + uint32_t n); + void opMov( const DxbcInstruction& ins); void opRet( const DxbcInstruction& ins); + DxbcValue getDynamicIndexValue( + const DxbcOperandIndex& index); + DxbcComponentMask getDstOperandMask( const DxbcOperand& operand); @@ -56,6 +66,9 @@ namespace dxvk { DxbcPointer getInterfaceOperandPtr( const DxbcOperand& operand); + DxbcPointer getConstantBufferPtr( + const DxbcOperand& operand); + DxbcPointer getOperandPtr( const DxbcOperand& operand); diff --git a/src/dxbc/gen/dxbc_gen_common.cpp b/src/dxbc/gen/dxbc_gen_common.cpp index eea20667..3629ba90 100644 --- a/src/dxbc/gen/dxbc_gen_common.cpp +++ b/src/dxbc/gen/dxbc_gen_common.cpp @@ -36,6 +36,25 @@ namespace dxvk { } + void DxbcCodeGen::dclConstantBuffer( + uint32_t bufferId, + uint32_t elementCount) { + uint32_t arrayType = this->defValueType( + DxbcValueType(DxbcScalarType::Float32, 4, elementCount)); + uint32_t structType = m_module.defStructType(1, &arrayType); + + m_module.memberDecorateOffset(structType, 0, 0); + m_module.decorateBlock(structType); + + uint32_t varIndex = m_module.newVar( + m_module.defPointerType(structType, spv::StorageClassUniform), + spv::StorageClassUniform); + + m_constantBuffers.at(bufferId).varId = varIndex; + m_constantBuffers.at(bufferId).size = elementCount; + } + + DxbcValue DxbcCodeGen::defConstScalar(uint32_t v) { DxbcValue result; result.type = DxbcValueType(DxbcScalarType::Uint32, 1); @@ -74,6 +93,26 @@ namespace dxvk { } + DxbcPointer DxbcCodeGen::ptrConstantBuffer( + uint32_t regId, + const DxbcValue& index) { + // The first index selects the struct member, + // the second one selects the array element. + std::array indices = { + m_module.constu32(0), index.valueId }; + + DxbcPointer result; + result.type = DxbcPointerType( + DxbcValueType(DxbcScalarType::Float32, 4), + spv::StorageClassUniform); + result.valueId = m_module.opAccessChain( + this->defPointerType(result.type), + m_constantBuffers.at(regId).varId, + 2, indices.data()); + return result; + } + + DxbcValue DxbcCodeGen::opAbs(const DxbcValue& src) { DxbcValue result; result.type = src.type; @@ -129,6 +168,16 @@ namespace dxvk { } + DxbcValue DxbcCodeGen::opDot(const DxbcValue& a, const DxbcValue& b) { + DxbcValue result; + result.type = DxbcValueType(a.type.componentType, 1); + result.valueId = m_module.opDot( + this->defValueType(result.type), + a.valueId, b.valueId); + return result; + } + + DxbcValue DxbcCodeGen::opNeg(const DxbcValue& src) { DxbcValue result; result.type = src.type; diff --git a/src/dxbc/gen/dxbc_gen_common.h b/src/dxbc/gen/dxbc_gen_common.h index 14d9f9f6..fb647a5a 100644 --- a/src/dxbc/gen/dxbc_gen_common.h +++ b/src/dxbc/gen/dxbc_gen_common.h @@ -22,6 +22,18 @@ namespace dxvk { }; + /** + * \brief Constant buffer binding + * + * Stores information about + * a constant buffer. + */ + struct DxbcConstantBuffer { + uint32_t varId = 0; + uint32_t size = 0; + }; + + /** * \brief DXBC code generator * @@ -40,6 +52,10 @@ namespace dxvk { void dclTemps(uint32_t n); + void dclConstantBuffer( + uint32_t bufferId, + uint32_t elementCount); + DxbcValue defConstScalar(uint32_t v); DxbcValue defConstVector( @@ -49,7 +65,11 @@ namespace dxvk { void fnReturn(); DxbcPointer ptrTempReg( - uint32_t regId); + uint32_t regId); + + DxbcPointer ptrConstantBuffer( + uint32_t regId, + const DxbcValue& index); DxbcValue opAbs( const DxbcValue& src); @@ -62,6 +82,10 @@ namespace dxvk { const DxbcValue& a, const DxbcValue& b); + DxbcValue opDot( + const DxbcValue& a, + const DxbcValue& b); + DxbcValue opNeg( const DxbcValue& src); @@ -132,6 +156,8 @@ namespace dxvk { std::vector m_rRegs; + std::array m_constantBuffers; + uint32_t defScalarType( DxbcScalarType type); diff --git a/src/spirv/spirv_module.cpp b/src/spirv/spirv_module.cpp index b5febb36..db02a9d9 100644 --- a/src/spirv/spirv_module.cpp +++ b/src/spirv/spirv_module.cpp @@ -307,6 +307,18 @@ namespace dxvk { } + void SpirvModule::memberDecorateOffset( + uint32_t structId, + uint32_t memberId, + uint32_t offset) { + m_annotations.putIns (spv::OpMemberDecorate, 5); + m_annotations.putWord (structId); + m_annotations.putWord (memberId); + m_annotations.putWord (spv::DecorationOffset); + m_annotations.putWord (offset); + } + + uint32_t SpirvModule::defVoidType() { return this->defType(spv::OpTypeVoid, 0, nullptr); } @@ -696,6 +708,21 @@ namespace dxvk { } + uint32_t SpirvModule::opDot( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpDot, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(vector1); + m_code.putWord(vector2); + return resultId; + } + + uint32_t SpirvModule::opFunctionCall( uint32_t resultType, uint32_t functionId, diff --git a/src/spirv/spirv_module.h b/src/spirv/spirv_module.h index a37b27fb..1a02cd17 100644 --- a/src/spirv/spirv_module.h +++ b/src/spirv/spirv_module.h @@ -116,6 +116,11 @@ namespace dxvk { uint32_t memberId, spv::BuiltIn builtIn); + void memberDecorateOffset( + uint32_t structId, + uint32_t memberId, + uint32_t offset); + uint32_t defVoidType(); uint32_t defBoolType(); @@ -251,6 +256,11 @@ namespace dxvk { uint32_t minVal, uint32_t maxVal); + uint32_t opDot( + uint32_t resultType, + uint32_t vector1, + uint32_t vector2); + uint32_t opFunctionCall( uint32_t resultType, uint32_t functionId,