Improve shader recompiler

This commit is contained in:
InoriRus 2021-12-06 15:45:28 +10:00
parent 43f49c8763
commit 0242926a7c
5 changed files with 1417 additions and 928 deletions

View file

@ -75,7 +75,7 @@ if (CLANG AND (KYTY_LINKER STREQUAL LLD))
set(KYTY_LD_OPTIONS "-fuse-ld=lld")
endif()
project(Kyty${KYTY_PROJECT_NAME}${CMAKE_BUILD_TYPE}${KYTY_COMPILER} VERSION 0.0.1)
project(Kyty${KYTY_PROJECT_NAME}${CMAKE_BUILD_TYPE}${KYTY_COMPILER} VERSION 0.0.2)
include(src_script.cmake)

View file

@ -7,6 +7,8 @@
#include "Emulator/Common.h"
#include <algorithm>
#ifdef KYTY_EMU_ENABLED
namespace Kyty::Libs::Graphics {
@ -27,9 +29,6 @@ enum class ShaderType
enum class ShaderInstructionType
{
Unknown,
DsAppend,
DsConsume,
Exp,
BufferLoadDword,
BufferLoadFormatX,
BufferLoadFormatXy,
@ -37,50 +36,78 @@ enum class ShaderInstructionType
BufferLoadFormatXyzw,
BufferStoreDword,
BufferStoreFormatX,
DsAppend,
DsConsume,
Exp,
ImageSample,
TBufferLoadFormatXyzw,
SAddI32,
SAndB32,
SAndn2B64,
SAndSaveexecB64,
SEndpgm,
SCbranchExecz,
SLshlB32,
SLoadDwordx4,
SLoadDwordx8,
SBufferLoadDword,
SBufferLoadDwordx16,
SBufferLoadDwordx2,
SBufferLoadDwordx4,
SBufferLoadDwordx8,
SBufferLoadDwordx16,
SCbranchExecz,
SCbranchScc0,
SCmpEqU32,
SEndpgm,
SLoadDwordx4,
SLoadDwordx8,
SLshlB32,
SLshrB32,
SMovB32,
SMovB64,
SMulI32,
SNorB64,
SOrB64,
SCselectB32,
SSetpcB64,
SSwappcB64,
SWaitcnt,
SWqmB64,
TBufferLoadFormatXyzw,
VAddI32,
VAndB32,
VAshrrevI32,
VBfeU32,
VCmpEqF32,
VCmpEqU32,
VCmpGtI32,
VCmpLeF32,
VCmpLeU32,
VCmpNeU32,
VCmpNeqF32,
VCmpNeU32,
VCmpxEqU32,
VCmpxGtU32,
VCmpxNeU32,
VCndmaskB32,
VCvtF32U32,
VCvtF32Ubyte0,
VCvtF32Ubyte1,
VCvtF32Ubyte2,
VCvtF32Ubyte3,
VCvtPkrtzF16F32,
VCvtU32F32,
VInterpP1F32,
VInterpP2F32,
VLshlrevB32,
VLshrB32,
VLshrrevB32,
VMacF32,
VMadakF32,
VMadF32,
VMadU32U24,
VMaxF32,
VMbcntHiU32B32,
VMbcntLoU32B32,
VMinF32,
VMovB32,
VMulF32,
VInterpP1F32,
VInterpP2F32,
VMulLoI32,
VMulU32U24,
VNotB32,
VRcpF32,
VRsqF32,
VSadU32,
@ -123,6 +150,7 @@ enum FormatByte : uint64_t
S2A4, // operand_array_to_str(inst.src[2], 4)
Attr, // attr%u.%u <- inst.src[1].constant.u, inst.src[2].constant.u
Idxen, // idxen
Offen, // offen
Float4, // format:float4
Pos0, // pos0
Done, // done
@ -131,6 +159,7 @@ enum FormatByte : uint64_t
Param2, // param2
Param3, // param3
Mrt0, // mrt_color0
Off, // off
Compr, // compr
Vm, // vm
L, // label_%u
@ -151,41 +180,46 @@ constexpr uint64_t FormatDefine(std::initializer_list<uint64_t> f)
enum Format : uint64_t
{
Unknown = FormatDefine({U}),
Empty = FormatDefine({N}),
Imm = FormatDefine({S0}),
Label = FormatDefine({L}),
Mrt0Vsrc0Vsrc1ComprVmDone = FormatDefine({Mrt0, S0, S1, Compr, Vm, Done}),
Mrt0Vsrc0Vsrc1Vsrc2Vsrc3VmDone = FormatDefine({Mrt0, S0, S1, S2, S3, Vm, Done}),
Param0Vsrc0Vsrc1Vsrc2Vsrc3 = FormatDefine({Param0, S0, S1, S2, S3}),
Param1Vsrc0Vsrc1Vsrc2Vsrc3 = FormatDefine({Param1, S0, S1, S2, S3}),
Param2Vsrc0Vsrc1Vsrc2Vsrc3 = FormatDefine({Param2, S0, S1, S2, S3}),
Param3Vsrc0Vsrc1Vsrc2Vsrc3 = FormatDefine({Param3, S0, S1, S2, S3}),
Pos0Vsrc0Vsrc1Vsrc2Vsrc3Done = FormatDefine({Pos0, S0, S1, S2, S3, Done}),
Saddr = FormatDefine({S0A2}),
Sdst4SbaseSoffset = FormatDefine({DA4, S0A2, S1}),
Sdst8SbaseSoffset = FormatDefine({DA8, S0A2, S1}),
SdstSvSoffset = FormatDefine({D, S0A4, S1}),
Sdst4SvSoffset = FormatDefine({DA4, S0A4, S1}),
Sdst8SvSoffset = FormatDefine({DA8, S0A4, S1}),
Sdst16SvSoffset = FormatDefine({DA16, S0A4, S1}),
SVdstSVsrc0 = FormatDefine({D, S0}),
SVdstSVsrc0SVsrc1 = FormatDefine({D, S0, S1}),
Sdst2Ssrc02 = FormatDefine({DA2, S0A2}),
Sdst2Ssrc02Ssrc12 = FormatDefine({DA2, S0A2, S1A2}),
SmaskVsrc0Vsrc1 = FormatDefine({DA2, S0, S1}),
Vdata1VaddrSvSoffsIdxen = FormatDefine({D, S0, S1A4, S2, Idxen}),
Vdata2VaddrSvSoffsIdxen = FormatDefine({DA2, S0, S1A4, S2, Idxen}),
Vdata3VaddrSvSoffsIdxen = FormatDefine({DA3, S0, S1A4, S2, Idxen}),
Vdata4VaddrSvSoffsIdxen = FormatDefine({DA4, S0, S1A4, S2, Idxen}),
Vdata4VaddrSvSoffsIdxenFloat4 = FormatDefine({DA4, S0, S1A4, S2, Idxen, Float4}),
Vdata3Vaddr3StSsDmask7 = FormatDefine({DA3, S0A3, S1A8, S2A4, Dmask7}),
Vdata4Vaddr3StSsDmaskF = FormatDefine({DA4, S0A3, S1A8, S2A4, DmaskF}),
VdstVsrc0Vsrc1Smask2 = FormatDefine({D, S0, S1, S2A2}),
VdstVsrc0Vsrc1Vsrc2 = FormatDefine({D, S0, S1, S2}),
VdstVsrcAttrChan = FormatDefine({D, S0, Attr}),
VdstSdst2Vsrc0Vsrc1 = FormatDefine({D, D2A2, S0, S1}),
VdstGds = FormatDefine({D, Gds})
Unknown = FormatDefine({U}),
Empty = FormatDefine({N}),
Imm = FormatDefine({S0}),
Label = FormatDefine({L}),
Mrt0OffOffComprVmDone = FormatDefine({Mrt0, Off, Off, Compr, Vm, Done}),
Mrt0Vsrc0Vsrc1ComprVmDone = FormatDefine({Mrt0, S0, S1, Compr, Vm, Done}),
Mrt0Vsrc0Vsrc1Vsrc2Vsrc3VmDone = FormatDefine({Mrt0, S0, S1, S2, S3, Vm, Done}),
Param0Vsrc0Vsrc1Vsrc2Vsrc3 = FormatDefine({Param0, S0, S1, S2, S3}),
Param1Vsrc0Vsrc1Vsrc2Vsrc3 = FormatDefine({Param1, S0, S1, S2, S3}),
Param2Vsrc0Vsrc1Vsrc2Vsrc3 = FormatDefine({Param2, S0, S1, S2, S3}),
Param3Vsrc0Vsrc1Vsrc2Vsrc3 = FormatDefine({Param3, S0, S1, S2, S3}),
Pos0Vsrc0Vsrc1Vsrc2Vsrc3Done = FormatDefine({Pos0, S0, S1, S2, S3, Done}),
Saddr = FormatDefine({S0A2}),
Sdst4SbaseSoffset = FormatDefine({DA4, S0A2, S1}),
Sdst8SbaseSoffset = FormatDefine({DA8, S0A2, S1}),
SdstSvSoffset = FormatDefine({D, S0A4, S1}),
Sdst2SvSoffset = FormatDefine({DA2, S0A4, S1}),
Sdst4SvSoffset = FormatDefine({DA4, S0A4, S1}),
Sdst8SvSoffset = FormatDefine({DA8, S0A4, S1}),
Sdst16SvSoffset = FormatDefine({DA16, S0A4, S1}),
SVdstSVsrc0 = FormatDefine({D, S0}),
SVdstSVsrc0SVsrc1 = FormatDefine({D, S0, S1}),
Sdst2Ssrc02 = FormatDefine({DA2, S0A2}),
Sdst2Ssrc0 = FormatDefine({DA2, S0}),
Sdst2Ssrc02Ssrc12 = FormatDefine({DA2, S0A2, S1A2}),
SmaskVsrc0Vsrc1 = FormatDefine({DA2, S0, S1}),
Ssrc0Ssrc1 = FormatDefine({S0, S1}),
Vdata1VaddrSvSoffsIdxen = FormatDefine({D, S0, S1A4, S2, Idxen}),
Vdata2VaddrSvSoffsIdxen = FormatDefine({DA2, S0, S1A4, S2, Idxen}),
Vdata3VaddrSvSoffsIdxen = FormatDefine({DA3, S0, S1A4, S2, Idxen}),
Vdata4VaddrSvSoffsIdxen = FormatDefine({DA4, S0, S1A4, S2, Idxen}),
Vdata4VaddrSvSoffsIdxenFloat4 = FormatDefine({DA4, S0, S1A4, S2, Idxen, Float4}),
Vdata4Vaddr2SvSoffsOffenIdxenFloat4 = FormatDefine({DA4, S0A2, S1A4, S2, Offen, Idxen, Float4}),
Vdata3Vaddr3StSsDmask7 = FormatDefine({DA3, S0A3, S1A8, S2A4, Dmask7}),
Vdata4Vaddr3StSsDmaskF = FormatDefine({DA4, S0A3, S1A8, S2A4, DmaskF}),
VdstVsrc0Vsrc1Smask2 = FormatDefine({D, S0, S1, S2A2}),
VdstVsrc0Vsrc1Vsrc2 = FormatDefine({D, S0, S1, S2}),
VdstVsrcAttrChan = FormatDefine({D, S0, Attr}),
VdstSdst2Vsrc0Vsrc1 = FormatDefine({D, D2A2, S0, S1}),
VdstGds = FormatDefine({D, Gds}),
};
} // namespace ShaderInstructionFormat
@ -201,6 +235,7 @@ enum class ShaderOperandType
ExecLo,
ExecHi,
ExecZ,
Scc,
Vgpr,
Sgpr,
M0
@ -240,6 +275,12 @@ struct ShaderInstruction
ShaderOperand dst2;
};
struct ShaderLabel
{
uint32_t dst;
uint32_t src;
};
class ShaderCode
{
public:
@ -249,8 +290,8 @@ public:
[[nodiscard]] const Vector<ShaderInstruction>& GetInstructions() const { return m_instructions; }
Vector<ShaderInstruction>& GetInstructions() { return m_instructions; }
[[nodiscard]] const Vector<uint32_t>& GetLabels() const { return m_labels; }
Vector<uint32_t>& GetLabels() { return m_labels; }
[[nodiscard]] const Vector<ShaderLabel>& GetLabels() const { return m_labels; }
Vector<ShaderLabel>& GetLabels() { return m_labels; }
[[nodiscard]] String DbgDump() const;
@ -259,9 +300,16 @@ public:
[[nodiscard]] ShaderType GetType() const { return m_type; }
void SetType(ShaderType type) { this->m_type = type; }
[[nodiscard]] bool HasAnyOf(std::initializer_list<ShaderInstructionType> types) const
{
return std::any_of(types.begin(), types.end(),
[this](auto type)
{ return m_instructions.Contains(type, [](auto inst, auto type) { return inst.type == type; }); });
}
private:
Vector<ShaderInstruction> m_instructions;
Vector<uint32_t> m_labels;
Vector<ShaderLabel> m_labels;
ShaderType m_type = ShaderType::Unknown;
};

