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
+1 -1
View File
@@ -75,7 +75,7 @@ if (CLANG AND (KYTY_LINKER STREQUAL LLD))
set(KYTY_LD_OPTIONS "-fuse-ld=lld") set(KYTY_LD_OPTIONS "-fuse-ld=lld")
endif() 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) include(src_script.cmake)
@@ -7,6 +7,8 @@
#include "Emulator/Common.h" #include "Emulator/Common.h"
#include <algorithm>
#ifdef KYTY_EMU_ENABLED #ifdef KYTY_EMU_ENABLED
namespace Kyty::Libs::Graphics { namespace Kyty::Libs::Graphics {
@@ -27,9 +29,6 @@ enum class ShaderType
enum class ShaderInstructionType enum class ShaderInstructionType
{ {
Unknown, Unknown,
DsAppend,
DsConsume,
Exp,
BufferLoadDword, BufferLoadDword,
BufferLoadFormatX, BufferLoadFormatX,
BufferLoadFormatXy, BufferLoadFormatXy,
@@ -37,50 +36,78 @@ enum class ShaderInstructionType
BufferLoadFormatXyzw, BufferLoadFormatXyzw,
BufferStoreDword, BufferStoreDword,
BufferStoreFormatX, BufferStoreFormatX,
DsAppend,
DsConsume,
Exp,
ImageSample, ImageSample,
TBufferLoadFormatXyzw, SAddI32,
SAndB32,
SAndn2B64, SAndn2B64,
SAndSaveexecB64, SAndSaveexecB64,
SEndpgm,
SCbranchExecz,
SLshlB32,
SLoadDwordx4,
SLoadDwordx8,
SBufferLoadDword, SBufferLoadDword,
SBufferLoadDwordx16,
SBufferLoadDwordx2,
SBufferLoadDwordx4, SBufferLoadDwordx4,
SBufferLoadDwordx8, SBufferLoadDwordx8,
SBufferLoadDwordx16, SCbranchExecz,
SCbranchScc0,
SCmpEqU32,
SEndpgm,
SLoadDwordx4,
SLoadDwordx8,
SLshlB32,
SLshrB32,
SMovB32, SMovB32,
SMovB64, SMovB64,
SMulI32,
SNorB64,
SOrB64,
SCselectB32,
SSetpcB64, SSetpcB64,
SSwappcB64, SSwappcB64,
SWaitcnt, SWaitcnt,
SWqmB64, SWqmB64,
TBufferLoadFormatXyzw,
VAddI32, VAddI32,
VAndB32, VAndB32,
VAshrrevI32,
VBfeU32,
VCmpEqF32, VCmpEqF32,
VCmpEqU32, VCmpEqU32,
VCmpGtI32,
VCmpLeF32, VCmpLeF32,
VCmpLeU32, VCmpLeU32,
VCmpNeU32,
VCmpNeqF32, VCmpNeqF32,
VCmpNeU32,
VCmpxEqU32, VCmpxEqU32,
VCmpxGtU32, VCmpxGtU32,
VCmpxNeU32,
VCndmaskB32, VCndmaskB32,
VCvtF32U32, VCvtF32U32,
VCvtF32Ubyte0,
VCvtF32Ubyte1,
VCvtF32Ubyte2,
VCvtF32Ubyte3,
VCvtPkrtzF16F32, VCvtPkrtzF16F32,
VCvtU32F32, VCvtU32F32,
VInterpP1F32,
VInterpP2F32,
VLshlrevB32,
VLshrB32,
VLshrrevB32,
VMacF32, VMacF32,
VMadakF32, VMadakF32,
VMadF32, VMadF32,
VMadU32U24,
VMaxF32, VMaxF32,
VMbcntHiU32B32, VMbcntHiU32B32,
VMbcntLoU32B32, VMbcntLoU32B32,
VMinF32, VMinF32,
VMovB32, VMovB32,
VMulF32, VMulF32,
VInterpP1F32, VMulLoI32,
VInterpP2F32, VMulU32U24,
VNotB32,
VRcpF32, VRcpF32,
VRsqF32, VRsqF32,
VSadU32, VSadU32,
@@ -123,6 +150,7 @@ enum FormatByte : uint64_t
S2A4, // operand_array_to_str(inst.src[2], 4) S2A4, // operand_array_to_str(inst.src[2], 4)
Attr, // attr%u.%u <- inst.src[1].constant.u, inst.src[2].constant.u Attr, // attr%u.%u <- inst.src[1].constant.u, inst.src[2].constant.u
Idxen, // idxen Idxen, // idxen
Offen, // offen
Float4, // format:float4 Float4, // format:float4
Pos0, // pos0 Pos0, // pos0
Done, // done Done, // done
@@ -131,6 +159,7 @@ enum FormatByte : uint64_t
Param2, // param2 Param2, // param2
Param3, // param3 Param3, // param3
Mrt0, // mrt_color0 Mrt0, // mrt_color0
Off, // off
Compr, // compr Compr, // compr
Vm, // vm Vm, // vm
L, // label_%u L, // label_%u
@@ -155,6 +184,7 @@ enum Format : uint64_t
Empty = FormatDefine({N}), Empty = FormatDefine({N}),
Imm = FormatDefine({S0}), Imm = FormatDefine({S0}),
Label = FormatDefine({L}), Label = FormatDefine({L}),
Mrt0OffOffComprVmDone = FormatDefine({Mrt0, Off, Off, Compr, Vm, Done}),
Mrt0Vsrc0Vsrc1ComprVmDone = FormatDefine({Mrt0, S0, S1, Compr, Vm, Done}), Mrt0Vsrc0Vsrc1ComprVmDone = FormatDefine({Mrt0, S0, S1, Compr, Vm, Done}),
Mrt0Vsrc0Vsrc1Vsrc2Vsrc3VmDone = FormatDefine({Mrt0, S0, S1, S2, S3, Vm, Done}), Mrt0Vsrc0Vsrc1Vsrc2Vsrc3VmDone = FormatDefine({Mrt0, S0, S1, S2, S3, Vm, Done}),
Param0Vsrc0Vsrc1Vsrc2Vsrc3 = FormatDefine({Param0, S0, S1, S2, S3}), Param0Vsrc0Vsrc1Vsrc2Vsrc3 = FormatDefine({Param0, S0, S1, S2, S3}),
@@ -166,26 +196,30 @@ enum Format : uint64_t
Sdst4SbaseSoffset = FormatDefine({DA4, S0A2, S1}), Sdst4SbaseSoffset = FormatDefine({DA4, S0A2, S1}),
Sdst8SbaseSoffset = FormatDefine({DA8, S0A2, S1}), Sdst8SbaseSoffset = FormatDefine({DA8, S0A2, S1}),
SdstSvSoffset = FormatDefine({D, S0A4, S1}), SdstSvSoffset = FormatDefine({D, S0A4, S1}),
Sdst2SvSoffset = FormatDefine({DA2, S0A4, S1}),
Sdst4SvSoffset = FormatDefine({DA4, S0A4, S1}), Sdst4SvSoffset = FormatDefine({DA4, S0A4, S1}),
Sdst8SvSoffset = FormatDefine({DA8, S0A4, S1}), Sdst8SvSoffset = FormatDefine({DA8, S0A4, S1}),
Sdst16SvSoffset = FormatDefine({DA16, S0A4, S1}), Sdst16SvSoffset = FormatDefine({DA16, S0A4, S1}),
SVdstSVsrc0 = FormatDefine({D, S0}), SVdstSVsrc0 = FormatDefine({D, S0}),
SVdstSVsrc0SVsrc1 = FormatDefine({D, S0, S1}), SVdstSVsrc0SVsrc1 = FormatDefine({D, S0, S1}),
Sdst2Ssrc02 = FormatDefine({DA2, S0A2}), Sdst2Ssrc02 = FormatDefine({DA2, S0A2}),
Sdst2Ssrc0 = FormatDefine({DA2, S0}),
Sdst2Ssrc02Ssrc12 = FormatDefine({DA2, S0A2, S1A2}), Sdst2Ssrc02Ssrc12 = FormatDefine({DA2, S0A2, S1A2}),
SmaskVsrc0Vsrc1 = FormatDefine({DA2, S0, S1}), SmaskVsrc0Vsrc1 = FormatDefine({DA2, S0, S1}),
Ssrc0Ssrc1 = FormatDefine({S0, S1}),
Vdata1VaddrSvSoffsIdxen = FormatDefine({D, S0, S1A4, S2, Idxen}), Vdata1VaddrSvSoffsIdxen = FormatDefine({D, S0, S1A4, S2, Idxen}),
Vdata2VaddrSvSoffsIdxen = FormatDefine({DA2, S0, S1A4, S2, Idxen}), Vdata2VaddrSvSoffsIdxen = FormatDefine({DA2, S0, S1A4, S2, Idxen}),
Vdata3VaddrSvSoffsIdxen = FormatDefine({DA3, S0, S1A4, S2, Idxen}), Vdata3VaddrSvSoffsIdxen = FormatDefine({DA3, S0, S1A4, S2, Idxen}),
Vdata4VaddrSvSoffsIdxen = FormatDefine({DA4, S0, S1A4, S2, Idxen}), Vdata4VaddrSvSoffsIdxen = FormatDefine({DA4, S0, S1A4, S2, Idxen}),
Vdata4VaddrSvSoffsIdxenFloat4 = FormatDefine({DA4, S0, S1A4, S2, Idxen, Float4}), Vdata4VaddrSvSoffsIdxenFloat4 = FormatDefine({DA4, S0, S1A4, S2, Idxen, Float4}),
Vdata4Vaddr2SvSoffsOffenIdxenFloat4 = FormatDefine({DA4, S0A2, S1A4, S2, Offen, Idxen, Float4}),
Vdata3Vaddr3StSsDmask7 = FormatDefine({DA3, S0A3, S1A8, S2A4, Dmask7}), Vdata3Vaddr3StSsDmask7 = FormatDefine({DA3, S0A3, S1A8, S2A4, Dmask7}),
Vdata4Vaddr3StSsDmaskF = FormatDefine({DA4, S0A3, S1A8, S2A4, DmaskF}), Vdata4Vaddr3StSsDmaskF = FormatDefine({DA4, S0A3, S1A8, S2A4, DmaskF}),
VdstVsrc0Vsrc1Smask2 = FormatDefine({D, S0, S1, S2A2}), VdstVsrc0Vsrc1Smask2 = FormatDefine({D, S0, S1, S2A2}),
VdstVsrc0Vsrc1Vsrc2 = FormatDefine({D, S0, S1, S2}), VdstVsrc0Vsrc1Vsrc2 = FormatDefine({D, S0, S1, S2}),
VdstVsrcAttrChan = FormatDefine({D, S0, Attr}), VdstVsrcAttrChan = FormatDefine({D, S0, Attr}),
VdstSdst2Vsrc0Vsrc1 = FormatDefine({D, D2A2, S0, S1}), VdstSdst2Vsrc0Vsrc1 = FormatDefine({D, D2A2, S0, S1}),
VdstGds = FormatDefine({D, Gds}) VdstGds = FormatDefine({D, Gds}),
}; };
} // namespace ShaderInstructionFormat } // namespace ShaderInstructionFormat
@@ -201,6 +235,7 @@ enum class ShaderOperandType
ExecLo, ExecLo,
ExecHi, ExecHi,
ExecZ, ExecZ,
Scc,
Vgpr, Vgpr,
Sgpr, Sgpr,
M0 M0
@@ -240,6 +275,12 @@ struct ShaderInstruction
ShaderOperand dst2; ShaderOperand dst2;
}; };
struct ShaderLabel
{
uint32_t dst;
uint32_t src;
};
class ShaderCode class ShaderCode
{ {
public: public:
@@ -249,8 +290,8 @@ public:
[[nodiscard]] const Vector<ShaderInstruction>& GetInstructions() const { return m_instructions; } [[nodiscard]] const Vector<ShaderInstruction>& GetInstructions() const { return m_instructions; }
Vector<ShaderInstruction>& GetInstructions() { return m_instructions; } Vector<ShaderInstruction>& GetInstructions() { return m_instructions; }
[[nodiscard]] const Vector<uint32_t>& GetLabels() const { return m_labels; } [[nodiscard]] const Vector<ShaderLabel>& GetLabels() const { return m_labels; }
Vector<uint32_t>& GetLabels() { return m_labels; } Vector<ShaderLabel>& GetLabels() { return m_labels; }
[[nodiscard]] String DbgDump() const; [[nodiscard]] String DbgDump() const;
@@ -259,9 +300,16 @@ public:
[[nodiscard]] ShaderType GetType() const { return m_type; } [[nodiscard]] ShaderType GetType() const { return m_type; }
void SetType(ShaderType type) { this->m_type = 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: private:
Vector<ShaderInstruction> m_instructions; Vector<ShaderInstruction> m_instructions;
Vector<uint32_t> m_labels; Vector<ShaderLabel> m_labels;
ShaderType m_type = ShaderType::Unknown; ShaderType m_type = ShaderType::Unknown;
}; };
@@ -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, TileGetDepthSize(z.width, z.height, z.z_info.format, z.stencil_info.format, htile, neo, &stencil_size, &htile_size, &depth_size,
&pitch); &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) switch (z.z_info.format * 2 + z.stencil_info.format)
{ {
+281 -176
View File
@@ -24,7 +24,8 @@
#ifdef KYTY_EMU_ENABLED #ifdef KYTY_EMU_ENABLED
#define KYTY_SHADER_PARSER_ARGS \ #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_SHADER_PARSER(f) static uint32_t f(KYTY_SHADER_PARSER_ARGS)
#define KYTY_CP_OP_PARSER_ARGS \ #define KYTY_CP_OP_PARSER_ARGS \
[[maybe_unused]] CommandProcessor *cp, [[maybe_unused]] uint32_t cmd_id, [[maybe_unused]] const uint32_t *buffer, \ [[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::ExecHi: ret = U"exec_hi"; break;
case ShaderOperandType::ExecLo: ret = U"exec_lo"; break; case ShaderOperandType::ExecLo: ret = U"exec_lo"; break;
case ShaderOperandType::ExecZ: ret = U"execz"; break; case ShaderOperandType::ExecZ: ret = U"execz"; break;
case ShaderOperandType::Scc: ret = U"scc"; break;
case ShaderOperandType::M0: ret = U"m0"; break; case ShaderOperandType::M0: ret = U"m0"; break;
case ShaderOperandType::Vgpr: ret = String::FromPrintf("v%d", op.register_id); 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; 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; default: break;
} }
EXIT_IF(ret == U"???");
if (op.negate) if (op.negate)
{ {
return U"-" + ret; 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::Unknown: return U"Unknown"; break;
case ShaderInstructionFormat::Empty: return U"Empty"; break; case ShaderInstructionFormat::Empty: return U"Empty"; break;
case ShaderInstructionFormat::Imm: return U"Imm"; break; case ShaderInstructionFormat::Imm: return U"Imm"; break;
case ShaderInstructionFormat::Mrt0OffOffComprVmDone: return U"Mrt0OffOffComprVmDone"; break;
case ShaderInstructionFormat::Mrt0Vsrc0Vsrc1ComprVmDone: return U"Mrt0Vsrc0Vsrc1ComprVmDone"; break; case ShaderInstructionFormat::Mrt0Vsrc0Vsrc1ComprVmDone: return U"Mrt0Vsrc0Vsrc1ComprVmDone"; break;
case ShaderInstructionFormat::Mrt0Vsrc0Vsrc1Vsrc2Vsrc3VmDone: return U"Mrt0Vsrc0Vsrc1Vsrc2Vsrc3VmDone"; break; case ShaderInstructionFormat::Mrt0Vsrc0Vsrc1Vsrc2Vsrc3VmDone: return U"Mrt0Vsrc0Vsrc1Vsrc2Vsrc3VmDone"; break;
case ShaderInstructionFormat::Param0Vsrc0Vsrc1Vsrc2Vsrc3: return U"Param0Vsrc0Vsrc1Vsrc2Vsrc3"; 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::Sdst4SbaseSoffset: return U"Sdst4SbaseSoffset"; break;
case ShaderInstructionFormat::Sdst8SbaseSoffset: return U"Sdst8SbaseSoffset"; break; case ShaderInstructionFormat::Sdst8SbaseSoffset: return U"Sdst8SbaseSoffset"; break;
case ShaderInstructionFormat::SdstSvSoffset: return U"SdstSvSoffset"; break; case ShaderInstructionFormat::SdstSvSoffset: return U"SdstSvSoffset"; break;
case ShaderInstructionFormat::Sdst2SvSoffset: return U"Sdst2SvSoffset"; break;
case ShaderInstructionFormat::Sdst4SvSoffset: return U"Sdst4SvSoffset"; break; case ShaderInstructionFormat::Sdst4SvSoffset: return U"Sdst4SvSoffset"; break;
case ShaderInstructionFormat::Sdst8SvSoffset: return U"Sdst8SvSoffset"; break; case ShaderInstructionFormat::Sdst8SvSoffset: return U"Sdst8SvSoffset"; break;
case ShaderInstructionFormat::Sdst16SvSoffset: return U"Sdst16SvSoffset"; break; case ShaderInstructionFormat::Sdst16SvSoffset: return U"Sdst16SvSoffset"; break;
case ShaderInstructionFormat::SVdstSVsrc0: return U"SVdstSVsrc0"; break; case ShaderInstructionFormat::SVdstSVsrc0: return U"SVdstSVsrc0"; break;
case ShaderInstructionFormat::Sdst2Ssrc02: return U"Sdst2Ssrc02"; break; case ShaderInstructionFormat::Sdst2Ssrc02: return U"Sdst2Ssrc02"; break;
case ShaderInstructionFormat::Sdst2Ssrc0: return U"Sdst2Ssrc0"; break;
case ShaderInstructionFormat::Sdst2Ssrc02Ssrc12: return U"Sdst2Ssrc02Ssrc12"; break; case ShaderInstructionFormat::Sdst2Ssrc02Ssrc12: return U"Sdst2Ssrc02Ssrc12"; break;
case ShaderInstructionFormat::SmaskVsrc0Vsrc1: return U"SmaskVsrc0Vsrc1"; break; case ShaderInstructionFormat::SmaskVsrc0Vsrc1: return U"SmaskVsrc0Vsrc1"; break;
case ShaderInstructionFormat::Ssrc0Ssrc1: return U"Ssrc0Ssrc1"; break;
case ShaderInstructionFormat::Vdata1VaddrSvSoffsIdxen: return U"Vdata1VaddrSvSoffsIdxen"; break; case ShaderInstructionFormat::Vdata1VaddrSvSoffsIdxen: return U"Vdata1VaddrSvSoffsIdxen"; break;
case ShaderInstructionFormat::Vdata2VaddrSvSoffsIdxen: return U"Vdata2VaddrSvSoffsIdxen"; break; case ShaderInstructionFormat::Vdata2VaddrSvSoffsIdxen: return U"Vdata2VaddrSvSoffsIdxen"; break;
case ShaderInstructionFormat::Vdata3VaddrSvSoffsIdxen: return U"Vdata3VaddrSvSoffsIdxen"; break; case ShaderInstructionFormat::Vdata3VaddrSvSoffsIdxen: return U"Vdata3VaddrSvSoffsIdxen"; break;
case ShaderInstructionFormat::Vdata4VaddrSvSoffsIdxen: return U"Vdata4VaddrSvSoffsIdxen"; break; case ShaderInstructionFormat::Vdata4VaddrSvSoffsIdxen: return U"Vdata4VaddrSvSoffsIdxen"; break;
case ShaderInstructionFormat::Vdata4VaddrSvSoffsIdxenFloat4: return U"Vdata4VaddrSvSoffsIdxenFloat4"; break; case ShaderInstructionFormat::Vdata4VaddrSvSoffsIdxenFloat4: return U"Vdata4VaddrSvSoffsIdxenFloat4"; break;
case ShaderInstructionFormat::Vdata4Vaddr2SvSoffsOffenIdxenFloat4: return U"Vdata4Vaddr2SvSoffsOffenIdxenFloat4"; break;
case ShaderInstructionFormat::Vdata3Vaddr3StSsDmask7: return U"Vdata4Vaddr3StSsDmask7"; break; case ShaderInstructionFormat::Vdata3Vaddr3StSsDmask7: return U"Vdata4Vaddr3StSsDmask7"; break;
case ShaderInstructionFormat::Vdata4Vaddr3StSsDmaskF: return U"Vdata4Vaddr3StSsDmaskF"; break; case ShaderInstructionFormat::Vdata4Vaddr3StSsDmaskF: return U"Vdata4Vaddr3StSsDmaskF"; break;
case ShaderInstructionFormat::SVdstSVsrc0SVsrc1: return U"SVdstSVsrc0SVsrc1"; break; case ShaderInstructionFormat::SVdstSVsrc0SVsrc1: return U"SVdstSVsrc0SVsrc1"; break;
@@ -202,6 +211,7 @@ static String dbg_fmt_print(const ShaderInstruction& inst)
{ {
return str; return str;
} }
int src_num = 0;
for (;;) for (;;)
{ {
String s; 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::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::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::Idxen: s = U"idxen"; break;
case ShaderInstructionFormat::Offen: s = U"offen"; break;
case ShaderInstructionFormat::Float4: s = U"format:float4"; break; case ShaderInstructionFormat::Float4: s = U"format:float4"; break;
case ShaderInstructionFormat::Pos0: s = U"pos0"; break; case ShaderInstructionFormat::Pos0: s = U"pos0"; break;
case ShaderInstructionFormat::Done: s = U"done"; 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::Param2: s = U"param2"; break;
case ShaderInstructionFormat::Param3: s = U"param3"; break; case ShaderInstructionFormat::Param3: s = U"param3"; break;
case ShaderInstructionFormat::Mrt0: s = U"mrt_color0"; 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::Compr: s = U"compr"; break;
case ShaderInstructionFormat::Vm: s = U"vm"; 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; 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; case ShaderInstructionFormat::Gds: s = U"gds"; break;
default: EXIT("unknown code: %u\n", static_cast<uint32_t>(fu)); 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); str = s + (str.IsEmpty() ? U"" : U", " + str);
f >>= 8u; f >>= 8u;
} }
EXIT_IF(src_num != inst.src_num);
if (inst.dst.multiplier == 2.0f) if (inst.dst.multiplier == 2.0f)
{ {
str += " mul:2"; str += " mul:2";
@@ -294,7 +327,7 @@ String ShaderCode::DbgDump() const
String ret; String ret;
for (const auto& inst: m_instructions) 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); ret += String::FromPrintf("label_%04" PRIx32 ":\n", inst.pc);
} }
@@ -363,6 +396,108 @@ static ShaderOperand operand_parse(uint32_t code)
return ret; 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) KYTY_SHADER_PARSER(shader_parse_sop1)
{ {
EXIT_IF(dst == nullptr); EXIT_IF(dst == nullptr);
@@ -395,10 +530,19 @@ KYTY_SHADER_PARSER(shader_parse_sop1)
break; break;
case 0x04: case 0x04:
inst.type = ShaderInstructionType::SMovB64; inst.type = ShaderInstructionType::SMovB64;
inst.format = ShaderInstructionFormat::Sdst2Ssrc02;
inst.dst.size = 2; 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; inst.src[0].size = 2;
break; break;
case ShaderOperandType::IntegerInlineConstant: inst.format = ShaderInstructionFormat::Sdst2Ssrc0; break;
default: EXIT("unknown src0 type");
}
break;
case 0x0a: case 0x0a:
inst.type = ShaderInstructionType::SWqmB64; inst.type = ShaderInstructionType::SWqmB64;
inst.format = ShaderInstructionFormat::Sdst2Ssrc02; inst.format = ShaderInstructionFormat::Sdst2Ssrc02;
@@ -430,51 +574,6 @@ KYTY_SHADER_PARSER(shader_parse_sop1)
return size; 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) KYTY_SHADER_PARSER(shader_parse_sop2)
{ {
EXIT_IF(dst == nullptr); EXIT_IF(dst == nullptr);
@@ -486,10 +585,16 @@ KYTY_SHADER_PARSER(shader_parse_sop2)
switch (opcode) switch (opcode)
{ {
case 0x7d: return shader_parse_sop1(pc, src, buffer, dst); break; 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; case 0x7f: return shader_parse_sopp(pc, src, buffer, dst); break;
default: break; default: break;
} }
if (opcode >= 0x60)
{
return shader_parse_sopk(pc, src, buffer, dst);
}
uint32_t ssrc1 = (buffer[0] >> 8u) & 0xffu; uint32_t ssrc1 = (buffer[0] >> 8u) & 0xffu;
uint32_t ssrc0 = (buffer[0] >> 0u) & 0xffu; uint32_t ssrc0 = (buffer[0] >> 0u) & 0xffu;
uint32_t sdst = (buffer[0] >> 16u) & 0x7fu; uint32_t sdst = (buffer[0] >> 16u) & 0x7fu;
@@ -519,6 +624,16 @@ KYTY_SHADER_PARSER(shader_parse_sop2)
switch (opcode) 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: case 0x15:
inst.type = ShaderInstructionType::SAndn2B64; inst.type = ShaderInstructionType::SAndn2B64;
inst.format = ShaderInstructionFormat::Sdst2Ssrc02Ssrc12; inst.format = ShaderInstructionFormat::Sdst2Ssrc02Ssrc12;
@@ -526,7 +641,16 @@ KYTY_SHADER_PARSER(shader_parse_sop2)
inst.src[0].size = 2; inst.src[0].size = 2;
inst.src[1].size = 2; inst.src[1].size = 2;
break; 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 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); 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++; size++;
} }
inst.format = ShaderInstructionFormat::SmaskVsrc0Vsrc1;
inst.dst.type = ShaderOperandType::VccLo;
inst.dst.size = 2;
switch (opcode) switch (opcode)
{ {
case 0x0d: case 0x02: inst.type = ShaderInstructionType::VCmpEqF32; break;
inst.type = ShaderInstructionType::VCmpNeqF32; case 0x0d: inst.type = ShaderInstructionType::VCmpNeqF32; break;
inst.format = ShaderInstructionFormat::SmaskVsrc0Vsrc1; case 0x84: inst.type = ShaderInstructionType::VCmpGtI32; break;
inst.dst.type = ShaderOperandType::VccLo; case 0xc2: inst.type = ShaderInstructionType::VCmpEqU32; break;
inst.dst.size = 2; case 0xc5: inst.type = ShaderInstructionType::VCmpNeU32; break;
break; case 0xd2: inst.type = ShaderInstructionType::VCmpxEqU32; break;
case 0xc2: case 0xd4: inst.type = ShaderInstructionType::VCmpxGtU32; break;
inst.type = ShaderInstructionType::VCmpEqU32; case 0xd5: inst.type = ShaderInstructionType::VCmpxNeU32; break;
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;
default: printf("%s", dst->DbgDump().C_Str()); EXIT("unknown vopc opcode: 0x%02" PRIx32 " at addr 0x%08" PRIx32 "\n", opcode, pc); 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++; size++;
} }
inst.format = ShaderInstructionFormat::SVdstSVsrc0;
switch (opcode) switch (opcode)
{ {
case 0x01: case 0x01: inst.type = ShaderInstructionType::VMovB32; break;
inst.type = ShaderInstructionType::VMovB32; case 0x06: inst.type = ShaderInstructionType::VCvtF32U32; break;
inst.format = ShaderInstructionFormat::SVdstSVsrc0; case 0x07: inst.type = ShaderInstructionType::VCvtU32F32; break;
break; case 0x11: inst.type = ShaderInstructionType::VCvtF32Ubyte0; break;
case 0x06: case 0x12: inst.type = ShaderInstructionType::VCvtF32Ubyte1; break;
inst.type = ShaderInstructionType::VCvtF32U32; case 0x13: inst.type = ShaderInstructionType::VCvtF32Ubyte2; break;
inst.format = ShaderInstructionFormat::SVdstSVsrc0; case 0x14: inst.type = ShaderInstructionType::VCvtF32Ubyte3; break;
break; case 0x2a: inst.type = ShaderInstructionType::VRcpF32; break;
case 0x07: case 0x2e: inst.type = ShaderInstructionType::VRsqF32; break;
inst.type = ShaderInstructionType::VCvtU32F32; case 0x33: inst.type = ShaderInstructionType::VSqrtF32; break;
inst.format = ShaderInstructionFormat::SVdstSVsrc0; case 0x37: inst.type = ShaderInstructionType::VNotB32; break;
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;
default: printf("%s", dst->DbgDump().C_Str()); EXIT("unknown vop1 opcode: 0x%02" PRIx32 " at addr 0x%08" PRIx32 "\n", opcode, pc); 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++; size++;
} }
inst.format = ShaderInstructionFormat::SVdstSVsrc0SVsrc1;
switch (opcode) switch (opcode)
{ {
case 0x00: case 0x00:
@@ -692,34 +789,18 @@ KYTY_SHADER_PARSER(shader_parse_vop2)
inst.src[2].size = 2; inst.src[2].size = 2;
inst.src_num = 3; inst.src_num = 3;
break; break;
case 0x04: case 0x04: inst.type = ShaderInstructionType::VSubF32; break;
inst.type = ShaderInstructionType::VSubF32; case 0x05: inst.type = ShaderInstructionType::VSubrevF32; break;
inst.format = ShaderInstructionFormat::SVdstSVsrc0SVsrc1; case 0x08: inst.type = ShaderInstructionType::VMulF32; break;
break; case 0x0b: inst.type = ShaderInstructionType::VMulU32U24; break;
case 0x05: case 0x0f: inst.type = ShaderInstructionType::VMinF32; break;
inst.type = ShaderInstructionType::VSubrevF32; case 0x10: inst.type = ShaderInstructionType::VMaxF32; break;
inst.format = ShaderInstructionFormat::SVdstSVsrc0SVsrc1; case 0x15: inst.type = ShaderInstructionType::VLshrB32; break;
break; case 0x16: inst.type = ShaderInstructionType::VLshrrevB32; break;
case 0x08: case 0x18: inst.type = ShaderInstructionType::VAshrrevI32; break;
inst.type = ShaderInstructionType::VMulF32; case 0x1a: inst.type = ShaderInstructionType::VLshlrevB32; break;
inst.format = ShaderInstructionFormat::SVdstSVsrc0SVsrc1; case 0x1b: inst.type = ShaderInstructionType::VAndB32; break;
break; case 0x1f: inst.type = ShaderInstructionType::VMacF32; 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 0x21: case 0x21:
inst.type = ShaderInstructionType::VMadakF32; inst.type = ShaderInstructionType::VMadakF32;
inst.format = ShaderInstructionFormat::VdstVsrc0Vsrc1Vsrc2; inst.format = ShaderInstructionFormat::VdstVsrc0Vsrc1Vsrc2;
@@ -729,14 +810,8 @@ KYTY_SHADER_PARSER(shader_parse_vop2)
inst.src[2].size = 0; inst.src[2].size = 0;
size++; size++;
break; break;
case 0x23: case 0x23: inst.type = ShaderInstructionType::VMbcntLoU32B32; break;
inst.type = ShaderInstructionType::VMbcntLoU32B32; case 0x24: inst.type = ShaderInstructionType::VMbcntHiU32B32; break;
inst.format = ShaderInstructionFormat::SVdstSVsrc0SVsrc1;
break;
case 0x24:
inst.type = ShaderInstructionType::VMbcntHiU32B32;
inst.format = ShaderInstructionFormat::SVdstSVsrc0SVsrc1;
break;
case 0x25: case 0x25:
inst.type = ShaderInstructionType::VAddI32; inst.type = ShaderInstructionType::VAddI32;
inst.format = ShaderInstructionFormat::VdstSdst2Vsrc0Vsrc1; inst.format = ShaderInstructionFormat::VdstSdst2Vsrc0Vsrc1;
@@ -755,10 +830,7 @@ KYTY_SHADER_PARSER(shader_parse_vop2)
inst.dst2.type = ShaderOperandType::VccLo; inst.dst2.type = ShaderOperandType::VccLo;
inst.dst2.size = 2; inst.dst2.size = 2;
break; break;
case 0x2f: case 0x2f: inst.type = ShaderInstructionType::VCvtPkrtzF16F32; break;
inst.type = ShaderInstructionType::VCvtPkrtzF16F32;
inst.format = ShaderInstructionFormat::SVdstSVsrc0SVsrc1;
break;
case 0x3e: return shader_parse_vopc(pc, src, buffer, dst); break; case 0x3e: return shader_parse_vopc(pc, src, buffer, dst); break;
case 0x3f: return shader_parse_vop1(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); 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++; size++;
} }
inst.format = ShaderInstructionFormat::VdstVsrc0Vsrc1Vsrc2;
switch (opcode) switch (opcode)
{ {
case 0x02: case 0x02:
@@ -856,6 +930,13 @@ KYTY_SHADER_PARSER(shader_parse_vop3)
inst.dst = operand_parse(vdst); inst.dst = operand_parse(vdst);
inst.dst.size = 2; inst.dst.size = 2;
break; 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: case 0xc2:
inst.type = ShaderInstructionType::VCmpEqU32; inst.type = ShaderInstructionType::VCmpEqU32;
inst.format = ShaderInstructionFormat::SmaskVsrc0Vsrc1; inst.format = ShaderInstructionFormat::SmaskVsrc0Vsrc1;
@@ -885,10 +966,12 @@ KYTY_SHADER_PARSER(shader_parse_vop3)
case 0x104: case 0x104:
inst.type = ShaderInstructionType::VSubF32; inst.type = ShaderInstructionType::VSubF32;
inst.format = ShaderInstructionFormat::SVdstSVsrc0SVsrc1; inst.format = ShaderInstructionFormat::SVdstSVsrc0SVsrc1;
inst.src_num = 2;
break; break;
case 0x108: case 0x108:
inst.type = ShaderInstructionType::VMulF32; inst.type = ShaderInstructionType::VMulF32;
inst.format = ShaderInstructionFormat::SVdstSVsrc0SVsrc1; inst.format = ShaderInstructionFormat::SVdstSVsrc0SVsrc1;
inst.src_num = 2;
break; break;
case 0x11f: case 0x11f:
inst.type = ShaderInstructionType::VMacF32; inst.type = ShaderInstructionType::VMacF32;
@@ -903,14 +986,16 @@ KYTY_SHADER_PARSER(shader_parse_vop3)
case 0x12f: case 0x12f:
inst.type = ShaderInstructionType::VCvtPkrtzF16F32; inst.type = ShaderInstructionType::VCvtPkrtzF16F32;
inst.format = ShaderInstructionFormat::SVdstSVsrc0SVsrc1; inst.format = ShaderInstructionFormat::SVdstSVsrc0SVsrc1;
inst.src_num = 2;
break; break;
case 0x141: case 0x141: inst.type = ShaderInstructionType::VMadF32; break;
inst.type = ShaderInstructionType::VMadF32; case 0x143: inst.type = ShaderInstructionType::VMadU32U24; break;
inst.format = ShaderInstructionFormat::VdstVsrc0Vsrc1Vsrc2; case 0x148: inst.type = ShaderInstructionType::VBfeU32; break;
break; case 0x15d: inst.type = ShaderInstructionType::VSadU32; break;
case 0x15d: case 0x16b:
inst.type = ShaderInstructionType::VSadU32; inst.type = ShaderInstructionType::VMulLoI32;
inst.format = ShaderInstructionFormat::VdstVsrc0Vsrc1Vsrc2; inst.format = ShaderInstructionFormat::SVdstSVsrc0SVsrc1;
inst.src_num = 2;
break; break;
default: printf("%s", dst->DbgDump().C_Str()); EXIT("unknown vop3 opcode: 0x%02" PRIx32 " at addr 0x%08" PRIx32 "\n", opcode, pc); 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 vsrc2 = (buffer[1] >> 16u) & 0xffu;
uint32_t vsrc3 = (buffer[1] >> 24u) & 0xffu; uint32_t vsrc3 = (buffer[1] >> 24u) & 0xffu;
EXIT_NOT_IMPLEMENTED(en != 0xf);
ShaderInstruction inst; ShaderInstruction inst;
inst.pc = pc; inst.pc = pc;
inst.src[0] = operand_parse(vsrc0 + 256); inst.src[0] = operand_parse(vsrc0 + 256);
@@ -952,27 +1035,39 @@ KYTY_SHADER_PARSER(shader_parse_exp)
switch (target) switch (target)
{ {
case 0x00: 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.format = ShaderInstructionFormat::Mrt0Vsrc0Vsrc1ComprVmDone;
inst.src_num = 2; 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; inst.format = ShaderInstructionFormat::Mrt0Vsrc0Vsrc1Vsrc2Vsrc3VmDone;
}; };
break; break;
case 0x0c: case 0x0c:
if (done != 0) if (done != 0 && en == 0xf)
{ {
inst.format = ShaderInstructionFormat::Pos0Vsrc0Vsrc1Vsrc2Vsrc3Done; inst.format = ShaderInstructionFormat::Pos0Vsrc0Vsrc1Vsrc2Vsrc3Done;
}; };
break; 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 0x20: inst.format = ShaderInstructionFormat::Param0Vsrc0Vsrc1Vsrc2Vsrc3; break;
case 0x21: inst.format = ShaderInstructionFormat::Param1Vsrc0Vsrc1Vsrc2Vsrc3; break; case 0x21: inst.format = ShaderInstructionFormat::Param1Vsrc0Vsrc1Vsrc2Vsrc3; break;
case 0x22: inst.format = ShaderInstructionFormat::Param2Vsrc0Vsrc1Vsrc2Vsrc3; break; case 0x22: inst.format = ShaderInstructionFormat::Param2Vsrc0Vsrc1Vsrc2Vsrc3; break;
case 0x23: inst.format = ShaderInstructionFormat::Param3Vsrc0Vsrc1Vsrc2Vsrc3; break; case 0x23: inst.format = ShaderInstructionFormat::Param3Vsrc0Vsrc1Vsrc2Vsrc3; break;
default: break; default: break;
} }
}
if (inst.format == ShaderInstructionFormat::Unknown) if (inst.format == ShaderInstructionFormat::Unknown)
{ {
@@ -1039,6 +1134,12 @@ KYTY_SHADER_PARSER(shader_parse_smrd)
inst.format = ShaderInstructionFormat::SdstSvSoffset; inst.format = ShaderInstructionFormat::SdstSvSoffset;
inst.src[0].size = 4; inst.src[0].size = 4;
break; break;
case 0x09:
inst.type = ShaderInstructionType::SBufferLoadDwordx2;
inst.format = ShaderInstructionFormat::Sdst2SvSoffset;
inst.src[0].size = 4;
inst.dst.size = 2;
break;
case 0x0a: case 0x0a:
inst.type = ShaderInstructionType::SBufferLoadDwordx4; inst.type = ShaderInstructionType::SBufferLoadDwordx4;
inst.format = ShaderInstructionFormat::Sdst4SvSoffset; inst.format = ShaderInstructionFormat::Sdst4SvSoffset;
@@ -1293,7 +1394,7 @@ KYTY_SHADER_PARSER(shader_parse_mtbuf)
uint32_t vaddr = (buffer[1] >> 0u) & 0xffu; uint32_t vaddr = (buffer[1] >> 0u) & 0xffu;
EXIT_NOT_IMPLEMENTED(idxen == 0); EXIT_NOT_IMPLEMENTED(idxen == 0);
EXIT_NOT_IMPLEMENTED(offen == 1); // EXIT_NOT_IMPLEMENTED(offen == 1);
EXIT_NOT_IMPLEMENTED(offset != 0); EXIT_NOT_IMPLEMENTED(offset != 0);
EXIT_NOT_IMPLEMENTED(glc == 1); EXIT_NOT_IMPLEMENTED(glc == 1);
EXIT_NOT_IMPLEMENTED(slc == 1); EXIT_NOT_IMPLEMENTED(slc == 1);
@@ -1317,12 +1418,15 @@ KYTY_SHADER_PARSER(shader_parse_mtbuf)
size++; size++;
} }
inst.src[1].size = 4;
switch (opcode) // NOLINT switch (opcode) // NOLINT
{ {
case 0x03: case 0x03:
inst.type = ShaderInstructionType::TBufferLoadFormatXyzw; inst.type = ShaderInstructionType::TBufferLoadFormatXyzw;
inst.format = ShaderInstructionFormat::Vdata4VaddrSvSoffsIdxenFloat4; inst.format = (offen == 1 ? ShaderInstructionFormat::Vdata4Vaddr2SvSoffsOffenIdxenFloat4
inst.src[1].size = 4; : ShaderInstructionFormat::Vdata4VaddrSvSoffsIdxenFloat4);
inst.src[0].size += static_cast<int>(offen);
inst.dst.size = 4; inst.dst.size = 4;
break; break;
default: printf("%s", dst->DbgDump().C_Str()); EXIT("unknown mtbuf opcode: 0x%02" PRIx32 " at addr 0x%08" PRIx32 "\n", opcode, pc); 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); 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)) (instruction == 0xBE802000 && type == ShaderType::Fetch))
{ {
break; break;
@@ -1512,23 +1617,23 @@ static void bi_print(const char* func, const ShaderBinaryInfo& bi)
{ {
printf("%s\n", func); printf("%s\n", func);
printf("\t m_signature = %.7s\n", bi.signature); printf("\t signature = %.7s\n", bi.signature);
printf("\t m_version = 0x%02" PRIx8 "\n", bi.version); printf("\t 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 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 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 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 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 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 chunk_usage_base_offset_dw = 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 num_input_usage_slots = 0x%02" PRIx8 "\n", bi.num_input_usage_slots);
printf("\t m_isSrt = 0x%02" PRIx8 "\n", bi.is_srt); printf("\t is_srt = 0x%02" PRIx8 "\n", bi.is_srt);
printf("\t m_isSrtUsedInfoValid = 0x%02" PRIx8 "\n", bi.is_srt_used_info_valid); printf("\t is_srt_used_info_valid = 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 is_extended_usage_info = 0x%02" PRIx8 "\n", bi.is_extended_usage_info);
printf("\t m_reserved2 = 0x%02" PRIx8 "\n", bi.reserved2); printf("\t reserved2 = 0x%02" PRIx8 "\n", bi.reserved2);
printf("\t m_reserved3 = 0x%02" PRIx8 "\n", bi.reserved3); printf("\t reserved3 = 0x%02" PRIx8 "\n", bi.reserved3);
printf("\t m_shaderHash0 = 0x%08" PRIx32 "\n", bi.hash0); printf("\t hash0 = 0x%08" PRIx32 "\n", bi.hash0);
printf("\t m_shaderHash1 = 0x%08" PRIx32 "\n", bi.hash1); printf("\t hash1 = 0x%08" PRIx32 "\n", bi.hash1);
printf("\t m_crc32 = 0x%08" PRIx32 "\n", bi.crc32); printf("\t crc32 = 0x%08" PRIx32 "\n", bi.crc32);
} }
static void vs_check(const VsStageRegisters& vs) 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(ps_info == nullptr);
EXIT_IF(regs == 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_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; ps_info->ps_pixel_kill_enable = regs->ps_regs.shader_kill_enable;
File diff suppressed because it is too large Load Diff