From 581e505f54bcb7d852183665a1b54af7e305a406 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Sat, 12 May 2018 01:39:23 +0200 Subject: [PATCH] [dxbc] Fix bit scan instructions firstbithi counts from the MSB rather than the LSB. Fixes rendering issues in Hitman. --- src/dxbc/dxbc_compiler.cpp | 54 +++++++++++++++++++++++++++----------- src/dxbc/dxbc_compiler.h | 3 +++ src/dxbc/dxbc_defs.cpp | 6 ++--- src/dxbc/dxbc_defs.h | 1 + 4 files changed, 46 insertions(+), 18 deletions(-) diff --git a/src/dxbc/dxbc_compiler.cpp b/src/dxbc/dxbc_compiler.cpp index 2856cd098..57bd3d2aa 100644 --- a/src/dxbc/dxbc_compiler.cpp +++ b/src/dxbc/dxbc_compiler.cpp @@ -73,6 +73,9 @@ namespace dxvk { case DxbcInstClass::BitInsert: return this->emitBitInsert(ins); + case DxbcInstClass::BitScan: + return this->emitBitScan(ins); + case DxbcInstClass::BufferQuery: return this->emitBufferQuery(ins); @@ -1498,21 +1501,6 @@ namespace dxvk { dst.id = m_module.opBitCount( typeId, src.at(0).id); break; - - case DxbcOpcode::FirstBitLo: - dst.id = m_module.opFindILsb( - typeId, src.at(0).id); - break; - - case DxbcOpcode::FirstBitHi: - dst.id = m_module.opFindUMsb( - typeId, src.at(0).id); - break; - - case DxbcOpcode::FirstBitShi: - dst.id = m_module.opFindSMsb( - typeId, src.at(0).id); - break; case DxbcOpcode::BfRev: dst.id = m_module.opBitReverse( @@ -2304,7 +2292,43 @@ namespace dxvk { emitRegisterStore(ins.dst[0], result); } + + void DxbcCompiler::emitBitScan(const DxbcShaderInstruction& ins) { + // firstbit(lo|hi|shi) have two operands: + // (dst0) The destination operant + // (src0) Source operand to scan + DxbcRegisterValue src = emitRegisterLoad(ins.src[0], ins.dst[0].mask); + DxbcRegisterValue dst; + dst.type.ctype = ins.dst[0].dataType; + dst.type.ccount = ins.dst[0].mask.popCount(); + + // Result type, should be an unsigned integer + const uint32_t typeId = getVectorTypeId(dst.type); + + switch (ins.op) { + case DxbcOpcode::FirstBitLo: dst.id = m_module.opFindILsb(typeId, src.id); break; + case DxbcOpcode::FirstBitHi: dst.id = m_module.opFindUMsb(typeId, src.id); break; + case DxbcOpcode::FirstBitShi: dst.id = m_module.opFindSMsb(typeId, src.id); break; + default: Logger::warn(str::format("DxbcCompiler: Unhandled instruction: ", ins.op)); return; + } + + // The 'Hi' variants are counted from the MSB in DXBC + // rather than the LSB, so we have to invert the number + if (ins.op == DxbcOpcode::FirstBitHi + || ins.op == DxbcOpcode::FirstBitShi) { + dst.id = m_module.opSelect(typeId, + m_module.opINotEqual(m_module.defBoolType(), + dst.id, m_module.constu32(0xFFFFFFFF)), + m_module.opISub(typeId, m_module.constu32(31), dst.id), + m_module.constu32(0xFFFFFFFF)); + } + + // No modifiers are supported + emitRegisterStore(ins.dst[0], dst); + } + + void DxbcCompiler::emitBufferQuery(const DxbcShaderInstruction& ins) { // bufinfo takes two arguments // (dst0) The destination register diff --git a/src/dxbc/dxbc_compiler.h b/src/dxbc/dxbc_compiler.h index c3f18e67c..9b7dd1f74 100644 --- a/src/dxbc/dxbc_compiler.h +++ b/src/dxbc/dxbc_compiler.h @@ -571,6 +571,9 @@ namespace dxvk { void emitBitInsert( const DxbcShaderInstruction& ins); + void emitBitScan( + const DxbcShaderInstruction& ins); + void emitBufferQuery( const DxbcShaderInstruction& ins); diff --git a/src/dxbc/dxbc_defs.cpp b/src/dxbc/dxbc_defs.cpp index 634e60999..499fe6694 100644 --- a/src/dxbc/dxbc_defs.cpp +++ b/src/dxbc/dxbc_defs.cpp @@ -660,17 +660,17 @@ namespace dxvk { { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, } }, /* FirstBitHi */ - { 2, DxbcInstClass::VectorAlu, { + { 2, DxbcInstClass::BitScan, { { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, } }, /* FirstBitLo */ - { 2, DxbcInstClass::VectorAlu, { + { 2, DxbcInstClass::BitScan, { { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, } }, /* FirstBitShi */ - { 2, DxbcInstClass::VectorAlu, { + { 2, DxbcInstClass::BitScan, { { DxbcOperandKind::DstReg, DxbcScalarType::Uint32 }, { DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 }, } }, diff --git a/src/dxbc/dxbc_defs.h b/src/dxbc/dxbc_defs.h index d1cedacaa..f7aa60af1 100644 --- a/src/dxbc/dxbc_defs.h +++ b/src/dxbc/dxbc_defs.h @@ -37,6 +37,7 @@ namespace dxvk { Barrier, ///< Execution or memory barrier BitExtract, ///< Bit field extract operations BitInsert, ///< Bit field insert operations + BitScan, ///< Bit scan operations BufferQuery, ///< Buffer query instruction BufferLoad, ///< Structured or raw buffer load BufferStore, ///< Structured or raw buffer store