1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-01-19 05:52:11 +01:00

[dxbc] Fix bit scan instructions

firstbithi counts from the MSB rather than the LSB. Fixes
rendering issues in Hitman.
This commit is contained in:
Philip Rebohle 2018-05-12 01:39:23 +02:00
parent 32631caf96
commit 581e505f54
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
4 changed files with 46 additions and 18 deletions

View File

@ -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

View File

@ -571,6 +571,9 @@ namespace dxvk {
void emitBitInsert(
const DxbcShaderInstruction& ins);
void emitBitScan(
const DxbcShaderInstruction& ins);
void emitBufferQuery(
const DxbcShaderInstruction& ins);

View File

@ -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 },
} },

View File

@ -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