mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-01-31 14:52:11 +01:00
[dxbc] Implement optional constant buffer range check
This commit is contained in:
parent
b9bfbb9ccc
commit
9b99c55a2e
@ -4587,35 +4587,6 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
DxbcRegisterPointer DxbcCompiler::emitGetConstBufPtr(
|
||||
const DxbcRegister& operand) {
|
||||
// Constant buffers take a two-dimensional index:
|
||||
// (0) register index (immediate)
|
||||
// (1) constant offset (relative)
|
||||
DxbcRegisterInfo info;
|
||||
info.type.ctype = DxbcScalarType::Float32;
|
||||
info.type.ccount = 4;
|
||||
info.type.alength = 0;
|
||||
info.sclass = spv::StorageClassUniform;
|
||||
|
||||
const uint32_t regId = operand.idx[0].offset;
|
||||
const DxbcRegisterValue constId = emitIndexLoad(operand.idx[1]);
|
||||
|
||||
const uint32_t ptrTypeId = getPointerTypeId(info);
|
||||
|
||||
const std::array<uint32_t, 2> indices =
|
||||
{{ m_module.consti32(0), constId.id }};
|
||||
|
||||
DxbcRegisterPointer result;
|
||||
result.type.ctype = info.type.ctype;
|
||||
result.type.ccount = info.type.ccount;
|
||||
result.id = m_module.opAccessChain(ptrTypeId,
|
||||
m_constantBuffers.at(regId).varId,
|
||||
indices.size(), indices.data());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
DxbcRegisterPointer DxbcCompiler::emitGetImmConstBufPtr(
|
||||
const DxbcRegister& operand) {
|
||||
const DxbcRegisterValue constId
|
||||
@ -4677,9 +4648,6 @@ namespace dxvk {
|
||||
case DxbcOperandType::Output:
|
||||
return emitGetOutputPtr(operand);
|
||||
|
||||
case DxbcOperandType::ConstantBuffer:
|
||||
return emitGetConstBufPtr(operand);
|
||||
|
||||
case DxbcOperandType::ImmediateConstantBuffer:
|
||||
return emitGetImmConstBufPtr(operand);
|
||||
|
||||
@ -5241,8 +5209,31 @@ namespace dxvk {
|
||||
DxbcRegisterValue DxbcCompiler::emitConstantBufferLoad(
|
||||
const DxbcRegister& reg,
|
||||
DxbcRegMask writeMask) {
|
||||
DxbcRegisterPointer ptr = emitGetOperandPtr(reg);
|
||||
// Constant buffers take a two-dimensional index:
|
||||
// (0) register index (immediate)
|
||||
// (1) constant offset (relative)
|
||||
DxbcRegisterInfo info;
|
||||
info.type.ctype = DxbcScalarType::Float32;
|
||||
info.type.ccount = 4;
|
||||
info.type.alength = 0;
|
||||
info.sclass = spv::StorageClassUniform;
|
||||
|
||||
uint32_t regId = reg.idx[0].offset;
|
||||
DxbcRegisterValue constId = emitIndexLoad(reg.idx[1]);
|
||||
|
||||
uint32_t ptrTypeId = getPointerTypeId(info);
|
||||
|
||||
const std::array<uint32_t, 2> indices =
|
||||
{{ m_module.consti32(0), constId.id }};
|
||||
|
||||
DxbcRegisterPointer ptr;
|
||||
ptr.type.ctype = info.type.ctype;
|
||||
ptr.type.ccount = info.type.ccount;
|
||||
ptr.id = m_module.opAccessChain(ptrTypeId,
|
||||
m_constantBuffers.at(regId).varId,
|
||||
indices.size(), indices.data());
|
||||
|
||||
// Load individual components from buffer
|
||||
std::array<uint32_t, 4> ccomps = { 0, 0, 0, 0 };
|
||||
std::array<uint32_t, 4> scomps = { 0, 0, 0, 0 };
|
||||
uint32_t scount = 0;
|
||||
@ -5283,6 +5274,33 @@ namespace dxvk {
|
||||
scount, scomps.data());
|
||||
}
|
||||
|
||||
// HACK: If requested, use the constant buffer size to perform a range
|
||||
// check. This does NOT match the API behaviour, but is needed for some
|
||||
// games since out-of-bounds access is undefined behaviour.
|
||||
if (m_moduleInfo.options.constantBufferRangeCheck && reg.idx[1].relReg) {
|
||||
uint32_t zero = m_module.constf32(0.0f);
|
||||
uint32_t cond = m_module.opULessThan(
|
||||
m_module.defBoolType(), constId.id,
|
||||
m_module.consti32(m_constantBuffers[regId].size));
|
||||
|
||||
if (scount > 1) {
|
||||
std::array<uint32_t, 4> zeroes = {{ zero, zero, zero, zero }};
|
||||
std::array<uint32_t, 4> conds = {{ cond, cond, cond, cond }};
|
||||
|
||||
zero = m_module.opCompositeConstruct(
|
||||
getVectorTypeId(result.type),
|
||||
scount, zeroes.data());
|
||||
cond = m_module.opCompositeConstruct(
|
||||
m_module.defVectorType(m_module.defBoolType(), scount),
|
||||
scount, conds.data());
|
||||
}
|
||||
|
||||
result.id = m_module.opSelect(
|
||||
getVectorTypeId(result.type), cond,
|
||||
result.id, zero);
|
||||
}
|
||||
|
||||
// Apply any post-processing that might be necessary
|
||||
result = emitRegisterBitcast(result, reg.dataType);
|
||||
result = emitSrcOperandModifiers(result, reg.modifiers);
|
||||
return result;
|
||||
|
@ -32,6 +32,10 @@ namespace dxvk {
|
||||
/// Enables sm4-compliant division-by-zero behaviour
|
||||
bool strictDivision = false;
|
||||
|
||||
// Enables range checking for constant buffers.
|
||||
// Fixes issues in some games, breaks others.
|
||||
bool constantBufferRangeCheck = false;
|
||||
|
||||
/// Clear thread-group shared memory to zero
|
||||
bool zeroInitWorkgroupMemory = false;
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user