From 109ce0a695154ce03771fec789d3962322a7cd8b Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Wed, 20 Dec 2017 23:50:39 +0100 Subject: [PATCH] [dxbc] Implemented sample_d and vector shift instructions --- build-win64.txt | 2 +- src/dxbc/dxbc_compiler.cpp | 99 ++++++++++++++++++++++++++++++++++++-- src/dxbc/dxbc_compiler.h | 3 ++ src/dxbc/dxbc_decoder.h | 4 +- src/dxbc/dxbc_defs.cpp | 58 ++++++++++++++++++---- src/dxbc/dxbc_defs.h | 1 + src/spirv/spirv_module.cpp | 80 +++++++++++++++++++++++++++++- src/spirv/spirv_module.h | 25 ++++++++++ 8 files changed, 255 insertions(+), 17 deletions(-) diff --git a/build-win64.txt b/build-win64.txt index cb2eb0ea..63d67d83 100644 --- a/build-win64.txt +++ b/build-win64.txt @@ -9,7 +9,7 @@ exe_wrapper = 'wine' c_args = ['-Og', '-ggdb'] c_link_args = ['-static', '-static-libgcc'] -cpp_args = ['-Og', '-gdwarf'] +cpp_args = ['-Og', '-gstabs'] cpp_link_args = ['-static', '-static-libgcc', '-static-libstdc++'] [host_machine] diff --git a/src/dxbc/dxbc_compiler.cpp b/src/dxbc/dxbc_compiler.cpp index c3f20a43..0127adca 100644 --- a/src/dxbc/dxbc_compiler.cpp +++ b/src/dxbc/dxbc_compiler.cpp @@ -86,6 +86,9 @@ namespace dxvk { case DxbcInstClass::VectorImul: return this->emitVectorImul(ins); + case DxbcInstClass::VectorShift: + return this->emitVectorShift(ins); + case DxbcInstClass::VectorSinCos: return this->emitVectorSinCos(ins); @@ -780,6 +783,7 @@ namespace dxvk { break; case DxbcOpcode::IMad: + case DxbcOpcode::UMad: dst.id = m_module.opIAdd(typeId, m_module.opIMul(typeId, src.at(0).id, src.at(1).id), @@ -801,6 +805,18 @@ namespace dxvk { typeId, src.at(0).id); break; + /////////////////////////////////////// + // ALU operations on unsigned integers + case DxbcOpcode::UMax: + dst.id = m_module.opUMax(typeId, + src.at(0).id, src.at(1).id); + break; + + case DxbcOpcode::UMin: + dst.id = m_module.opUMin(typeId, + src.at(0).id, src.at(1).id); + break; + /////////////////////////////////////// // Bit operations on unsigned integers case DxbcOpcode::And: @@ -1157,6 +1173,57 @@ namespace dxvk { } + void DxbcCompiler::emitVectorShift(const DxbcShaderInstruction& ins) { + // Shift operations have three operands: + // (dst0) The destination register + // (src0) The register to shift + // (src1) The shift amount (scalar) + const DxbcRegisterValue shiftReg = emitRegisterLoad( + ins.src[0], ins.dst[0].mask); + + DxbcRegisterValue countReg = emitRegisterLoad( + ins.src[1], DxbcRegMask(true, false, false, false)); + + // Unlike in DXBC, SPIR-V shift operations allow different + // shift amounts per component, so we'll extend the count + // register to a vector. + countReg = emitRegisterExtend(countReg, shiftReg.type.ccount); + + DxbcRegisterValue result; + result.type.ctype = ins.dst[0].dataType; + result.type.ccount = ins.dst[0].mask.setCount(); + + switch (ins.op) { + case DxbcOpcode::IShl: + result.id = m_module.opShiftLeftLogical( + getVectorTypeId(result.type), + shiftReg.id, countReg.id); + break; + + case DxbcOpcode::IShr: + result.id = m_module.opShiftRightArithmetic( + getVectorTypeId(result.type), + shiftReg.id, countReg.id); + break; + + case DxbcOpcode::UShr: + result.id = m_module.opShiftRightLogical( + getVectorTypeId(result.type), + shiftReg.id, countReg.id); + break; + + default: + Logger::warn(str::format( + "DxbcCompiler: Unhandled instruction: ", + ins.op)); + return; + } + + result = emitDstOperandModifiers(result, ins.modifiers); + emitRegisterStore(ins.dst[0], result); + } + + void DxbcCompiler::emitVectorSinCos(const DxbcShaderInstruction& ins) { // sincos has three operands: // (dst0) Destination register for sin(x) @@ -1232,20 +1299,33 @@ namespace dxvk { const uint32_t textureId = textureReg.idx[0].offset; const uint32_t samplerId = samplerReg.idx[0].offset; + // FIXME implement properly + DxbcRegMask coordArrayMask(true, true, true, true); + DxbcRegMask coordLayerMask(true, true, true, true); + // Load the texture coordinates. SPIR-V allows these // to be float4 even if not all components are used. - const DxbcRegisterValue coord = emitRegisterLoad( - texCoordReg, DxbcRegMask(true, true, true, true)); + const DxbcRegisterValue coord = emitRegisterLoad(texCoordReg, coordArrayMask); - // Determine whether this is a depth-compare op + // Load reference value for depth-compare operations const bool isDepthCompare = ins.op == DxbcOpcode::SampleC || ins.op == DxbcOpcode::SampleClz; - // Load reference value for depth-compare operations const DxbcRegisterValue referenceValue = isDepthCompare ? emitRegisterLoad(ins.src[3], DxbcRegMask(true, false, false, false)) : DxbcRegisterValue(); + // Load explicit gradients for sample operations that require them + const bool explicitGradients = ins.op == DxbcOpcode::SampleD; + + const DxbcRegisterValue explicitGradientX = explicitGradients + ? emitRegisterLoad(ins.src[3], coordLayerMask) + : DxbcRegisterValue(); + + const DxbcRegisterValue explicitGradientY = explicitGradients + ? emitRegisterLoad(ins.src[4], coordLayerMask) + : DxbcRegisterValue(); + // Determine the sampled image type based on the opcode. // FIXME while this is in line what the officla glsl compiler // does, this might actually violate the SPIR-V specification. @@ -1300,6 +1380,17 @@ namespace dxvk { referenceValue.id, imageOperands); } break; + // Sample operation with explicit gradients + case DxbcOpcode::SampleD: { + imageOperands.flags |= spv::ImageOperandsGradMask; + imageOperands.sGradX = explicitGradientX.id; + imageOperands.sGradY = explicitGradientY.id; + + result.id = m_module.opImageSampleExplicitLod( + getVectorTypeId(result.type), sampledImageId, coord.id, + imageOperands); + } break; + default: Logger::warn(str::format( "DxbcCompiler: Unhandled instruction: ", diff --git a/src/dxbc/dxbc_compiler.h b/src/dxbc/dxbc_compiler.h index 5ac0951c..cc2e3c72 100644 --- a/src/dxbc/dxbc_compiler.h +++ b/src/dxbc/dxbc_compiler.h @@ -328,6 +328,9 @@ namespace dxvk { void emitVectorImul( const DxbcShaderInstruction& ins); + void emitVectorShift( + const DxbcShaderInstruction& ins); + void emitVectorSinCos( const DxbcShaderInstruction& ins); diff --git a/src/dxbc/dxbc_decoder.h b/src/dxbc/dxbc_decoder.h index 66659946..1a16f17f 100644 --- a/src/dxbc/dxbc_decoder.h +++ b/src/dxbc/dxbc_decoder.h @@ -332,8 +332,8 @@ namespace dxvk { DxbcShaderInstruction m_instruction; - std::array m_dstOperands; - std::array m_srcOperands; + std::array m_dstOperands; + std::array m_srcOperands; std::array m_immOperands; std::array m_indices; diff --git a/src/dxbc/dxbc_defs.cpp b/src/dxbc/dxbc_defs.cpp index 80ed95c2..147841f9 100644 --- a/src/dxbc/dxbc_defs.cpp +++ b/src/dxbc/dxbc_defs.cpp @@ -186,9 +186,17 @@ namespace dxvk { { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, } }, /* IShl */ - { }, + { 3, DxbcInstClass::VectorShift, { + { DxbcOperandKind::DstReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, /* IShr */ - { }, + { 3, DxbcInstClass::VectorShift, { + { DxbcOperandKind::DstReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, /* ItoF */ { 2, DxbcInstClass::VectorAlu, { { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, @@ -318,7 +326,14 @@ namespace dxvk { /* SampleL */ { }, /* SampleD */ - { }, + { 6, DxbcInstClass::TextureSample, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, /* SampleB */ { }, /* Sqrt */ @@ -342,9 +357,17 @@ namespace dxvk { { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, } }, /* ULt */ - { }, + { 3, DxbcInstClass::VectorCmp, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, /* UGe */ - { }, + { 3, DxbcInstClass::VectorCmp, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, /* UMul */ { 4, DxbcInstClass::VectorImul, { { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, @@ -353,13 +376,30 @@ namespace dxvk { { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, } }, /* UMad */ - { }, + { 4, DxbcInstClass::VectorAlu, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, /* UMax */ - { }, + { 3, DxbcInstClass::VectorAlu, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, /* UMin */ - { }, + { 3, DxbcInstClass::VectorAlu, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, /* UShr */ - { }, + { 3, DxbcInstClass::VectorShift, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, /* UtoF */ { 2, DxbcInstClass::VectorAlu, { { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, diff --git a/src/dxbc/dxbc_defs.h b/src/dxbc/dxbc_defs.h index a3668e20..2ce3c684 100644 --- a/src/dxbc/dxbc_defs.h +++ b/src/dxbc/dxbc_defs.h @@ -40,6 +40,7 @@ namespace dxvk { VectorDot, ///< Dot product instruction VectorIdiv, ///< Component-wise integer division VectorImul, ///< Component-wise integer multiplication + VectorShift, ///< Bit shift operations on vectors VectorSinCos, ///< Sine and Cosine instruction Undefined, ///< Instruction code not defined }; diff --git a/src/spirv/spirv_module.cpp b/src/spirv/spirv_module.cpp index 737b7c9c..5fc61c60 100644 --- a/src/spirv/spirv_module.cpp +++ b/src/spirv/spirv_module.cpp @@ -654,6 +654,51 @@ namespace dxvk { } + uint32_t SpirvModule::opShiftLeftLogical( + uint32_t resultType, + uint32_t base, + uint32_t shift) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpShiftLeftLogical, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(base); + m_code.putWord(shift); + return resultId; + } + + + uint32_t SpirvModule::opShiftRightArithmetic( + uint32_t resultType, + uint32_t base, + uint32_t shift) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpShiftRightArithmetic, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(base); + m_code.putWord(shift); + return resultId; + } + + + uint32_t SpirvModule::opShiftRightLogical( + uint32_t resultType, + uint32_t base, + uint32_t shift) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpShiftRightLogical, 5); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(base); + m_code.putWord(shift); + return resultId; + } + + uint32_t SpirvModule::opConvertFtoS( uint32_t resultType, uint32_t operand) { @@ -1136,6 +1181,40 @@ namespace dxvk { } + uint32_t SpirvModule::opUMax( + 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::GLSLstd450UMax); + m_code.putWord(a); + m_code.putWord(b); + return resultId; + } + + + uint32_t SpirvModule::opUMin( + 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::GLSLstd450UMin); + m_code.putWord(a); + m_code.putWord(b); + return resultId; + } + + uint32_t SpirvModule::opFClamp( uint32_t resultType, uint32_t x, @@ -1550,7 +1629,6 @@ namespace dxvk { m_code.putWord(resultId); m_code.putWord(sampledImage); m_code.putWord(coordinates); - m_code.putWord(spv::ImageOperandsLodMask); putImageOperands(operands); return resultId; diff --git a/src/spirv/spirv_module.h b/src/spirv/spirv_module.h index 1717972f..340ab9b0 100644 --- a/src/spirv/spirv_module.h +++ b/src/spirv/spirv_module.h @@ -253,6 +253,21 @@ namespace dxvk { uint32_t resultType, uint32_t operand); + uint32_t opShiftLeftLogical( + uint32_t resultType, + uint32_t base, + uint32_t shift); + + uint32_t opShiftRightArithmetic( + uint32_t resultType, + uint32_t base, + uint32_t shift); + + uint32_t opShiftRightLogical( + uint32_t resultType, + uint32_t base, + uint32_t shift); + uint32_t opConvertFtoS( uint32_t resultType, uint32_t operand); @@ -405,6 +420,16 @@ namespace dxvk { uint32_t a, uint32_t b); + uint32_t opUMax( + uint32_t resultType, + uint32_t a, + uint32_t b); + + uint32_t opUMin( + uint32_t resultType, + uint32_t a, + uint32_t b); + uint32_t opFClamp( uint32_t resultType, uint32_t x,