View file

@ -2616,7 +2616,7 @@ static void FindRenderDepthInfo(const HardwareContext& hw, RenderDepthInfo* r)
TileGetDepthSize(z.width, z.height, z.z_info.format, z.stencil_info.format, htile, neo, &stencil_size, &htile_size, &depth_size,
&pitch);
EXIT_NOT_IMPLEMENTED((z.pitch_div8_minus1 + 1) * 8 != pitch);
EXIT_NOT_IMPLEMENTED(pitch != 0 && (z.pitch_div8_minus1 + 1) * 8 != pitch);
switch (z.z_info.format * 2 + z.stencil_info.format)
{

View file

@ -24,7 +24,8 @@
#ifdef KYTY_EMU_ENABLED
#define KYTY_SHADER_PARSER_ARGS \
[[maybe_unused]] uint32_t pc, const uint32_t *src, [[maybe_unused]] const uint32_t *buffer, [[maybe_unused]] ShaderCode *dst
[[maybe_unused]] uint32_t pc, [[maybe_unused]] const uint32_t *src, [[maybe_unused]] const uint32_t *buffer, \
[[maybe_unused]] ShaderCode *dst
#define KYTY_SHADER_PARSER(f) static uint32_t f(KYTY_SHADER_PARSER_ARGS)
#define KYTY_CP_OP_PARSER_ARGS \
[[maybe_unused]] CommandProcessor *cp, [[maybe_unused]] uint32_t cmd_id, [[maybe_unused]] const uint32_t *buffer, \
@ -103,6 +104,7 @@ static String operand_to_str(ShaderOperand op)
case ShaderOperandType::ExecHi: ret = U"exec_hi"; break;
case ShaderOperandType::ExecLo: ret = U"exec_lo"; break;
case ShaderOperandType::ExecZ: ret = U"execz"; break;
case ShaderOperandType::Scc: ret = U"scc"; break;
case ShaderOperandType::M0: ret = U"m0"; break;
case ShaderOperandType::Vgpr: ret = String::FromPrintf("v%d", op.register_id); break;
case ShaderOperandType::Sgpr: ret = String::FromPrintf("s%d", op.register_id); break;
@ -142,6 +144,8 @@ static String operand_array_to_str(ShaderOperand op, int n)
default: break;
}
EXIT_IF(ret == U"???");
if (op.negate)
{
return U"-" + ret;
@ -157,6 +161,7 @@ static String dbg_fmt_to_str(const ShaderInstruction& inst)
case ShaderInstructionFormat::Unknown: return U"Unknown"; break;
case ShaderInstructionFormat::Empty: return U"Empty"; break;
case ShaderInstructionFormat::Imm: return U"Imm"; break;
case ShaderInstructionFormat::Mrt0OffOffComprVmDone: return U"Mrt0OffOffComprVmDone"; break;
case ShaderInstructionFormat::Mrt0Vsrc0Vsrc1ComprVmDone: return U"Mrt0Vsrc0Vsrc1ComprVmDone"; break;
case ShaderInstructionFormat::Mrt0Vsrc0Vsrc1Vsrc2Vsrc3VmDone: return U"Mrt0Vsrc0Vsrc1Vsrc2Vsrc3VmDone"; break;
case ShaderInstructionFormat::Param0Vsrc0Vsrc1Vsrc2Vsrc3: return U"Param0Vsrc0Vsrc1Vsrc2Vsrc3"; break;
@ -168,18 +173,22 @@ static String dbg_fmt_to_str(const ShaderInstruction& inst)
case ShaderInstructionFormat::Sdst4SbaseSoffset: return U"Sdst4SbaseSoffset"; break;
case ShaderInstructionFormat::Sdst8SbaseSoffset: return U"Sdst8SbaseSoffset"; break;
case ShaderInstructionFormat::SdstSvSoffset: return U"SdstSvSoffset"; break;
case ShaderInstructionFormat::Sdst2SvSoffset: return U"Sdst2SvSoffset"; break;
case ShaderInstructionFormat::Sdst4SvSoffset: return U"Sdst4SvSoffset"; break;
case ShaderInstructionFormat::Sdst8SvSoffset: return U"Sdst8SvSoffset"; break;
case ShaderInstructionFormat::Sdst16SvSoffset: return U"Sdst16SvSoffset"; break;
case ShaderInstructionFormat::SVdstSVsrc0: return U"SVdstSVsrc0"; break;
case ShaderInstructionFormat::Sdst2Ssrc02: return U"Sdst2Ssrc02"; break;
case ShaderInstructionFormat::Sdst2Ssrc0: return U"Sdst2Ssrc0"; break;
case ShaderInstructionFormat::Sdst2Ssrc02Ssrc12: return U"Sdst2Ssrc02Ssrc12"; break;
case ShaderInstructionFormat::SmaskVsrc0Vsrc1: return U"SmaskVsrc0Vsrc1"; break;
case ShaderInstructionFormat::Ssrc0Ssrc1: return U"Ssrc0Ssrc1"; break;
case ShaderInstructionFormat::Vdata1VaddrSvSoffsIdxen: return U"Vdata1VaddrSvSoffsIdxen"; break;
case ShaderInstructionFormat::Vdata2VaddrSvSoffsIdxen: return U"Vdata2VaddrSvSoffsIdxen"; break;
case ShaderInstructionFormat::Vdata3VaddrSvSoffsIdxen: return U"Vdata3VaddrSvSoffsIdxen"; break;
case ShaderInstructionFormat::Vdata4VaddrSvSoffsIdxen: return U"Vdata4VaddrSvSoffsIdxen"; break;
case ShaderInstructionFormat::Vdata4VaddrSvSoffsIdxenFloat4: return U"Vdata4VaddrSvSoffsIdxenFloat4"; break;
case ShaderInstructionFormat::Vdata4Vaddr2SvSoffsOffenIdxenFloat4: return U"Vdata4Vaddr2SvSoffsOffenIdxenFloat4"; break;
case ShaderInstructionFormat::Vdata3Vaddr3StSsDmask7: return U"Vdata4Vaddr3StSsDmask7"; break;
case ShaderInstructionFormat::Vdata4Vaddr3StSsDmaskF: return U"Vdata4Vaddr3StSsDmaskF"; break;
case ShaderInstructionFormat::SVdstSVsrc0SVsrc1: return U"SVdstSVsrc0SVsrc1"; break;
@ -202,6 +211,7 @@ static String dbg_fmt_print(const ShaderInstruction& inst)
{
return str;
}
int src_num = 0;
for (;;)
{
String s;
@ -238,6 +248,7 @@ static String dbg_fmt_print(const ShaderInstruction& inst)
case ShaderInstructionFormat::S2A4: s = operand_array_to_str(inst.src[2], 4); break;
case ShaderInstructionFormat::Attr: s = String::FromPrintf("attr%u.%u", inst.src[1].constant.u, inst.src[2].constant.u); break;
case ShaderInstructionFormat::Idxen: s = U"idxen"; break;
case ShaderInstructionFormat::Offen: s = U"offen"; break;
case ShaderInstructionFormat::Float4: s = U"format:float4"; break;
case ShaderInstructionFormat::Pos0: s = U"pos0"; break;
case ShaderInstructionFormat::Done: s = U"done"; break;
@ -246,6 +257,7 @@ static String dbg_fmt_print(const ShaderInstruction& inst)
case ShaderInstructionFormat::Param2: s = U"param2"; break;
case ShaderInstructionFormat::Param3: s = U"param3"; break;
case ShaderInstructionFormat::Mrt0: s = U"mrt_color0"; break;
case ShaderInstructionFormat::Off: s = U"off"; break;
case ShaderInstructionFormat::Compr: s = U"compr"; break;
case ShaderInstructionFormat::Vm: s = U"vm"; break;
case ShaderInstructionFormat::L: s = String::FromPrintf("label_%04" PRIx32, inst.pc + 4 + inst.src[0].constant.i); break;
@ -254,9 +266,30 @@ static String dbg_fmt_print(const ShaderInstruction& inst)
case ShaderInstructionFormat::Gds: s = U"gds"; break;
default: EXIT("unknown code: %u\n", static_cast<uint32_t>(fu));
}
switch (fu)
{
case ShaderInstructionFormat::L:
case ShaderInstructionFormat::S0:
case ShaderInstructionFormat::S0A2:
case ShaderInstructionFormat::S0A3:
case ShaderInstructionFormat::S0A4: src_num = std::max(src_num, 1); break;
case ShaderInstructionFormat::S1:
case ShaderInstructionFormat::S1A2:
case ShaderInstructionFormat::S1A3:
case ShaderInstructionFormat::S1A4:
case ShaderInstructionFormat::S1A8: src_num = std::max(src_num, 2); break;
case ShaderInstructionFormat::S2:
case ShaderInstructionFormat::S2A2:
case ShaderInstructionFormat::S2A3:
case ShaderInstructionFormat::S2A4:
case ShaderInstructionFormat::Attr: src_num = std::max(src_num, 3); break;
case ShaderInstructionFormat::S3: src_num = std::max(src_num, 4); break;
default: break;
}
str = s + (str.IsEmpty() ? U"" : U", " + str);
f >>= 8u;
}
EXIT_IF(src_num != inst.src_num);
if (inst.dst.multiplier == 2.0f)
{
str += " mul:2";
@ -294,7 +327,7 @@ String ShaderCode::DbgDump() const
String ret;
for (const auto& inst: m_instructions)
{
if (m_labels.Contains(inst.pc))
if (m_labels.Contains(inst.pc, [](auto label, auto pc) { return label.dst == pc; }))
{
ret += String::FromPrintf("label_%04" PRIx32 ":\n", inst.pc);
}
@ -363,6 +396,108 @@ static ShaderOperand operand_parse(uint32_t code)
return ret;
}
KYTY_SHADER_PARSER(shader_parse_sopc)
{
EXIT_IF(dst == nullptr);
EXIT_IF(src == nullptr);
EXIT_IF(buffer == nullptr || buffer < src);
uint32_t ssrc1 = (buffer[0] >> 8u) & 0xffu;
uint32_t ssrc0 = (buffer[0] >> 0u) & 0xffu;
uint32_t opcode = (buffer[0] >> 16u) & 0x7fu;
ShaderInstruction inst;
inst.pc = pc;
inst.src[0] = operand_parse(ssrc0);
inst.src[1] = operand_parse(ssrc1);
inst.src_num = 2;
uint32_t size = 1;
if (inst.src[0].type == ShaderOperandType::LiteralConstant)
{
inst.src[0].constant.u = buffer[size];
size++;
}
if (inst.src[1].type == ShaderOperandType::LiteralConstant)
{
inst.src[1].constant.u = buffer[size];
size++;
}
inst.format = ShaderInstructionFormat::Ssrc0Ssrc1;
switch (opcode) // NOLINT
{
case 0x06: inst.type = ShaderInstructionType::SCmpEqU32; break;
default: printf("%s", dst->DbgDump().C_Str()); EXIT("unknown sopc opcode: 0x%02" PRIx32 " at addr 0x%08" PRIx32 "\n", opcode, pc);
}
dst->GetInstructions().Add(inst);
return size;
}
KYTY_SHADER_PARSER(shader_parse_sopk)
{
KYTY_NOT_IMPLEMENTED;
return 1;
}
KYTY_SHADER_PARSER(shader_parse_sopp)
{
EXIT_IF(dst == nullptr);
EXIT_IF(src == nullptr);
EXIT_IF(buffer == nullptr || buffer < src);
uint32_t opcode = (buffer[0] >> 16u) & 0x7fu;
uint32_t simm = (buffer[0] >> 0u) & 0xffffu;
ShaderInstruction inst;
inst.pc = pc;
switch (opcode)
{
case 0x01:
inst.type = ShaderInstructionType::SEndpgm;
inst.format = ShaderInstructionFormat::Empty;
break;
case 0x04:
inst.type = ShaderInstructionType::SCbranchScc0;
inst.format = ShaderInstructionFormat::Label;
inst.src[0].type = ShaderOperandType::LiteralConstant;
inst.src[0].constant.i = static_cast<int16_t>(simm) * 4;
inst.src_num = 1;
break;
case 0x08:
inst.type = ShaderInstructionType::SCbranchExecz;
inst.format = ShaderInstructionFormat::Label;
inst.src[0].type = ShaderOperandType::LiteralConstant;
inst.src[0].constant.i = static_cast<int16_t>(simm) * 4;
inst.src_num = 1;
break;
case 0x0c:
inst.type = ShaderInstructionType::SWaitcnt;
inst.format = ShaderInstructionFormat::Imm;
inst.src[0].type = ShaderOperandType::LiteralConstant;
inst.src[0].constant.u = simm;
inst.src_num = 1;
break;
default: printf("%s", dst->DbgDump().C_Str()); EXIT("unknown sopp opcode: 0x%02" PRIx32 " at addr 0x%08" PRIx32 "\n", opcode, pc);
}
dst->GetInstructions().Add(inst);
if (inst.type == ShaderInstructionType::SCbranchScc0 || inst.type == ShaderInstructionType::SCbranchExecz)
{
dst->GetLabels().Add({inst.pc + 4 + inst.src[0].constant.i, inst.pc});
}
return 1;
}
KYTY_SHADER_PARSER(shader_parse_sop1)
{
EXIT_IF(dst == nullptr);
@ -394,10 +529,19 @@ KYTY_SHADER_PARSER(shader_parse_sop1)
inst.format = ShaderInstructionFormat::SVdstSVsrc0;
break;
case 0x04:
inst.type = ShaderInstructionType::SMovB64;
inst.format = ShaderInstructionFormat::Sdst2Ssrc02;
inst.dst.size = 2;
inst.src[0].size = 2;
inst.type = ShaderInstructionType::SMovB64;
inst.dst.size = 2;
switch (inst.src[0].type)
{
case ShaderOperandType::VccLo:
case ShaderOperandType::ExecLo:
case ShaderOperandType::Sgpr:
inst.format = ShaderInstructionFormat::Sdst2Ssrc02;
inst.src[0].size = 2;
break;
case ShaderOperandType::IntegerInlineConstant: inst.format = ShaderInstructionFormat::Sdst2Ssrc0; break;
default: EXIT("unknown src0 type");
}
break;
case 0x0a:
inst.type = ShaderInstructionType::SWqmB64;
@ -430,51 +574,6 @@ KYTY_SHADER_PARSER(shader_parse_sop1)
return size;
}
KYTY_SHADER_PARSER(shader_parse_sopp)
{
EXIT_IF(dst == nullptr);
EXIT_IF(src == nullptr);
EXIT_IF(buffer == nullptr || buffer < src);
uint32_t opcode = (buffer[0] >> 16u) & 0x7fu;
uint32_t simm = (buffer[0] >> 0u) & 0xffffu;
ShaderInstruction inst;
inst.pc = pc;
switch (opcode)
{
case 0x01:
inst.type = ShaderInstructionType::SEndpgm;
inst.format = ShaderInstructionFormat::Empty;
break;
case 0x08:
inst.type = ShaderInstructionType::SCbranchExecz;
inst.format = ShaderInstructionFormat::Label;
inst.src[0].type = ShaderOperandType::LiteralConstant;
inst.src[0].constant.i = static_cast<int16_t>(simm) * 4;
inst.src_num = 1;
break;
case 0x0c:
inst.type = ShaderInstructionType::SWaitcnt;
inst.format = ShaderInstructionFormat::Imm;
inst.src[0].type = ShaderOperandType::LiteralConstant;
inst.src[0].constant.u = simm;
inst.src_num = 1;
break;
default: printf("%s", dst->DbgDump().C_Str()); EXIT("unknown sopp opcode: 0x%02" PRIx32 " at addr 0x%08" PRIx32 "\n", opcode, pc);
}
dst->GetInstructions().Add(inst);
if (inst.type == ShaderInstructionType::SCbranchExecz)
{
dst->GetLabels().Add(inst.pc + 4 + inst.src[0].constant.i);
}
return 1;
}
KYTY_SHADER_PARSER(shader_parse_sop2)
{
EXIT_IF(dst == nullptr);
@ -486,10 +585,16 @@ KYTY_SHADER_PARSER(shader_parse_sop2)
switch (opcode)
{
case 0x7d: return shader_parse_sop1(pc, src, buffer, dst); break;
case 0x7e: return shader_parse_sopc(pc, src, buffer, dst); break;
case 0x7f: return shader_parse_sopp(pc, src, buffer, dst); break;
default: break;
}
if (opcode >= 0x60)
{
return shader_parse_sopk(pc, src, buffer, dst);
}
uint32_t ssrc1 = (buffer[0] >> 8u) & 0xffu;
uint32_t ssrc0 = (buffer[0] >> 0u) & 0xffu;
uint32_t sdst = (buffer[0] >> 16u) & 0x7fu;
@ -519,6 +624,16 @@ KYTY_SHADER_PARSER(shader_parse_sop2)
switch (opcode)
{
case 0x02: inst.type = ShaderInstructionType::SAddI32; break;
case 0x0a: inst.type = ShaderInstructionType::SCselectB32; break;
case 0x0e: inst.type = ShaderInstructionType::SAndB32; break;
case 0x11:
inst.type = ShaderInstructionType::SOrB64;
inst.format = ShaderInstructionFormat::Sdst2Ssrc02Ssrc12;
inst.dst.size = 2;
inst.src[0].size = 2;
inst.src[1].size = 2;
break;
case 0x15:
inst.type = ShaderInstructionType::SAndn2B64;
inst.format = ShaderInstructionFormat::Sdst2Ssrc02Ssrc12;
@ -526,7 +641,16 @@ KYTY_SHADER_PARSER(shader_parse_sop2)
inst.src[0].size = 2;
inst.src[1].size = 2;
break;
case 0x1b:
inst.type = ShaderInstructionType::SNorB64;
inst.format = ShaderInstructionFormat::Sdst2Ssrc02Ssrc12;
inst.dst.size = 2;
inst.src[0].size = 2;
inst.src[1].size = 2;
break;
case 0x1e: inst.type = ShaderInstructionType::SLshlB32; break;
case 0x20: inst.type = ShaderInstructionType::SLshrB32; break;
case 0x26: inst.type = ShaderInstructionType::SMulI32; break;
default: printf("%s", dst->DbgDump().C_Str()); EXIT("unknown sop2 opcode: 0x%02" PRIx32 " at addr 0x%08" PRIx32 "\n", opcode, pc);
}
@ -559,38 +683,20 @@ KYTY_SHADER_PARSER(shader_parse_vopc)
size++;
}
inst.format = ShaderInstructionFormat::SmaskVsrc0Vsrc1;
inst.dst.type = ShaderOperandType::VccLo;
inst.dst.size = 2;
switch (opcode)
{
case 0x0d:
inst.type = ShaderInstructionType::VCmpNeqF32;
inst.format = ShaderInstructionFormat::SmaskVsrc0Vsrc1;
inst.dst.type = ShaderOperandType::VccLo;
inst.dst.size = 2;
break;
case 0xc2:
inst.type = ShaderInstructionType::VCmpEqU32;
inst.format = ShaderInstructionFormat::SmaskVsrc0Vsrc1;
inst.dst.type = ShaderOperandType::VccLo;
inst.dst.size = 2;
break;
case 0xc5:
inst.type = ShaderInstructionType::VCmpNeU32;
inst.format = ShaderInstructionFormat::SmaskVsrc0Vsrc1;
inst.dst.type = ShaderOperandType::VccLo;
inst.dst.size = 2;
break;
case 0xd2:
inst.type = ShaderInstructionType::VCmpxEqU32;
inst.format = ShaderInstructionFormat::SmaskVsrc0Vsrc1;
inst.dst.type = ShaderOperandType::VccLo;
inst.dst.size = 2;
break;
case 0xd4:
inst.type = ShaderInstructionType::VCmpxGtU32;
inst.format = ShaderInstructionFormat::SmaskVsrc0Vsrc1;
inst.dst.type = ShaderOperandType::VccLo;
inst.dst.size = 2;
break;
case 0x02: inst.type = ShaderInstructionType::VCmpEqF32; break;
case 0x0d: inst.type = ShaderInstructionType::VCmpNeqF32; break;
case 0x84: inst.type = ShaderInstructionType::VCmpGtI32; break;
case 0xc2: inst.type = ShaderInstructionType::VCmpEqU32; break;
case 0xc5: inst.type = ShaderInstructionType::VCmpNeU32; break;
case 0xd2: inst.type = ShaderInstructionType::VCmpxEqU32; break;
case 0xd4: inst.type = ShaderInstructionType::VCmpxGtU32; break;
case 0xd5: inst.type = ShaderInstructionType::VCmpxNeU32; break;
default: printf("%s", dst->DbgDump().C_Str()); EXIT("unknown vopc opcode: 0x%02" PRIx32 " at addr 0x%08" PRIx32 "\n", opcode, pc);
}
@ -623,32 +729,21 @@ KYTY_SHADER_PARSER(shader_parse_vop1)
size++;
}
inst.format = ShaderInstructionFormat::SVdstSVsrc0;
switch (opcode)
{
case 0x01:
inst.type = ShaderInstructionType::VMovB32;
inst.format = ShaderInstructionFormat::SVdstSVsrc0;
break;
case 0x06:
inst.type = ShaderInstructionType::VCvtF32U32;
inst.format = ShaderInstructionFormat::SVdstSVsrc0;
break;
case 0x07:
inst.type = ShaderInstructionType::VCvtU32F32;
inst.format = ShaderInstructionFormat::SVdstSVsrc0;
break;
case 0x2a:
inst.type = ShaderInstructionType::VRcpF32;
inst.format = ShaderInstructionFormat::SVdstSVsrc0;
break;
case 0x2e:
inst.type = ShaderInstructionType::VRsqF32;
inst.format = ShaderInstructionFormat::SVdstSVsrc0;
break;
case 0x33:
inst.type = ShaderInstructionType::VSqrtF32;
inst.format = ShaderInstructionFormat::SVdstSVsrc0;
break;
case 0x01: inst.type = ShaderInstructionType::VMovB32; break;
case 0x06: inst.type = ShaderInstructionType::VCvtF32U32; break;
case 0x07: inst.type = ShaderInstructionType::VCvtU32F32; break;
case 0x11: inst.type = ShaderInstructionType::VCvtF32Ubyte0; break;
case 0x12: inst.type = ShaderInstructionType::VCvtF32Ubyte1; break;
case 0x13: inst.type = ShaderInstructionType::VCvtF32Ubyte2; break;
case 0x14: inst.type = ShaderInstructionType::VCvtF32Ubyte3; break;
case 0x2a: inst.type = ShaderInstructionType::VRcpF32; break;
case 0x2e: inst.type = ShaderInstructionType::VRsqF32; break;
case 0x33: inst.type = ShaderInstructionType::VSqrtF32; break;
case 0x37: inst.type = ShaderInstructionType::VNotB32; break;
default: printf("%s", dst->DbgDump().C_Str()); EXIT("unknown vop1 opcode: 0x%02" PRIx32 " at addr 0x%08" PRIx32 "\n", opcode, pc);
}
@ -683,6 +778,8 @@ KYTY_SHADER_PARSER(shader_parse_vop2)
size++;
}
inst.format = ShaderInstructionFormat::SVdstSVsrc0SVsrc1;
switch (opcode)
{
case 0x00:
@ -692,34 +789,18 @@ KYTY_SHADER_PARSER(shader_parse_vop2)
inst.src[2].size = 2;
inst.src_num = 3;
break;
case 0x04:
inst.type = ShaderInstructionType::VSubF32;
inst.format = ShaderInstructionFormat::SVdstSVsrc0SVsrc1;
break;
case 0x05:
inst.type = ShaderInstructionType::VSubrevF32;
inst.format = ShaderInstructionFormat::SVdstSVsrc0SVsrc1;
break;
case 0x08:
inst.type = ShaderInstructionType::VMulF32;
inst.format = ShaderInstructionFormat::SVdstSVsrc0SVsrc1;
break;
case 0x0f:
inst.type = ShaderInstructionType::VMinF32;
inst.format = ShaderInstructionFormat::SVdstSVsrc0SVsrc1;
break;
case 0x10:
inst.type = ShaderInstructionType::VMaxF32;
inst.format = ShaderInstructionFormat::SVdstSVsrc0SVsrc1;
break;
case 0x1b:
inst.type = ShaderInstructionType::VAndB32;
inst.format = ShaderInstructionFormat::SVdstSVsrc0SVsrc1;
break;
case 0x1f:
inst.type = ShaderInstructionType::VMacF32;
inst.format = ShaderInstructionFormat::SVdstSVsrc0SVsrc1;
break;
case 0x04: inst.type = ShaderInstructionType::VSubF32; break;
case 0x05: inst.type = ShaderInstructionType::VSubrevF32; break;
case 0x08: inst.type = ShaderInstructionType::VMulF32; break;
case 0x0b: inst.type = ShaderInstructionType::VMulU32U24; break;
case 0x0f: inst.type = ShaderInstructionType::VMinF32; break;
case 0x10: inst.type = ShaderInstructionType::VMaxF32; break;
case 0x15: inst.type = ShaderInstructionType::VLshrB32; break;
case 0x16: inst.type = ShaderInstructionType::VLshrrevB32; break;
case 0x18: inst.type = ShaderInstructionType::VAshrrevI32; break;
case 0x1a: inst.type = ShaderInstructionType::VLshlrevB32; break;
case 0x1b: inst.type = ShaderInstructionType::VAndB32; break;
case 0x1f: inst.type = ShaderInstructionType::VMacF32; break;
case 0x21:
inst.type = ShaderInstructionType::VMadakF32;
inst.format = ShaderInstructionFormat::VdstVsrc0Vsrc1Vsrc2;
@ -729,14 +810,8 @@ KYTY_SHADER_PARSER(shader_parse_vop2)
inst.src[2].size = 0;
size++;
break;
case 0x23:
inst.type = ShaderInstructionType::VMbcntLoU32B32;
inst.format = ShaderInstructionFormat::SVdstSVsrc0SVsrc1;
break;
case 0x24:
inst.type = ShaderInstructionType::VMbcntHiU32B32;
inst.format = ShaderInstructionFormat::SVdstSVsrc0SVsrc1;
break;
case 0x23: inst.type = ShaderInstructionType::VMbcntLoU32B32; break;
case 0x24: inst.type = ShaderInstructionType::VMbcntHiU32B32; break;
case 0x25:
inst.type = ShaderInstructionType::VAddI32;
inst.format = ShaderInstructionFormat::VdstSdst2Vsrc0Vsrc1;
@ -755,10 +830,7 @@ KYTY_SHADER_PARSER(shader_parse_vop2)
inst.dst2.type = ShaderOperandType::VccLo;
inst.dst2.size = 2;
break;
case 0x2f:
inst.type = ShaderInstructionType::VCvtPkrtzF16F32;
inst.format = ShaderInstructionFormat::SVdstSVsrc0SVsrc1;
break;
case 0x2f: inst.type = ShaderInstructionType::VCvtPkrtzF16F32; break;
case 0x3e: return shader_parse_vopc(pc, src, buffer, dst); break;
case 0x3f: return shader_parse_vop1(pc, src, buffer, dst); break;
default: printf("%s", dst->DbgDump().C_Str()); EXIT("unknown vop2 opcode: 0x%02" PRIx32 " at addr 0x%08" PRIx32 "\n", opcode, pc);
@ -840,6 +912,8 @@ KYTY_SHADER_PARSER(shader_parse_vop3)
size++;
}
inst.format = ShaderInstructionFormat::VdstVsrc0Vsrc1Vsrc2;
switch (opcode)
{
case 0x02:
@ -856,6 +930,13 @@ KYTY_SHADER_PARSER(shader_parse_vop3)
inst.dst = operand_parse(vdst);
inst.dst.size = 2;
break;
case 0x84:
inst.type = ShaderInstructionType::VCmpGtI32;
inst.format = ShaderInstructionFormat::SmaskVsrc0Vsrc1;
inst.src_num = 2;
inst.dst = operand_parse(vdst);
inst.dst.size = 2;
break;
case 0xc2:
inst.type = ShaderInstructionType::VCmpEqU32;
inst.format = ShaderInstructionFormat::SmaskVsrc0Vsrc1;
@ -883,12 +964,14 @@ KYTY_SHADER_PARSER(shader_parse_vop3)
inst.src[2].size = 2;
break;
case 0x104:
inst.type = ShaderInstructionType::VSubF32;
inst.format = ShaderInstructionFormat::SVdstSVsrc0SVsrc1;
inst.type = ShaderInstructionType::VSubF32;
inst.format = ShaderInstructionFormat::SVdstSVsrc0SVsrc1;
inst.src_num = 2;
break;
case 0x108:
inst.type = ShaderInstructionType::VMulF32;
inst.format = ShaderInstructionFormat::SVdstSVsrc0SVsrc1;
inst.type = ShaderInstructionType::VMulF32;
inst.format = ShaderInstructionFormat::SVdstSVsrc0SVsrc1;
inst.src_num = 2;
break;
case 0x11f:
inst.type = ShaderInstructionType::VMacF32;
@ -901,16 +984,18 @@ KYTY_SHADER_PARSER(shader_parse_vop3)
inst.src_num = 2;
break;
case 0x12f:
inst.type = ShaderInstructionType::VCvtPkrtzF16F32;
inst.format = ShaderInstructionFormat::SVdstSVsrc0SVsrc1;
inst.type = ShaderInstructionType::VCvtPkrtzF16F32;
inst.format = ShaderInstructionFormat::SVdstSVsrc0SVsrc1;
inst.src_num = 2;
break;
case 0x141:
inst.type = ShaderInstructionType::VMadF32;
inst.format = ShaderInstructionFormat::VdstVsrc0Vsrc1Vsrc2;
break;
case 0x15d:
inst.type = ShaderInstructionType::VSadU32;
inst.format = ShaderInstructionFormat::VdstVsrc0Vsrc1Vsrc2;
case 0x141: inst.type = ShaderInstructionType::VMadF32; break;
case 0x143: inst.type = ShaderInstructionType::VMadU32U24; break;
case 0x148: inst.type = ShaderInstructionType::VBfeU32; break;
case 0x15d: inst.type = ShaderInstructionType::VSadU32; break;
case 0x16b:
inst.type = ShaderInstructionType::VMulLoI32;
inst.format = ShaderInstructionFormat::SVdstSVsrc0SVsrc1;
inst.src_num = 2;
break;
default: printf("%s", dst->DbgDump().C_Str()); EXIT("unknown vop3 opcode: 0x%02" PRIx32 " at addr 0x%08" PRIx32 "\n", opcode, pc);
}
@ -937,8 +1022,6 @@ KYTY_SHADER_PARSER(shader_parse_exp)
uint32_t vsrc2 = (buffer[1] >> 16u) & 0xffu;
uint32_t vsrc3 = (buffer[1] >> 24u) & 0xffu;
EXIT_NOT_IMPLEMENTED(en != 0xf);
ShaderInstruction inst;
inst.pc = pc;
inst.src[0] = operand_parse(vsrc0 + 256);
@ -952,28 +1035,40 @@ KYTY_SHADER_PARSER(shader_parse_exp)
switch (target)
{
case 0x00:
if (done != 0 && compr != 0 && vm != 0)
if (done != 0 && compr != 0 && vm != 0 && en == 0x0)
{
inst.format = ShaderInstructionFormat::Mrt0OffOffComprVmDone;
inst.src_num = 0;
} else if (done != 0 && compr != 0 && vm != 0 && en == 0xf)
{
inst.format = ShaderInstructionFormat::Mrt0Vsrc0Vsrc1ComprVmDone;
inst.src_num = 2;
} else if (done != 0 && compr == 0 && vm != 0)
} else if (done != 0 && compr == 0 && vm != 0 && en == 0xf)
{
inst.format = ShaderInstructionFormat::Mrt0Vsrc0Vsrc1Vsrc2Vsrc3VmDone;
};
break;
case 0x0c:
if (done != 0)
if (done != 0 && en == 0xf)
{
inst.format = ShaderInstructionFormat::Pos0Vsrc0Vsrc1Vsrc2Vsrc3Done;
};
break;
case 0x20: inst.format = ShaderInstructionFormat::Param0Vsrc0Vsrc1Vsrc2Vsrc3; break;
case 0x21: inst.format = ShaderInstructionFormat::Param1Vsrc0Vsrc1Vsrc2Vsrc3; break;
case 0x22: inst.format = ShaderInstructionFormat::Param2Vsrc0Vsrc1Vsrc2Vsrc3; break;
case 0x23: inst.format = ShaderInstructionFormat::Param3Vsrc0Vsrc1Vsrc2Vsrc3; break;
default: break;
}
if (inst.format == ShaderInstructionFormat::Unknown && done == 0 && compr == 0 && vm == 0 && en == 0xf)
{
switch (target)
{
case 0x20: inst.format = ShaderInstructionFormat::Param0Vsrc0Vsrc1Vsrc2Vsrc3; break;
case 0x21: inst.format = ShaderInstructionFormat::Param1Vsrc0Vsrc1Vsrc2Vsrc3; break;
case 0x22: inst.format = ShaderInstructionFormat::Param2Vsrc0Vsrc1Vsrc2Vsrc3; break;
case 0x23: inst.format = ShaderInstructionFormat::Param3Vsrc0Vsrc1Vsrc2Vsrc3; break;
default: break;
}
}
if (inst.format == ShaderInstructionFormat::Unknown)
{
printf("%s", dst->DbgDump().C_Str());
@ -1039,6 +1134,12 @@ KYTY_SHADER_PARSER(shader_parse_smrd)
inst.format = ShaderInstructionFormat::SdstSvSoffset;
inst.src[0].size = 4;
break;
case 0x09:
inst.type = ShaderInstructionType::SBufferLoadDwordx2;
inst.format = ShaderInstructionFormat::Sdst2SvSoffset;
inst.src[0].size = 4;
inst.dst.size = 2;
break;
case 0x0a:
inst.type = ShaderInstructionType::SBufferLoadDwordx4;
inst.format = ShaderInstructionFormat::Sdst4SvSoffset;
@ -1293,7 +1394,7 @@ KYTY_SHADER_PARSER(shader_parse_mtbuf)
uint32_t vaddr = (buffer[1] >> 0u) & 0xffu;
EXIT_NOT_IMPLEMENTED(idxen == 0);
EXIT_NOT_IMPLEMENTED(offen == 1);
// EXIT_NOT_IMPLEMENTED(offen == 1);
EXIT_NOT_IMPLEMENTED(offset != 0);
EXIT_NOT_IMPLEMENTED(glc == 1);
EXIT_NOT_IMPLEMENTED(slc == 1);
@ -1317,13 +1418,16 @@ KYTY_SHADER_PARSER(shader_parse_mtbuf)
size++;
}
inst.src[1].size = 4;
switch (opcode) // NOLINT
{
case 0x03:
inst.type = ShaderInstructionType::TBufferLoadFormatXyzw;
inst.format = ShaderInstructionFormat::Vdata4VaddrSvSoffsIdxenFloat4;
inst.src[1].size = 4;
inst.dst.size = 4;
inst.type = ShaderInstructionType::TBufferLoadFormatXyzw;
inst.format = (offen == 1 ? ShaderInstructionFormat::Vdata4Vaddr2SvSoffsOffenIdxenFloat4
: ShaderInstructionFormat::Vdata4VaddrSvSoffsIdxenFloat4);
inst.src[0].size += static_cast<int>(offen);
inst.dst.size = 4;
break;
default: printf("%s", dst->DbgDump().C_Str()); EXIT("unknown mtbuf opcode: 0x%02" PRIx32 " at addr 0x%08" PRIx32 "\n", opcode, pc);
}
@ -1426,7 +1530,8 @@ KYTY_SHADER_PARSER(shader_parse)
EXIT("unknown code 0x%08" PRIx32 " at addr 0x%08" PRIx32 "\n", ptr[0], pc);
}
if ((instruction == 0xBF810000 && (type == ShaderType::Vertex || type == ShaderType::Pixel || type == ShaderType::Compute)) ||
if ((instruction == 0xBF810000 && (type == ShaderType::Vertex || type == ShaderType::Pixel || type == ShaderType::Compute) &&
!dst->GetLabels().Contains(4 * static_cast<uint32_t>(ptr - src), [](auto label, auto pc) { return label.dst == pc; })) ||
(instruction == 0xBE802000 && type == ShaderType::Fetch))
{
break;
@ -1512,23 +1617,23 @@ static void bi_print(const char* func, const ShaderBinaryInfo& bi)
{
printf("%s\n", func);
printf("\t m_signature = %.7s\n", bi.signature);
printf("\t m_version = 0x%02" PRIx8 "\n", bi.version);
printf("\t m_pssl_or_cg = 0x%08" PRIx32 "\n", static_cast<uint32_t>(bi.pssl_or_cg));
printf("\t m_cached = 0x%08" PRIx32 "\n", static_cast<uint32_t>(bi.cached));
printf("\t m_type = 0x%08" PRIx32 "\n", static_cast<uint32_t>(bi.type));
printf("\t m_source_type = 0x%08" PRIx32 "\n", static_cast<uint32_t>(bi.source_type));
printf("\t m_length = 0x%08" PRIx32 "\n", static_cast<uint32_t>(bi.length));
printf("\t m_chunkUsageBaseOffsetInDW = 0x%02" PRIx8 "\n", bi.chunk_usage_base_offset_dw);
printf("\t m_numInputUsageSlots = 0x%02" PRIx8 "\n", bi.num_input_usage_slots);
printf("\t m_isSrt = 0x%02" PRIx8 "\n", bi.is_srt);
printf("\t m_isSrtUsedInfoValid = 0x%02" PRIx8 "\n", bi.is_srt_used_info_valid);
printf("\t m_isExtendedUsageInfo = 0x%02" PRIx8 "\n", bi.is_extended_usage_info);
printf("\t m_reserved2 = 0x%02" PRIx8 "\n", bi.reserved2);
printf("\t m_reserved3 = 0x%02" PRIx8 "\n", bi.reserved3);
printf("\t m_shaderHash0 = 0x%08" PRIx32 "\n", bi.hash0);
printf("\t m_shaderHash1 = 0x%08" PRIx32 "\n", bi.hash1);
printf("\t m_crc32 = 0x%08" PRIx32 "\n", bi.crc32);
printf("\t signature = %.7s\n", bi.signature);
printf("\t version = 0x%02" PRIx8 "\n", bi.version);
printf("\t pssl_or_cg = 0x%08" PRIx32 "\n", static_cast<uint32_t>(bi.pssl_or_cg));
printf("\t cached = 0x%08" PRIx32 "\n", static_cast<uint32_t>(bi.cached));
printf("\t type = 0x%08" PRIx32 "\n", static_cast<uint32_t>(bi.type));
printf("\t source_type = 0x%08" PRIx32 "\n", static_cast<uint32_t>(bi.source_type));
printf("\t length = 0x%08" PRIx32 "\n", static_cast<uint32_t>(bi.length));
printf("\t chunk_usage_base_offset_dw = 0x%02" PRIx8 "\n", bi.chunk_usage_base_offset_dw);
printf("\t num_input_usage_slots = 0x%02" PRIx8 "\n", bi.num_input_usage_slots);
printf("\t is_srt = 0x%02" PRIx8 "\n", bi.is_srt);
printf("\t is_srt_used_info_valid = 0x%02" PRIx8 "\n", bi.is_srt_used_info_valid);
printf("\t is_extended_usage_info = 0x%02" PRIx8 "\n", bi.is_extended_usage_info);
printf("\t reserved2 = 0x%02" PRIx8 "\n", bi.reserved2);
printf("\t reserved3 = 0x%02" PRIx8 "\n", bi.reserved3);
printf("\t hash0 = 0x%08" PRIx32 "\n", bi.hash0);
printf("\t hash1 = 0x%08" PRIx32 "\n", bi.hash1);
printf("\t crc32 = 0x%08" PRIx32 "\n", bi.crc32);
}
static void vs_check(const VsStageRegisters& vs)
@ -2089,7 +2194,7 @@ void ShaderGetInputInfoPS(const PixelShaderInfo* regs, const ShaderVertexInputIn
EXIT_IF(ps_info == nullptr);
EXIT_IF(regs == nullptr);
ps_info->input_num = regs->ps_input_num;
ps_info->input_num = regs->ps_regs.ps_in_control;
ps_info->ps_pos_xy = (regs->ps_regs.ps_input_ena == 0x00000302 && regs->ps_regs.ps_input_addr == 0x00000302);
ps_info->ps_pixel_kill_enable = regs->ps_regs.shader_kill_enable;

File diff suppressed because it is too large Load diff