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

Revert "[dxbc] Bound-check dynamically indexed constant buffer reads"

This reverts commit 621aed5fdbaf92764944be7b3a27cbb3df63ba94.

Breaks Dishonored 2. Apparently, out-of-bounds access to constant buffers
is allowed as long as it doesn't exceed the range of bound constants.
This commit is contained in:
Philip Rebohle 2018-06-02 18:09:59 +02:00
parent 34477933ef
commit 217399926d
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
2 changed files with 36 additions and 71 deletions

View File

@ -4210,6 +4210,35 @@ 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( DxbcRegisterPointer DxbcCompiler::emitGetImmConstBufPtr(
const DxbcRegister& operand) { const DxbcRegister& operand) {
if (m_immConstBuf == 0) if (m_immConstBuf == 0)
@ -4252,6 +4281,9 @@ namespace dxvk {
case DxbcOperandType::Output: case DxbcOperandType::Output:
return emitGetOutputPtr(operand); return emitGetOutputPtr(operand);
case DxbcOperandType::ConstantBuffer:
return emitGetConstBufPtr(operand);
case DxbcOperandType::ImmediateConstantBuffer: case DxbcOperandType::ImmediateConstantBuffer:
return emitGetImmConstBufPtr(operand); return emitGetImmConstBufPtr(operand);
@ -4708,22 +4740,6 @@ namespace dxvk {
} }
DxbcRegisterValue DxbcCompiler::emitIndexBoundCheck(
DxbcRegisterValue index,
DxbcRegisterValue count) {
index = emitRegisterBitcast(index, DxbcScalarType::Uint32);
count = emitRegisterBitcast(count, DxbcScalarType::Uint32);
DxbcRegisterValue result;
result.type.ctype = DxbcScalarType::Bool;
result.type.ccount = index.type.ccount;
result.id = m_module.opULessThan(
getVectorTypeId(result.type),
index.id, count.id);
return result;
}
DxbcRegisterValue DxbcCompiler::emitIndexLoad( DxbcRegisterValue DxbcCompiler::emitIndexLoad(
DxbcRegIndex index) { DxbcRegIndex index) {
if (index.relReg != nullptr) { if (index.relReg != nullptr) {
@ -4786,56 +4802,9 @@ namespace dxvk {
} }
DxbcRegisterValue DxbcCompiler::emitConstBufLoadRaw(
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 pointer;
pointer.type.ctype = info.type.ctype;
pointer.type.ccount = info.type.ccount;
pointer.id = m_module.opAccessChain(ptrTypeId,
m_constantBuffers.at(regId).varId,
indices.size(), indices.data());
DxbcRegisterValue value = emitValueLoad(pointer);
// For dynamically indexed constant buffers, we should
// return a vec4(ß.0f) if the index is out of bounds
if (operand.idx[1].relReg != nullptr) {
DxbcRegisterValue cbSize;
cbSize.type = { DxbcScalarType::Uint32, 1 };
cbSize.id = m_module.constu32(m_constantBuffers.at(regId).size);
DxbcRegisterValue inBounds = emitRegisterExtend(emitIndexBoundCheck(constId, cbSize), 4);
value.id = m_module.opSelect(
getVectorTypeId(value.type), inBounds.id, value.id,
m_module.constvec4f32(0.0f, 0.0f, 0.0f, 0.0f));
}
return value;
}
DxbcRegisterValue DxbcCompiler::emitRegisterLoadRaw( DxbcRegisterValue DxbcCompiler::emitRegisterLoadRaw(
const DxbcRegister& reg) { const DxbcRegister& reg) {
return reg.type == DxbcOperandType::ConstantBuffer return emitValueLoad(emitGetOperandPtr(reg));
? emitConstBufLoadRaw(reg)
: emitValueLoad(emitGetOperandPtr(reg));
} }

View File

@ -819,6 +819,9 @@ namespace dxvk {
DxbcRegisterPointer emitGetOutputPtr( DxbcRegisterPointer emitGetOutputPtr(
const DxbcRegister& operand); const DxbcRegister& operand);
DxbcRegisterPointer emitGetConstBufPtr(
const DxbcRegister& operand);
DxbcRegisterPointer emitGetImmConstBufPtr( DxbcRegisterPointer emitGetImmConstBufPtr(
const DxbcRegister& operand); const DxbcRegister& operand);
@ -876,10 +879,6 @@ namespace dxvk {
////////////////////////////// //////////////////////////////
// Operand load/store methods // Operand load/store methods
DxbcRegisterValue emitIndexBoundCheck(
DxbcRegisterValue index,
DxbcRegisterValue count);
DxbcRegisterValue emitIndexLoad( DxbcRegisterValue emitIndexLoad(
DxbcRegIndex index); DxbcRegIndex index);
@ -891,9 +890,6 @@ namespace dxvk {
DxbcRegisterValue value, DxbcRegisterValue value,
DxbcRegMask writeMask); DxbcRegMask writeMask);
DxbcRegisterValue emitConstBufLoadRaw(
const DxbcRegister& operand);
DxbcRegisterValue emitRegisterLoadRaw( DxbcRegisterValue emitRegisterLoadRaw(
const DxbcRegister& reg); const DxbcRegister& reg);