mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-03-03 16:29:15 +01:00
[dxbc] Bound-check dynamically indexed input registers
Halo MCC reads undefined PS inputs otherwise.
This commit is contained in:
parent
7f4e25267c
commit
f17317061c
@ -281,7 +281,7 @@ namespace dxvk {
|
||||
return this->emitDclGlobalFlags(ins);
|
||||
|
||||
case DxbcOpcode::DclIndexRange:
|
||||
return; // not needed for anything
|
||||
return this->emitDclIndexRange(ins);
|
||||
|
||||
case DxbcOpcode::DclTemps:
|
||||
return this->emitDclTemps(ins);
|
||||
@ -375,6 +375,21 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
void DxbcCompiler::emitDclIndexRange(const DxbcShaderInstruction& ins) {
|
||||
// dcl_index_range has one operand:
|
||||
// (0) Range start, either an input or output register
|
||||
// (1) Range end
|
||||
uint32_t index = ins.dst[0].idxDim - 1u;
|
||||
|
||||
DxbcIndexRange range = { };
|
||||
range.type = ins.dst[0].type;
|
||||
range.start = ins.dst[0].idx[index].offset;
|
||||
range.length = ins.imm[0].u32;
|
||||
|
||||
m_indexRanges.push_back(range);
|
||||
}
|
||||
|
||||
|
||||
void DxbcCompiler::emitDclTemps(const DxbcShaderInstruction& ins) {
|
||||
// dcl_temps has one operand:
|
||||
// (imm0) Number of temp registers
|
||||
@ -5737,14 +5752,37 @@ namespace dxvk {
|
||||
|
||||
DxbcRegisterValue DxbcCompiler::emitRegisterLoadRaw(
|
||||
const DxbcRegister& reg) {
|
||||
if (reg.type == DxbcOperandType::IndexableTemp) {
|
||||
bool doBoundsCheck = reg.idx[1].relReg != nullptr;
|
||||
DxbcRegisterValue vectorId = emitIndexLoad(reg.idx[1]);
|
||||
// Try to find index range for the given register
|
||||
const DxbcIndexRange* indexRange = nullptr;
|
||||
|
||||
if (reg.idxDim && reg.idx[reg.idxDim - 1u].relReg) {
|
||||
uint32_t offset = reg.idx[reg.idxDim - 1u].offset;
|
||||
|
||||
for (const auto& range : m_indexRanges) {
|
||||
if (reg.type == range.type && offset >= range.start && offset < range.start + range.length)
|
||||
indexRange = ⦥
|
||||
}
|
||||
}
|
||||
|
||||
if (reg.type == DxbcOperandType::IndexableTemp || indexRange) {
|
||||
bool doBoundsCheck = reg.idx[reg.idxDim - 1u].relReg != nullptr;
|
||||
|
||||
if (doBoundsCheck) {
|
||||
uint32_t boundsCheck = m_module.opULessThan(
|
||||
m_module.defBoolType(), vectorId.id,
|
||||
m_module.constu32(m_xRegs.at(reg.idx[0].offset).alength));
|
||||
DxbcRegisterValue indexId = emitIndexLoad(reg.idx[reg.idxDim - 1u]);
|
||||
uint32_t boundsCheck = 0u;
|
||||
|
||||
if (reg.type == DxbcOperandType::IndexableTemp) {
|
||||
boundsCheck = m_module.opULessThan(
|
||||
m_module.defBoolType(), indexId.id,
|
||||
m_module.constu32(m_xRegs.at(reg.idx[0].offset).alength));
|
||||
} else {
|
||||
uint32_t adjustedId = m_module.opISub(getVectorTypeId(indexId.type),
|
||||
indexId.id, m_module.consti32(indexRange->start));
|
||||
|
||||
boundsCheck = m_module.opULessThan(
|
||||
m_module.defBoolType(), adjustedId,
|
||||
m_module.constu32(indexRange->length));
|
||||
}
|
||||
|
||||
// Kind of ugly to have an empty else block here but there's no
|
||||
// way for us to know the current block ID for the phi below
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "../spirv/spirv_module.h"
|
||||
@ -136,6 +137,13 @@ namespace dxvk {
|
||||
};
|
||||
|
||||
|
||||
struct DxbcIndexRange {
|
||||
DxbcOperandType type;
|
||||
uint32_t start;
|
||||
uint32_t length;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief Vertex shader-specific structure
|
||||
*/
|
||||
@ -445,6 +453,10 @@ namespace dxvk {
|
||||
// xfb output registers for geometry shaders
|
||||
std::vector<DxbcXfbVar> m_xfbVars;
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// Dynamically indexed input and output regs
|
||||
std::vector<DxbcIndexRange> m_indexRanges = { };
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
// Shader resource variables. These provide access to
|
||||
// constant buffers, samplers, textures, and UAVs.
|
||||
@ -546,6 +558,9 @@ namespace dxvk {
|
||||
void emitDclGlobalFlags(
|
||||
const DxbcShaderInstruction& ins);
|
||||
|
||||
void emitDclIndexRange(
|
||||
const DxbcShaderInstruction& ins);
|
||||
|
||||
void emitDclTemps(
|
||||
const DxbcShaderInstruction& ins);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user