From a4eb807215df79e7b079b1140cd1173699c797cc Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Wed, 13 Dec 2017 16:35:01 +0100 Subject: [PATCH] [dxbc] Implemented SinCos, Min and Max instructions --- src/dxbc/dxbc_compiler.cpp | 67 ++++++++++++++++++++++++++++++++++++++ src/dxbc/dxbc_compiler.h | 3 ++ src/dxbc/dxbc_defs.cpp | 18 ++++++++-- src/dxbc/dxbc_defs.h | 1 + src/spirv/spirv_module.cpp | 64 ++++++++++++++++++++++++++++++++++++ src/spirv/spirv_module.h | 18 ++++++++++ 6 files changed, 168 insertions(+), 3 deletions(-) diff --git a/src/dxbc/dxbc_compiler.cpp b/src/dxbc/dxbc_compiler.cpp index aef83ca26..432ca24ae 100644 --- a/src/dxbc/dxbc_compiler.cpp +++ b/src/dxbc/dxbc_compiler.cpp @@ -61,6 +61,7 @@ namespace dxvk { case DxbcInstClass::TextureSample: return this->handleTextureSample(parsedInst); case DxbcInstClass::VectorAlu: return this->handleVectorAlu (parsedInst); case DxbcInstClass::VectorDot: return this->handleVectorDot (parsedInst); + case DxbcInstClass::VectorSinCos: return this->handleVectorSinCos (parsedInst); default: return DxbcError::eUnhandledOpcode; } } @@ -676,6 +677,20 @@ namespace dxvk { arguments[2].valueId); break; + case DxbcOpcode::Max: + result.valueId = m_module.opFMax( + resultTypeId, + arguments[0].valueId, + arguments[1].valueId); + break; + + case DxbcOpcode::Min: + result.valueId = m_module.opFMin( + resultTypeId, + arguments[0].valueId, + arguments[1].valueId); + break; + case DxbcOpcode::Mov: result.valueId = arguments[0].valueId; break; @@ -747,6 +762,58 @@ namespace dxvk { } + DxbcError DxbcCompiler2::handleVectorSinCos(const DxbcInst& ins) { + // sincos has three operands: + // (1) Destination register for sin(x) + // (2) Destination register for cos(x) + // (3) Source operand x + const DxbcInstOp dstSinOp = ins.operands[0]; + const DxbcInstOp dstCosOp = ins.operands[1]; + const DxbcInstOp srcOp = ins.operands[2]; + + // Load source operand as 32-bit float vector + const DxbcValue2 srcValue = this->loadOp(srcOp, + DxbcRegMask(true, true, true, true), + DxbcScalarType::Float32); + + // Either output may be DxbcOperandType::Null, in + // which case we don't have to generate any code + if (dstSinOp.type != DxbcOperandType::Null) { + const DxbcValue2 sinInput = this->extractReg( + srcValue, dstSinOp.mask); + + DxbcValue2 sinValue; + sinValue.componentType = srcValue.componentType; + sinValue.componentCount = srcValue.componentCount; + sinValue.valueId = m_module.opSin( + this->defineVectorType( + sinInput.componentType, + sinInput.componentCount), + sinInput.valueId); + + this->storeOp(dstSinOp, sinValue); + } + + if (dstCosOp.type != DxbcOperandType::Null) { + const DxbcValue2 cosInput = this->extractReg( + srcValue, dstCosOp.mask); + + DxbcValue2 cosValue; + cosValue.componentType = srcValue.componentType; + cosValue.componentCount = srcValue.componentCount; + cosValue.valueId = m_module.opCos( + this->defineVectorType( + cosInput.componentType, + cosInput.componentCount), + cosInput.valueId); + + this->storeOp(dstCosOp, cosValue); + } + + return DxbcError::sOk; + } + + DxbcValue2 DxbcCompiler2::bitcastReg( const DxbcValue2& src, DxbcScalarType type) { diff --git a/src/dxbc/dxbc_compiler.h b/src/dxbc/dxbc_compiler.h index 8f9dc8bb5..a392d0ce5 100644 --- a/src/dxbc/dxbc_compiler.h +++ b/src/dxbc/dxbc_compiler.h @@ -280,6 +280,9 @@ namespace dxvk { DxbcError handleVectorDot( const DxbcInst& ins); + DxbcError handleVectorSinCos( + const DxbcInst& ins); + /////////////////////// // Declaration methods DxbcError declareGlobalFlags( diff --git a/src/dxbc/dxbc_defs.cpp b/src/dxbc/dxbc_defs.cpp index 1549939eb..3e9582778 100644 --- a/src/dxbc/dxbc_defs.cpp +++ b/src/dxbc/dxbc_defs.cpp @@ -127,9 +127,17 @@ namespace dxvk { { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, } }, /* Min */ - { }, + { 3, DxbcInstClass::VectorAlu, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, /* Max */ - { }, + { 3, DxbcInstClass::VectorAlu, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, /* CustomData */ { }, /* Mov */ @@ -194,7 +202,11 @@ namespace dxvk { /* Switch */ { }, /* SinCos */ - { }, + { 3, DxbcInstClass::VectorSinCos, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, /* UDiv */ { }, /* ULt */ diff --git a/src/dxbc/dxbc_defs.h b/src/dxbc/dxbc_defs.h index 57fede352..e68f15916 100644 --- a/src/dxbc/dxbc_defs.h +++ b/src/dxbc/dxbc_defs.h @@ -20,6 +20,7 @@ namespace dxvk { VectorAlu, ///< Component-wise vector instructions VectorCmp, ///< Component-wise vector comparison VectorDot, ///< Dot product instruction + VectorSinCos, ///< Sine and Cosine instruction ControlFlow, ///< Control flow instructions Undefined, ///< Instruction code not defined }; diff --git a/src/spirv/spirv_module.cpp b/src/spirv/spirv_module.cpp index 4a10e807f..407f9a92f 100644 --- a/src/spirv/spirv_module.cpp +++ b/src/spirv/spirv_module.cpp @@ -785,6 +785,40 @@ namespace dxvk { m_code.putWord(c); return resultId; } + + + uint32_t SpirvModule::opFMax( + uint32_t resultType, + uint32_t a, + uint32_t b) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 7); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450FMax); + m_code.putWord(a); + m_code.putWord(b); + return resultId; + } + + + uint32_t SpirvModule::opFMin( + uint32_t resultType, + uint32_t a, + uint32_t b) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 7); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450FMin); + m_code.putWord(a); + m_code.putWord(b); + return resultId; + } uint32_t SpirvModule::opFClamp( @@ -821,6 +855,36 @@ namespace dxvk { } + uint32_t SpirvModule::opSin( + uint32_t resultType, + uint32_t vector) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450Sin); + m_code.putWord(vector); + return resultId; + } + + + uint32_t SpirvModule::opCos( + uint32_t resultType, + uint32_t vector) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpExtInst, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(m_instExtGlsl450); + m_code.putWord(spv::GLSLstd450Cos); + m_code.putWord(vector); + return resultId; + } + + uint32_t SpirvModule::opInverseSqrt( uint32_t resultType, uint32_t x) { diff --git a/src/spirv/spirv_module.h b/src/spirv/spirv_module.h index 0d83c5a7a..c20ba9aae 100644 --- a/src/spirv/spirv_module.h +++ b/src/spirv/spirv_module.h @@ -281,6 +281,16 @@ namespace dxvk { uint32_t b, uint32_t c); + uint32_t opFMax( + uint32_t resultType, + uint32_t a, + uint32_t b); + + uint32_t opFMin( + uint32_t resultType, + uint32_t a, + uint32_t b); + uint32_t opFClamp( uint32_t resultType, uint32_t x, @@ -292,6 +302,14 @@ namespace dxvk { uint32_t vector1, uint32_t vector2); + uint32_t opSin( + uint32_t resultType, + uint32_t vector); + + uint32_t opCos( + uint32_t resultType, + uint32_t vector); + uint32_t opInverseSqrt( uint32_t resultType, uint32_t x);