From f93745adcf27f943f38283eac0d9251069d22eaf Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Sat, 30 Dec 2017 03:44:19 +0100 Subject: [PATCH] [dxbc] Implemented bfi and bfe instructions --- src/dxbc/dxbc_compiler.cpp | 83 +++++++++++++++++++++++++++++++ src/dxbc/dxbc_compiler.h | 14 ++++++ src/dxbc/dxbc_defs.cpp | 27 ++++++++-- src/dxbc/dxbc_defs.h | 2 + src/spirv/spirv_module.cpp | 53 ++++++++++++++++++++ src/spirv/spirv_module.h | 19 +++++++ tests/dxbc/test_hlsl_compiler.cpp | 3 +- 7 files changed, 196 insertions(+), 5 deletions(-) diff --git a/src/dxbc/dxbc_compiler.cpp b/src/dxbc/dxbc_compiler.cpp index 419a758e..04baa109 100644 --- a/src/dxbc/dxbc_compiler.cpp +++ b/src/dxbc/dxbc_compiler.cpp @@ -72,6 +72,12 @@ namespace dxvk { case DxbcInstClass::Barrier: return this->emitBarrier(ins); + case DxbcInstClass::BitExtract: + return this->emitBitExtract(ins); + + case DxbcInstClass::BitInsert: + return this->emitBitInsert(ins); + case DxbcInstClass::BufferQuery: return this->emitBufferQuery(ins); @@ -996,6 +1002,13 @@ namespace dxvk { src.at(0).id, src.at(1).id); break; + case DxbcOpcode::Rcp: { + const std::array ones = {{ 1.0f, 1.0f, 1.0f, 1.0f }}; + dst.id = m_module.opFDiv(typeId, + emitBuildConstVecf32(ones.data(), ins.dst[0].mask).id, + src.at(0).id); + } break; + case DxbcOpcode::RoundNe: dst.id = m_module.opRoundEven( typeId, src.at(0).id); @@ -1591,6 +1604,53 @@ namespace dxvk { } + void DxbcCompiler::emitBitExtract(const DxbcShaderInstruction& ins) { + // ibfe and ubfe take the following arguments: + // (dst0) The destination register + // (src0) Number of bits to extact + // (src1) Offset of the bits to extract + // (src2) Register to extract bits from + const bool isSigned = ins.op == DxbcOpcode::IBfe; + + const DxbcRegisterValue bitCnt = emitRegisterLoad(ins.src[0], ins.dst[0].mask); + const DxbcRegisterValue bitOfs = emitRegisterLoad(ins.src[1], ins.dst[0].mask); + + const DxbcRegisterValue src = emitRegisterLoad(ins.src[2], ins.dst[0].mask); + const uint32_t typeId = getVectorTypeId(src.type); + + DxbcRegisterValue result; + result.type = src.type; + result.id = isSigned + ? m_module.opBitFieldSExtract(typeId, result.id, bitOfs.id, bitCnt.id) + : m_module.opBitFieldUExtract(typeId, result.id, bitOfs.id, bitCnt.id); + + emitRegisterStore(ins.dst[0], result); + } + + + void DxbcCompiler::emitBitInsert(const DxbcShaderInstruction& ins) { + // ibfe and ubfe take the following arguments: + // (dst0) The destination register + // (src0) Number of bits to extact + // (src1) Offset of the bits to extract + // (src2) Register to take bits from + // (src3) Register to replace bits in + const DxbcRegisterValue bitCnt = emitRegisterLoad(ins.src[0], ins.dst[0].mask); + const DxbcRegisterValue bitOfs = emitRegisterLoad(ins.src[1], ins.dst[0].mask); + + const DxbcRegisterValue insert = emitRegisterLoad(ins.src[2], ins.dst[0].mask); + const DxbcRegisterValue base = emitRegisterLoad(ins.src[3], ins.dst[0].mask); + + DxbcRegisterValue result; + result.type = base.type; + result.id = m_module.opBitFieldInsert( + getVectorTypeId(result.type), + base.id, insert.id, bitOfs.id, bitCnt.id); + + emitRegisterStore(ins.dst[0], result); + } + + void DxbcCompiler::emitBufferQuery(const DxbcShaderInstruction& ins) { // bufinfo takes two arguments // (dst0) The destination register @@ -2307,6 +2367,29 @@ namespace dxvk { } + DxbcRegisterValue DxbcCompiler::emitBuildConstVecf32( + const float values[4], + const DxbcRegMask& writeMask) { + std::array ids = { 0, 0, 0, 0 }; + uint32_t componentIndex = 0; + + for (uint32_t i = 0; i < 4; i++) { + if (writeMask[i]) + ids[componentIndex++] = m_module.constf32(values[i]); + } + + DxbcRegisterValue result; + result.type.ctype = DxbcScalarType::Float32; + result.type.ccount = componentIndex; + result.id = componentIndex > 1 + ? m_module.constComposite( + getVectorTypeId(result.type), + componentIndex, ids.data()) + : ids[0]; + return result; + } + + DxbcRegisterValue DxbcCompiler::emitRegisterBitcast( DxbcRegisterValue srcValue, DxbcScalarType dstType) { diff --git a/src/dxbc/dxbc_compiler.h b/src/dxbc/dxbc_compiler.h index dce7f741..f956e053 100644 --- a/src/dxbc/dxbc_compiler.h +++ b/src/dxbc/dxbc_compiler.h @@ -395,6 +395,12 @@ namespace dxvk { void emitBarrier( const DxbcShaderInstruction& ins); + void emitBitExtract( + const DxbcShaderInstruction& ins); + + void emitBitInsert( + const DxbcShaderInstruction& ins); + void emitBufferQuery( const DxbcShaderInstruction& ins); @@ -445,6 +451,14 @@ namespace dxvk { void emitControlFlow( const DxbcShaderInstruction& ins); + //////////////////////////////////////////////// + // Constant building methods. These are used to + // generate constant vectors that store the same + // value in each component. + DxbcRegisterValue emitBuildConstVecf32( + const float values[4], + const DxbcRegMask& writeMask); + ///////////////////////////////////////// // Generic register manipulation methods DxbcRegisterValue emitRegisterBitcast( diff --git a/src/dxbc/dxbc_defs.cpp b/src/dxbc/dxbc_defs.cpp index 87a06ab1..f5460836 100644 --- a/src/dxbc/dxbc_defs.cpp +++ b/src/dxbc/dxbc_defs.cpp @@ -581,7 +581,10 @@ namespace dxvk { /* Gather4PoC */ { }, /* Rcp */ - { }, + { 2, DxbcInstClass::VectorAlu, { + { DxbcOperandKind::DstReg, DxbcScalarType::Float32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Float32 }, + } }, /* F32toF16 */ { }, /* F16toF32 */ @@ -599,11 +602,27 @@ namespace dxvk { /* FirstBitShi */ { }, /* UBfe */ - { }, + { 4, DxbcInstClass::BitExtract, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, /* IBfe */ - { }, + { 4, DxbcInstClass::BitExtract, { + { DxbcOperandKind::DstReg, DxbcScalarType::Sint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Sint32 }, + } }, /* Bfi */ - { }, + { 5, DxbcInstClass::BitInsert, { + { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, + } }, /* BfRev */ { }, /* Swapc */ diff --git a/src/dxbc/dxbc_defs.h b/src/dxbc/dxbc_defs.h index 81a2600f..35a91f9f 100644 --- a/src/dxbc/dxbc_defs.h +++ b/src/dxbc/dxbc_defs.h @@ -34,6 +34,8 @@ namespace dxvk { GeometryEmit, ///< Special geometry shader instructions Atomic, ///< Atomic operations Barrier, ///< Execution or memory barrier + BitExtract, ///< Bit field extract operations + BitInsert, ///< Bit field insert operations BufferQuery, ///< Buffer query instruction BufferLoad, ///< Structured or raw buffer load BufferStore, ///< Structured or raw buffer store diff --git a/src/spirv/spirv_module.cpp b/src/spirv/spirv_module.cpp index 289055ca..6a3fc8d2 100644 --- a/src/spirv/spirv_module.cpp +++ b/src/spirv/spirv_module.cpp @@ -604,6 +604,59 @@ namespace dxvk { } + uint32_t SpirvModule::opBitFieldInsert( + uint32_t resultType, + uint32_t base, + uint32_t insert, + uint32_t offset, + uint32_t count) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpBitFieldInsert, 7); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(base); + m_code.putWord(insert); + m_code.putWord(offset); + m_code.putWord(count); + return resultId; + } + + + uint32_t SpirvModule::opBitFieldSExtract( + uint32_t resultType, + uint32_t base, + uint32_t offset, + uint32_t count) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpBitFieldSExtract, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(base); + m_code.putWord(offset); + m_code.putWord(count); + return resultId; + } + + + uint32_t SpirvModule::opBitFieldUExtract( + uint32_t resultType, + uint32_t base, + uint32_t offset, + uint32_t count) { + uint32_t resultId = this->allocateId(); + + m_code.putIns (spv::OpBitFieldUExtract, 6); + m_code.putWord(resultType); + m_code.putWord(resultId); + m_code.putWord(base); + m_code.putWord(offset); + m_code.putWord(count); + return resultId; + } + + uint32_t SpirvModule::opBitwiseAnd( uint32_t resultType, uint32_t operand1, diff --git a/src/spirv/spirv_module.h b/src/spirv/spirv_module.h index c3a61334..6cdae38f 100644 --- a/src/spirv/spirv_module.h +++ b/src/spirv/spirv_module.h @@ -237,6 +237,25 @@ namespace dxvk { uint32_t resultType, uint32_t operand); + uint32_t opBitFieldInsert( + uint32_t resultType, + uint32_t base, + uint32_t insert, + uint32_t offset, + uint32_t count); + + uint32_t opBitFieldSExtract( + uint32_t resultType, + uint32_t base, + uint32_t offset, + uint32_t count); + + uint32_t opBitFieldUExtract( + uint32_t resultType, + uint32_t base, + uint32_t offset, + uint32_t count); + uint32_t opBitwiseAnd( uint32_t resultType, uint32_t operand1, diff --git a/tests/dxbc/test_hlsl_compiler.cpp b/tests/dxbc/test_hlsl_compiler.cpp index 38b56f3e..8b9a204c 100644 --- a/tests/dxbc/test_hlsl_compiler.cpp +++ b/tests/dxbc/test_hlsl_compiler.cpp @@ -47,7 +47,8 @@ int WINAPI WinMain(HINSTANCE hInstance, "Shader", nullptr, nullptr, str::fromws(entryPoint).c_str(), str::fromws(target).c_str(), - 0, 0, &binary, &errors); + D3DCOMPILE_OPTIMIZATION_LEVEL3, + 0, &binary, &errors); if (FAILED(hr)) { if (errors != nullptr)