mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 02:47:02 +02:00
shader: handle disabled RDNA2 traps
This commit is contained in:
@@ -74,7 +74,8 @@ constexpr OpcodeMap SOPP_OPS[] = {
|
|||||||
{0x04u, Opcode::SCbranchScc0}, {0x05u, Opcode::SCbranchScc1}, {0x06u, Opcode::SCbranchVccz},
|
{0x04u, Opcode::SCbranchScc0}, {0x05u, Opcode::SCbranchScc1}, {0x06u, Opcode::SCbranchVccz},
|
||||||
{0x07u, Opcode::SCbranchVccnz}, {0x08u, Opcode::SCbranchExecz}, {0x09u, Opcode::SCbranchExecnz},
|
{0x07u, Opcode::SCbranchVccnz}, {0x08u, Opcode::SCbranchExecz}, {0x09u, Opcode::SCbranchExecnz},
|
||||||
{0x0au, Opcode::SBarrier}, {0x0cu, Opcode::SWaitcnt}, {0x0eu, Opcode::SSleep},
|
{0x0au, Opcode::SBarrier}, {0x0cu, Opcode::SWaitcnt}, {0x0eu, Opcode::SSleep},
|
||||||
{0x10u, Opcode::SSendmsg}, {0x16u, Opcode::STtraceData}, {0x20u, Opcode::SInstPrefetch},
|
{0x10u, Opcode::SSendmsg}, {0x12u, Opcode::STrap}, {0x16u, Opcode::STtraceData},
|
||||||
|
{0x20u, Opcode::SInstPrefetch},
|
||||||
};
|
};
|
||||||
static_assert(Detail::HasUniqueEncodings(SOP1_OPS));
|
static_assert(Detail::HasUniqueEncodings(SOP1_OPS));
|
||||||
static_assert(Detail::HasUniqueEncodings(SOP2_OPS));
|
static_assert(Detail::HasUniqueEncodings(SOP2_OPS));
|
||||||
@@ -257,15 +258,18 @@ bool DecodeSopp(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index
|
|||||||
inst.opcode_id = opcode;
|
inst.opcode_id = opcode;
|
||||||
inst.opcode = Detail::LookupOpcode(SOPP_OPS, opcode);
|
inst.opcode = Detail::LookupOpcode(SOPP_OPS, opcode);
|
||||||
inst.src0.kind = OperandKind::LiteralConstant;
|
inst.src0.kind = OperandKind::LiteralConstant;
|
||||||
inst.src0.value = simm;
|
inst.src0.value = inst.opcode == Opcode::STrap ? simm & 0xffu : simm;
|
||||||
inst.src0.signed_val = static_cast<int16_t>(simm);
|
inst.src0.signed_val = inst.opcode == Opcode::STrap
|
||||||
inst.src_count = (inst.opcode == Opcode::SNop || inst.opcode == Opcode::SWaitcnt ||
|
? static_cast<int32_t>(inst.src0.value)
|
||||||
inst.opcode == Opcode::SSleep || inst.opcode == Opcode::SSendmsg ||
|
: static_cast<int32_t>(static_cast<int16_t>(simm));
|
||||||
inst.opcode == Opcode::STtraceData || inst.opcode == Opcode::SInstPrefetch)
|
inst.src_count = (inst.opcode == Opcode::SNop || inst.opcode == Opcode::SWaitcnt ||
|
||||||
? 1
|
inst.opcode == Opcode::SSleep || inst.opcode == Opcode::SSendmsg ||
|
||||||
: 0;
|
inst.opcode == Opcode::STrap || inst.opcode == Opcode::STtraceData ||
|
||||||
inst.branch_offset = static_cast<int32_t>(static_cast<int16_t>(simm)) * 4;
|
inst.opcode == Opcode::SInstPrefetch)
|
||||||
inst.branch_target = pc + 4u + static_cast<uint32_t>(inst.branch_offset);
|
? 1
|
||||||
|
: 0;
|
||||||
|
inst.branch_offset = static_cast<int32_t>(static_cast<int16_t>(simm)) * 4;
|
||||||
|
inst.branch_target = pc + 4u + static_cast<uint32_t>(inst.branch_offset);
|
||||||
SetRawWords(inst, code, word_index, 1);
|
SetRawWords(inst, code, word_index, 1);
|
||||||
|
|
||||||
if (inst.opcode == Opcode::Unsupported) {
|
if (inst.opcode == Opcode::Unsupported) {
|
||||||
|
|||||||
@@ -937,6 +937,7 @@ std::string OpcodeToString(Opcode opcode) {
|
|||||||
case Opcode::SSendmsg: return "s_sendmsg";
|
case Opcode::SSendmsg: return "s_sendmsg";
|
||||||
case Opcode::SSetregB32: return "s_setreg_b32";
|
case Opcode::SSetregB32: return "s_setreg_b32";
|
||||||
case Opcode::SSleep: return "s_sleep";
|
case Opcode::SSleep: return "s_sleep";
|
||||||
|
case Opcode::STrap: return "s_trap";
|
||||||
case Opcode::STtraceData: return "s_ttracedata";
|
case Opcode::STtraceData: return "s_ttracedata";
|
||||||
case Opcode::SInstPrefetch: return "s_inst_prefetch";
|
case Opcode::SInstPrefetch: return "s_inst_prefetch";
|
||||||
case Opcode::SEndpgm: return "s_endpgm";
|
case Opcode::SEndpgm: return "s_endpgm";
|
||||||
@@ -1039,6 +1040,7 @@ std::string InstructionToString(const Instruction& inst) {
|
|||||||
case Opcode::SNop:
|
case Opcode::SNop:
|
||||||
case Opcode::SWaitcnt:
|
case Opcode::SWaitcnt:
|
||||||
case Opcode::SSleep:
|
case Opcode::SSleep:
|
||||||
|
case Opcode::STrap:
|
||||||
case Opcode::SSendmsg:
|
case Opcode::SSendmsg:
|
||||||
case Opcode::STtraceData:
|
case Opcode::STtraceData:
|
||||||
case Opcode::SInstPrefetch:
|
case Opcode::SInstPrefetch:
|
||||||
|
|||||||
@@ -537,6 +537,7 @@ enum class Opcode {
|
|||||||
SSendmsg,
|
SSendmsg,
|
||||||
SSetregB32,
|
SSetregB32,
|
||||||
SSleep,
|
SSleep,
|
||||||
|
STrap,
|
||||||
STtraceData,
|
STtraceData,
|
||||||
SInstPrefetch,
|
SInstPrefetch,
|
||||||
SEndpgm,
|
SEndpgm,
|
||||||
|
|||||||
@@ -1000,6 +1000,9 @@ bool LowerControlInstruction(const Decoder::Instruction& decoded, BasicBlock& bl
|
|||||||
case Decoder::Opcode::SSetregB32:
|
case Decoder::Opcode::SSetregB32:
|
||||||
case Decoder::Opcode::SSleep:
|
case Decoder::Opcode::SSleep:
|
||||||
return LowerControlMarker(decoded, block, Opcode::ControlNop, true, error);
|
return LowerControlMarker(decoded, block, Opcode::ControlNop, true, error);
|
||||||
|
case Decoder::Opcode::STrap:
|
||||||
|
// RDNA2 converts S_TRAP to a NOP when the unmodeled trap state is disabled.
|
||||||
|
return LowerControlMarker(decoded, block, Opcode::ControlNop, true, error);
|
||||||
case Decoder::Opcode::STtraceData:
|
case Decoder::Opcode::STtraceData:
|
||||||
return LowerControlMarker(decoded, block, Opcode::TtraceData, true, error);
|
return LowerControlMarker(decoded, block, Opcode::TtraceData, true, error);
|
||||||
case Decoder::Opcode::SInstPrefetch:
|
case Decoder::Opcode::SInstPrefetch:
|
||||||
@@ -1076,6 +1079,7 @@ bool IsControlOpcode(Decoder::Opcode opcode) {
|
|||||||
case Decoder::Opcode::SSendmsg:
|
case Decoder::Opcode::SSendmsg:
|
||||||
case Decoder::Opcode::SSetregB32:
|
case Decoder::Opcode::SSetregB32:
|
||||||
case Decoder::Opcode::SSleep:
|
case Decoder::Opcode::SSleep:
|
||||||
|
case Decoder::Opcode::STrap:
|
||||||
case Decoder::Opcode::STtraceData:
|
case Decoder::Opcode::STtraceData:
|
||||||
case Decoder::Opcode::SInstPrefetch: return true;
|
case Decoder::Opcode::SInstPrefetch: return true;
|
||||||
default: return false;
|
default: return false;
|
||||||
|
|||||||
@@ -35,11 +35,11 @@
|
|||||||
#include "graphics/host_gpu/vulkanCommon.h"
|
#include "graphics/host_gpu/vulkanCommon.h"
|
||||||
#include "graphics/presentation/window/windowInternal.h"
|
#include "graphics/presentation/window/windowInternal.h"
|
||||||
#include "graphics/shader/recompiler/ShaderRecompiler.h"
|
#include "graphics/shader/recompiler/ShaderRecompiler.h"
|
||||||
#include "graphics/shader/recompiler/frontend/decode/ShaderDecoder.h"
|
|
||||||
#include "graphics/shader/recompiler/backend/spirv/SpirvBuilder.h"
|
#include "graphics/shader/recompiler/backend/spirv/SpirvBuilder.h"
|
||||||
#include "graphics/shader/recompiler/backend/spirv/SpirvEmitter.h"
|
#include "graphics/shader/recompiler/backend/spirv/SpirvEmitter.h"
|
||||||
#include "graphics/shader/recompiler/ir/passes/BindingLayout.h"
|
#include "graphics/shader/recompiler/frontend/decode/ShaderDecoder.h"
|
||||||
#include "graphics/shader/recompiler/ir/ValueProgram.h"
|
#include "graphics/shader/recompiler/ir/ValueProgram.h"
|
||||||
|
#include "graphics/shader/recompiler/ir/passes/BindingLayout.h"
|
||||||
#include "graphics/shader/rectListShader.h"
|
#include "graphics/shader/rectListShader.h"
|
||||||
#include "graphics/shader/shader.h"
|
#include "graphics/shader/shader.h"
|
||||||
#include "kernel/memory.h"
|
#include "kernel/memory.h"
|
||||||
@@ -1080,15 +1080,13 @@ CompiledShader CompileCase(const TestCase &test) {
|
|||||||
}
|
}
|
||||||
for (const auto &[text, expected] : test.decoded_counts) {
|
for (const auto &[text, expected] : test.decoded_counts) {
|
||||||
const auto actual = CountText(result.decoded_dump, text);
|
const auto actual = CountText(result.decoded_dump, text);
|
||||||
Require(test.name, "decoded RDNA2",
|
Require(test.name, "decoded RDNA2", actual == expected,
|
||||||
actual == expected,
|
|
||||||
text + " count=" + std::to_string(actual) +
|
text + " count=" + std::to_string(actual) +
|
||||||
", expected=" + std::to_string(expected));
|
", expected=" + std::to_string(expected));
|
||||||
}
|
}
|
||||||
for (const auto &[text, expected] : test.ir_counts) {
|
for (const auto &[text, expected] : test.ir_counts) {
|
||||||
const auto actual = CountText(result.ir_dump, text);
|
const auto actual = CountText(result.ir_dump, text);
|
||||||
Require(test.name, "typed IR",
|
Require(test.name, "typed IR", actual == expected,
|
||||||
actual == expected,
|
|
||||||
text + " count=" + std::to_string(actual) +
|
text + " count=" + std::to_string(actual) +
|
||||||
", expected=" + std::to_string(expected));
|
", expected=" + std::to_string(expected));
|
||||||
}
|
}
|
||||||
@@ -10556,6 +10554,30 @@ TestCase Rdna2ScalarOpcodes() {
|
|||||||
O::VMovB32, O::BufferStoreDword, O::SEndpgm}};
|
O::VMovB32, O::BufferStoreDword, O::SEndpgm}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TestCase ScalarTrapDisabledFallsThroughExactRaw() {
|
||||||
|
using O = ShaderOpcode;
|
||||||
|
|
||||||
|
std::vector<u32> code;
|
||||||
|
AppendVMovU32(&code, 0, 7);
|
||||||
|
code.push_back(0xbf920001u); // s_trap 1 from the game shader
|
||||||
|
AppendVMovU32(&code, 0, 42);
|
||||||
|
AppendStoreVgpr(&code, 0, 0);
|
||||||
|
AppendEnd(&code);
|
||||||
|
|
||||||
|
TestCase test;
|
||||||
|
test.name = "ScalarTrapDisabledFallsThroughExactRaw";
|
||||||
|
test.code = code;
|
||||||
|
test.expected = {42};
|
||||||
|
test.opcodes = {O::VMovB32, O::STrap, O::BufferStoreDword, O::SEndpgm};
|
||||||
|
test.decoded_counts = {{"s_trap 0x00000001", 1}};
|
||||||
|
test.compute_info.threads_num[0] = 1;
|
||||||
|
test.compute_info.threads_num[1] = 1;
|
||||||
|
test.compute_info.threads_num[2] = 1;
|
||||||
|
test.compute_info.wave_size = 32;
|
||||||
|
test.has_compute_info = true;
|
||||||
|
return test;
|
||||||
|
}
|
||||||
|
|
||||||
TestCase ScalarExtendedArithmetic() {
|
TestCase ScalarExtendedArithmetic() {
|
||||||
using O = ShaderOpcode;
|
using O = ShaderOpcode;
|
||||||
|
|
||||||
@@ -11721,9 +11743,9 @@ TestCase VectorSubrevCoCiU32ExactRawOnGpu() {
|
|||||||
test.name = "VectorSubrevCoCiU32ExactRawOnGpu";
|
test.name = "VectorSubrevCoCiU32ExactRawOnGpu";
|
||||||
test.code = code;
|
test.code = code;
|
||||||
test.expected = {0xdeadbeefu, 0, 2, 3, 0, 0, 0, 0};
|
test.expected = {0xdeadbeefu, 0, 2, 3, 0, 0, 0, 0};
|
||||||
test.opcodes = {O::VMovB32, O::VLshlrevB32, O::VAddNcU32,
|
test.opcodes = {O::VMovB32, O::VLshlrevB32, O::VAddNcU32,
|
||||||
O::VCmpLtU32, O::SMovB64, O::VCmpNeU32,
|
O::VCmpLtU32, O::SMovB64, O::VCmpNeU32,
|
||||||
O::VSubrevCoCiU32, O::VCndmaskB32, O::BufferStoreDword,
|
O::VSubrevCoCiU32, O::VCndmaskB32, O::BufferStoreDword,
|
||||||
O::SEndpgm};
|
O::SEndpgm};
|
||||||
test.required_spirv = {"OpISub", "OpUGreaterThan"};
|
test.required_spirv = {"OpISub", "OpUGreaterThan"};
|
||||||
test.compute_info.threads_num[0] = 4;
|
test.compute_info.threads_num[0] = 4;
|
||||||
@@ -16851,6 +16873,7 @@ std::vector<TestCase> MakeCases() {
|
|||||||
AddCase(ExactPushConstantExtent);
|
AddCase(ExactPushConstantExtent);
|
||||||
AddCase(ScalarShiftCountsMaskLowBits);
|
AddCase(ScalarShiftCountsMaskLowBits);
|
||||||
AddCase(Rdna2ScalarOpcodes);
|
AddCase(Rdna2ScalarOpcodes);
|
||||||
|
AddCase(ScalarTrapDisabledFallsThroughExactRaw);
|
||||||
AddCase(ScalarExtendedArithmetic);
|
AddCase(ScalarExtendedArithmetic);
|
||||||
AddCase(ScalarArithmeticSccCarryBorrowOverflow);
|
AddCase(ScalarArithmeticSccCarryBorrowOverflow);
|
||||||
AddCase(ScalarMinMaxSccComparisonEdges);
|
AddCase(ScalarMinMaxSccComparisonEdges);
|
||||||
|
|||||||
Reference in New Issue
Block a user