diff --git a/core/libs/tests/ImageSampleGather.cpp b/core/libs/tests/ImageSampleGather.cpp index 95d335262..6fa633e3a 100644 --- a/core/libs/tests/ImageSampleGather.cpp +++ b/core/libs/tests/ImageSampleGather.cpp @@ -28,6 +28,30 @@ static void CheckPck(std::uint32_t encoding, RdnaOpcode opcode, std::uint32_t dm Require(instruction.dataDwordCount == dataComponents); Require(IsImageOpcode(instruction.op)); } +static void CheckSamplerVccTuple() { + const std::array code{0xf0800f08u, 26u << 21u}; + const RdnaInstruction instruction = DecodeRdnaMimg(0u, code, 0u); + Require(instruction.op == RdnaOpcode::ImageSample); + Require(instruction.source1.reg == 0u); + Require(instruction.source2.kind == RdnaOperandKind::ScalarRegister && instruction.source2.reg == 104u); + IrProgram program; + auto& block = program.CreateBlock(); + program.SetEntryBlock(block); + TranslationContext context(program, block, 256); + context.TranslateInstruction(instruction); + Require(program.Resources().memoryInfo.size() == 1u); + Require(program.Resources().memoryInfo.back().sampler == 26u); +} +static void CheckSamplerVccTupleOverflow() { + const std::array code{0xf0800f08u, 27u << 21u}; + bool rejected = false; + try { + DecodeRdnaMimg(0u, code, 0u); + } catch (const std::runtime_error&) { + rejected = true; + } + Require(rejected); +} static void CheckPckRejectsZeroMask(std::uint32_t encoding) { const std::array code{(0x3cu << 26u) | (encoding << 18u) | (1u << 3u), 0u}; bool rejected = false; @@ -49,6 +73,8 @@ static void CheckUnsupportedOpcodeDiagnostic(std::uint32_t encoding, std::string Require(false); } int main() { + CheckSamplerVccTuple(); + CheckSamplerVccTupleOverflow(); Check(0x26u, RdnaOpcode::ImageSampleBCl, 0xfu); Check(0x36u, RdnaOpcode::ImageSampleBClO, 0xfu); Check(0x35u, RdnaOpcode::ImageSampleBO, 0xfu); diff --git a/core/shader/recompiler/RdnaDecoder/src/RdnaImageOpDecoder.cpp b/core/shader/recompiler/RdnaDecoder/src/RdnaImageOpDecoder.cpp index 0ab4c4645..f64c3c6bd 100644 --- a/core/shader/recompiler/RdnaDecoder/src/RdnaImageOpDecoder.cpp +++ b/core/shader/recompiler/RdnaDecoder/src/RdnaImageOpDecoder.cpp @@ -417,7 +417,7 @@ RdnaInstruction DecodeRdnaMimg(std::uint32_t programCounter, std::span> 16u) & 31u) * 4u; const auto sampler = ((word1 >> 21u) & 31u) * 4u; const bool r128 = (word0 & 0x8000u) != 0u; - if (resource + (r128 ? 4u : 8u) > 106u || ((info.sample || info.gather || opcode == 0x60u) && sampler + 4u > 106u)) { + if (resource + (r128 ? 4u : 8u) > 106u || ((info.sample || info.gather || opcode == 0x60u) && sampler > 104u)) { throw std::runtime_error("MIMG descriptor register range overflow"); } RdnaInstruction instruction{};