1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-01-18 20:52:10 +01:00

[dxbc] Bounds-check temporary array stores

Fixes flickering terrain in Just Cause 3 on RADV and possibly ANV.
This commit is contained in:
Rhys Perry 2020-09-11 12:07:02 +01:00 committed by Philip Rebohle
parent 4801fbe098
commit 73cb711f32
2 changed files with 54 additions and 25 deletions

View File

@ -387,6 +387,7 @@ namespace dxvk {
m_xRegs.resize(regId + 1);
m_xRegs.at(regId).ccount = info.type.ccount;
m_xRegs.at(regId).alength = info.type.alength;
m_xRegs.at(regId).varId = emitNewVariable(info);
m_module.setDebugName(m_xRegs.at(regId).varId,
@ -4724,28 +4725,7 @@ namespace dxvk {
DxbcRegisterPointer DxbcCompiler::emitGetIndexableTempPtr(
const DxbcRegister& operand) {
// x# regs are indexed as follows:
// (0) register index (immediate)
// (1) element index (relative)
const uint32_t regId = operand.idx[0].offset;
const DxbcRegisterValue vectorId
= emitIndexLoad(operand.idx[1]);
DxbcRegisterInfo info;
info.type.ctype = DxbcScalarType::Float32;
info.type.ccount = m_xRegs[regId].ccount;
info.type.alength = 0;
info.sclass = spv::StorageClassPrivate;
DxbcRegisterPointer result;
result.type.ctype = info.type.ctype;
result.type.ccount = info.type.ccount;
result.id = m_module.opAccessChain(
getPointerTypeId(info),
m_xRegs.at(regId).varId,
1, &vectorId.id);
return result;
return getIndexableTempPtr(operand, emitIndexLoad(operand.idx[1]));
}
@ -5673,7 +5653,27 @@ namespace dxvk {
void DxbcCompiler::emitRegisterStore(
const DxbcRegister& reg,
DxbcRegisterValue value) {
emitValueStore(emitGetOperandPtr(reg), value, reg.mask);
if (reg.type == DxbcOperandType::IndexableTemp) {
DxbcRegisterValue vectorId = emitIndexLoad(reg.idx[1]);
uint32_t boundsCheck = m_module.opULessThan(
m_module.defBoolType(), vectorId.id,
m_module.constu32(m_xRegs.at(reg.idx[0].offset).alength));
DxbcConditional cond;
cond.labelIf = m_module.allocateId();
cond.labelEnd = m_module.allocateId();
m_module.opSelectionMerge(cond.labelEnd, spv::SelectionControlMaskNone);
m_module.opBranchConditional(boundsCheck, cond.labelIf, cond.labelEnd);
m_module.opLabel(cond.labelIf);
emitValueStore(getIndexableTempPtr(reg, vectorId), value, reg.mask);
m_module.opBranch(cond.labelEnd);
m_module.opLabel (cond.labelEnd);
} else {
emitValueStore(emitGetOperandPtr(reg), value, reg.mask);
}
}
@ -7686,6 +7686,30 @@ namespace dxvk {
|| type == DxbcScalarType::Float64;
}
DxbcRegisterPointer DxbcCompiler::getIndexableTempPtr(
const DxbcRegister& operand,
DxbcRegisterValue vectorId) {
// x# regs are indexed as follows:
// (0) register index (immediate)
// (1) element index (relative)
const uint32_t regId = operand.idx[0].offset;
DxbcRegisterInfo info;
info.type.ctype = DxbcScalarType::Float32;
info.type.ccount = m_xRegs[regId].ccount;
info.type.alength = 0;
info.sclass = spv::StorageClassPrivate;
DxbcRegisterPointer result;
result.type.ctype = info.type.ctype;
result.type.ccount = info.type.ccount;
result.id = m_module.opAccessChain(
getPointerTypeId(info),
m_xRegs.at(regId).varId,
1, &vectorId.id);
return result;
}
uint32_t DxbcCompiler::getScalarTypeId(DxbcScalarType type) {
if (type == DxbcScalarType::Float64)

View File

@ -83,8 +83,9 @@ namespace dxvk {
struct DxbcXreg {
uint32_t ccount = 0;
uint32_t varId = 0;
uint32_t ccount = 0;
uint32_t alength = 0;
uint32_t varId = 0;
};
@ -1221,6 +1222,10 @@ namespace dxvk {
bool isDoubleType(
DxbcScalarType type) const;
DxbcRegisterPointer getIndexableTempPtr(
const DxbcRegister& operand,
DxbcRegisterValue vectorId);
///////////////////////////
// Type definition methods
uint32_t getScalarTypeId(