Files
graham wihlidal 1ea8fe45eb Fixed RDNA2 disassembler to correctly handle v_madak_f32 and v_madmk_f32 advancing with a trailing literal
[FYI] rune.stubbe, brian.karis, john.huelin, jian.ru, jamie.hayes



#[robomerge][bot5] -FNMain
Fixed case on consoles where Nanite export depth would not fully clear all non-Nanite pixels, leaving corrupt rendering in certain cases (like disabling the transient allocator, or running with -rdgimmediate).

#rb yuriy.odonnell
#[fyi] brian.karis, rune.stubbe, jamie.hayes, zach.bethel
#jira UE-202941, UE-205770

Fixed some additional ISA issues by adding v_fmaak_f32, v_fmamk_f32, v_fmamk_f16, and v_fmaak_f16 to the trailing literal check

[FYI] rune.stubbe, brian.karis, jian.ru, jamie.hayes, luke.thatcher



#[robomerge][bot5] -FNMain
Add NANITE_TESSELLATION permutation to Nanite SW rasterizer shaders to fix issues where we were assuming that if displacement is connected in the material shader parameters, that displacement would not be disabled in the final compiled material.

#rb graham.wihlidal
#[fyi] rune.stubbe, brian.karis
Fix for flickering tessellated triangles with corrupt values in raster bin meta between tessellated cluster and patch raster.

#rb jamie.hayes
#[fyi] rune.stubbe, brian.karis

#changelist validated
#virtualized

#ushell-cherrypick of 31148557 by graham.wihlidal
#ushell-cherrypick of 31154834 by graham.wihlidal
#ushell-cherrypick of 31164583 by graham.wihlidal
#ushell-cherrypick of 31182678 by jamie.hayes
#ushell-cherrypick of 31228365 by graham.wihlidal

[CL 31281009 by graham wihlidal in 5.4 branch]
2024-02-07 19:58:41 -05:00

790 lines
18 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "ISAParser/ISAParser.h"
#include "RDNA1_ISA.h"
#include "RDNA2_ISA.h"
struct FDebugParserRDNA1
{
uint32 AdjustAdvance(EInstructionType InstructionType, const uint32* InstPtr)
{
uint32 AdvanceAmount = 0u;
if (InstructionType == EInstructionType::VOP2)
{
const FInstVOP2& Inst = *reinterpret_cast<const FInstVOP2*>(InstPtr);
const RDNA1::EVOP2Ops Op = (const RDNA1::EVOP2Ops)Inst.OP;
// These instructions always have a literal constant that follows
if (RDNA1::HasTrailingLiteral(Op))
{
AdvanceAmount++;
}
}
return AdvanceAmount;
}
bool ParseSOP1(const FInstSOP1& Inst)
{
RDNA1::PrintSOP1(Inst);
return true;
}
bool ParseSOP2(const FInstSOP2& Inst)
{
RDNA1::PrintSOP2(Inst);
return true;
}
bool ParseSOPP(const FInstSOPP& Inst)
{
RDNA1::PrintSOPP(Inst);
const RDNA1::ESOPPOps Op = (const RDNA1::ESOPPOps)Inst.OP;
return (Op != RDNA1::ESOPPOps::s_endpgm);
}
bool ParseSOPK(const FInstSOPK& Inst)
{
RDNA1::PrintSOPK(Inst);
return true;
}
bool ParseSOPC(const FInstSOPC& Inst)
{
RDNA1::PrintSOPC(Inst);
return true;
}
bool ParseSMEM(const FInstSMEM& Inst)
{
RDNA1::PrintSMEM(Inst);
return true;
}
bool ParseVOP1(const FInstVOP1& Inst)
{
RDNA1::PrintVOP1(Inst);
return true;
}
bool ParseVOP1_DPP16(const FInstVOP1& Inst, const FDPP16& DPP16)
{
RDNA1::PrintVOP1(Inst);
return true;
}
bool ParseVOP2(const FInstVOP2& Inst)
{
RDNA1::PrintVOP2(Inst);
return true;
}
bool ParseVOP2_DPP16(const FInstVOP2& Inst, const FDPP16& DPP16)
{
RDNA1::PrintVOP2(Inst);
if (DPP16.DPPCTRL <= 0x0FF)
{
// DPP_QUAD_PERM
}
return true;
}
bool ParseVOP3(const FInstVOP3& Inst)
{
if (RDNA1::IsVOP3BEncoding((RDNA1::EVOP3ABOps)Inst.Encoding.VOP3B.OP))
{
RDNA1::PrintVOP3B(Inst.Encoding.VOP3B);
}
else
{
RDNA1::PrintVOP3A(Inst.Encoding.VOP3A);
}
return true;
}
bool ParseVOPC(const FInstVOPC& Inst)
{
RDNA1::PrintVOPC(Inst);
return true;
}
bool ParseVOPC_DPP16(const FInstVOPC& Inst, const FDPP16& DPP16)
{
RDNA1::PrintVOPC(Inst);
return true;
}
bool ParseVOP3P(const FInstVOP3P& Inst)
{
RDNA1::PrintVOP3P(Inst);
return true;
}
bool ParseVINTERP(const FInstVINTERP& Inst)
{
RDNA1::PrintVINTERP(Inst);
return true;
}
bool ParseLDSGDS(const FInstLDSGDS& Inst)
{
RDNA1::PrintLDSGDS(Inst);
return true;
}
bool ParseMUBUF(const FInstMUBUF& Inst)
{
RDNA1::PrintMUBUF(Inst);
return true;
}
bool ParseMTBUF(const FInstMTBUF& Inst)
{
RDNA1::PrintMTBUF(Inst);
return true;
}
bool ParseEXPORT(const FInstEXPORT& Inst)
{
RDNA1::PrintEXPORT(Inst);
return true;
}
bool ParseFSG(const FInstFSG& Inst)
{
RDNA1::PrintFSG(Inst);
return true;
}
bool ParseMIMG(const FInstMIMG& Inst)
{
RDNA1::PrintMIMG(Inst);
return true;
}
};
struct FDebugParserRDNA2
{
uint32 AdjustAdvance(EInstructionType InstructionType, const uint32* InstPtr)
{
uint32 AdvanceAmount = 0u;
if (InstructionType == EInstructionType::VOP2)
{
const FInstVOP2& Inst = *reinterpret_cast<const FInstVOP2*>(InstPtr);
const RDNA2::EVOP2Ops Op = (const RDNA2::EVOP2Ops)Inst.OP;
// These instructions always have a literal constant that follows
if (RDNA2::HasTrailingLiteral(Op))
{
AdvanceAmount++;
}
}
return AdvanceAmount;
}
bool ParseSOP1(const FInstSOP1& Inst)
{
RDNA2::PrintSOP1(Inst);
return true;
}
bool ParseSOP2(const FInstSOP2& Inst)
{
RDNA2::PrintSOP2(Inst);
return true;
}
bool ParseSOPP(const FInstSOPP& Inst)
{
RDNA2::PrintSOPP(Inst);
const RDNA2::ESOPPOps Op = (const RDNA2::ESOPPOps)Inst.OP;
return (Op != RDNA2::ESOPPOps::s_endpgm);
}
bool ParseSOPK(const FInstSOPK& Inst)
{
RDNA2::PrintSOPK(Inst);
return true;
}
bool ParseSOPC(const FInstSOPC& Inst)
{
RDNA2::PrintSOPC(Inst);
return true;
}
bool ParseSMEM(const FInstSMEM& Inst)
{
RDNA2::PrintSMEM(Inst);
return true;
}
bool ParseVOP1(const FInstVOP1& Inst)
{
RDNA2::PrintVOP1(Inst);
return true;
}
bool ParseVOP1_DPP16(const FInstVOP1& Inst, const FDPP16& DPP16)
{
RDNA2::PrintVOP1(Inst);
return true;
}
bool ParseVOP2(const FInstVOP2& Inst)
{
RDNA2::PrintVOP2(Inst);
return true;
}
bool ParseVOP2_DPP16(const FInstVOP2& Inst, const FDPP16& DPP16)
{
RDNA2::PrintVOP2(Inst);
if (DPP16.DPPCTRL <= 0x0FF)
{
// DPP_QUAD_PERM
}
return true;
}
bool ParseVOP3(const FInstVOP3& Inst)
{
if (RDNA2::IsVOP3BEncoding((RDNA2::EVOP3ABOps)Inst.Encoding.VOP3B.OP))
{
RDNA2::PrintVOP3B(Inst.Encoding.VOP3B);
}
else
{
RDNA2::PrintVOP3A(Inst.Encoding.VOP3A);
}
return true;
}
bool ParseVOPC(const FInstVOPC& Inst)
{
RDNA2::PrintVOPC(Inst);
return true;
}
bool ParseVOPC_DPP16(const FInstVOPC& Inst, const FDPP16& DPP16)
{
RDNA2::PrintVOPC(Inst);
return true;
}
bool ParseVOP3P(const FInstVOP3P& Inst)
{
RDNA2::PrintVOP3P(Inst);
return true;
}
bool ParseVINTERP(const FInstVINTERP& Inst)
{
RDNA2::PrintVINTERP(Inst);
return true;
}
bool ParseLDSGDS(const FInstLDSGDS& Inst)
{
RDNA2::PrintLDSGDS(Inst);
return true;
}
bool ParseMUBUF(const FInstMUBUF& Inst)
{
RDNA2::PrintMUBUF(Inst);
return true;
}
bool ParseMTBUF(const FInstMTBUF& Inst)
{
RDNA2::PrintMTBUF(Inst);
return true;
}
bool ParseEXPORT(const FInstEXPORT& Inst)
{
RDNA2::PrintEXPORT(Inst);
return true;
}
bool ParseFSG(const FInstFSG& Inst)
{
RDNA2::PrintFSG(Inst);
return true;
}
bool ParseMIMG(const FInstMIMG& Inst)
{
RDNA2::PrintMIMG(Inst);
return true;
}
};
struct FQuadModeParserRDNA1
{
bool bQuadMode = false;
bool bDebug = false;
uint32 AdjustAdvance(EInstructionType InstructionType, const uint32* InstPtr)
{
uint32 AdvanceAmount = 0u;
if (InstructionType == EInstructionType::VOP2)
{
const FInstVOP2& Inst = *reinterpret_cast<const FInstVOP2*>(InstPtr);
const RDNA1::EVOP2Ops Op = (const RDNA1::EVOP2Ops)Inst.OP;
// These instructions always have a literal constant that follows
if (RDNA1::HasTrailingLiteral(Op))
{
AdvanceAmount++;
}
}
return AdvanceAmount;
}
inline bool KeepParsing() const
{
// If we detected the need for quad mode, and are not debugging, stop parsing early
return !bQuadMode || bDebug;
}
bool IsDPPQuadPerm(const FDPP16& DPP16)
{
return (DPP16.DPPCTRL <= 0x0FF); // DPP_QUAD_PERM
}
bool ParseSOPP(const FInstSOPP& Inst)
{
const RDNA1::ESOPPOps Op = (const RDNA1::ESOPPOps)Inst.OP;
return (Op != RDNA1::ESOPPOps::s_endpgm) && KeepParsing();
}
bool ParseSOP1(const FInstSOP1& Inst) { return KeepParsing(); }
bool ParseSOP2(const FInstSOP2& Inst) { return KeepParsing(); }
bool ParseSOPK(const FInstSOPK& Inst) { return KeepParsing(); }
bool ParseSOPC(const FInstSOPC& Inst) { return KeepParsing(); }
bool ParseSMEM(const FInstSMEM& Inst) { return KeepParsing(); }
bool ParseVOP1(const FInstVOP1& Inst) { return KeepParsing(); }
bool ParseVOP2(const FInstVOP2& Inst) { return KeepParsing(); }
bool ParseVOP3(const FInstVOP3& Inst) { return KeepParsing(); }
bool ParseVOPC(const FInstVOPC& Inst) { return KeepParsing(); }
bool ParseVOP3P(const FInstVOP3P& Inst) { return KeepParsing(); }
bool ParseVINTERP(const FInstVINTERP& Inst) { return KeepParsing(); }
bool ParseLDSGDS(const FInstLDSGDS& Inst) { return KeepParsing(); }
bool ParseMUBUF(const FInstMUBUF& Inst) { return KeepParsing(); }
bool ParseMTBUF(const FInstMTBUF& Inst) { return KeepParsing(); }
bool ParseEXPORT(const FInstEXPORT& Inst) { return KeepParsing(); }
bool ParseFSG(const FInstFSG& Inst) { return KeepParsing(); }
bool ParseVOP1_DPP16(const FInstVOP1& Inst, const FDPP16& DPP16)
{
if (IsDPPQuadPerm(DPP16))
{
bQuadMode = true;
if (bDebug)
{
RDNA1::PrintVOP1(Inst);
}
}
return KeepParsing();
}
bool ParseVOP2_DPP16(const FInstVOP2& Inst, const FDPP16& DPP16)
{
if (IsDPPQuadPerm(DPP16))
{
bQuadMode = true;
if (bDebug)
{
RDNA1::PrintVOP2(Inst);
}
}
return KeepParsing();
}
bool ParseVOPC_DPP16(const FInstVOPC& Inst, const FDPP16& DPP16)
{
if (IsDPPQuadPerm(DPP16))
{
bQuadMode = true;
if (bDebug)
{
RDNA1::PrintVOPC(Inst);
}
}
return KeepParsing();
}
bool ParseMIMG(const FInstMIMG& Inst)
{
const RDNA1::EMIMGOps Op = (const RDNA1::EMIMGOps)Inst.OP;
switch (Op)
{
case RDNA1::EMIMGOps::image_sample:
case RDNA1::EMIMGOps::image_sample_cl:
case RDNA1::EMIMGOps::image_sample_b:
case RDNA1::EMIMGOps::image_sample_b_cl:
case RDNA1::EMIMGOps::image_sample_c:
case RDNA1::EMIMGOps::image_sample_c_cl:
case RDNA1::EMIMGOps::image_sample_c_b:
case RDNA1::EMIMGOps::image_sample_c_b_cl:
case RDNA1::EMIMGOps::image_sample_o:
case RDNA1::EMIMGOps::image_sample_cl_o:
case RDNA1::EMIMGOps::image_sample_b_o:
case RDNA1::EMIMGOps::image_sample_b_cl_o:
case RDNA1::EMIMGOps::image_sample_c_o:
case RDNA1::EMIMGOps::image_sample_c_cl_o:
case RDNA1::EMIMGOps::image_sample_c_b_o:
case RDNA1::EMIMGOps::image_sample_c_b_cl_o:
case RDNA1::EMIMGOps::image_gather4:
case RDNA1::EMIMGOps::image_gather4_cl:
case RDNA1::EMIMGOps::image_gather4_b:
case RDNA1::EMIMGOps::image_gather4_b_cl:
case RDNA1::EMIMGOps::image_gather4_c:
case RDNA1::EMIMGOps::image_gather4_c_cl:
case RDNA1::EMIMGOps::image_gather4_c_b:
case RDNA1::EMIMGOps::image_gather4_c_b_cl:
case RDNA1::EMIMGOps::image_gather4_o:
case RDNA1::EMIMGOps::image_gather4_cl_o:
case RDNA1::EMIMGOps::image_gather4_b_o:
case RDNA1::EMIMGOps::image_gather4_b_cl_o:
case RDNA1::EMIMGOps::image_gather4_c_o:
case RDNA1::EMIMGOps::image_gather4_c_cl_o:
case RDNA1::EMIMGOps::image_gather4_c_b_o:
case RDNA1::EMIMGOps::image_gather4_c_b_cl_o:
case RDNA1::EMIMGOps::image_get_lod:
case RDNA1::EMIMGOps::image_gather4h:
{
if (bDebug)
{
RDNA1::PrintMIMG(Inst);
}
bQuadMode = true;
break;
}
default:
break;
}
return KeepParsing();
}
};
struct FQuadModeParserRDNA2
{
bool bQuadMode = false;
bool bDebug = false;
uint32 AdjustAdvance(EInstructionType InstructionType, const uint32* InstPtr)
{
uint32 AdvanceAmount = 0u;
if (InstructionType == EInstructionType::VOP2)
{
const FInstVOP2& Inst = *reinterpret_cast<const FInstVOP2*>(InstPtr);
const RDNA2::EVOP2Ops Op = (const RDNA2::EVOP2Ops)Inst.OP;
// These instructions always have a literal constant that follows
if (RDNA2::HasTrailingLiteral(Op))
{
AdvanceAmount++;
}
}
return AdvanceAmount;
}
inline bool KeepParsing() const
{
// If we detected the need for quad mode, and are not debugging, stop parsing early
return !bQuadMode || bDebug;
}
bool IsDPPQuadPerm(const FDPP16& DPP16)
{
return (DPP16.DPPCTRL <= 0x0FF); // DPP_QUAD_PERM
}
bool ParseSOPP(const FInstSOPP& Inst)
{
const RDNA2::ESOPPOps Op = (const RDNA2::ESOPPOps)Inst.OP;
return (Op != RDNA2::ESOPPOps::s_endpgm) && KeepParsing();
}
bool ParseSOP1(const FInstSOP1& Inst) { return KeepParsing(); }
bool ParseSOP2(const FInstSOP2& Inst) { return KeepParsing(); }
bool ParseSOPK(const FInstSOPK& Inst) { return KeepParsing(); }
bool ParseSOPC(const FInstSOPC& Inst) { return KeepParsing(); }
bool ParseSMEM(const FInstSMEM& Inst) { return KeepParsing(); }
bool ParseVOP1(const FInstVOP1& Inst) { return KeepParsing(); }
bool ParseVOP2(const FInstVOP2& Inst) { return KeepParsing(); }
bool ParseVOP3(const FInstVOP3& Inst) { return KeepParsing(); }
bool ParseVOPC(const FInstVOPC& Inst) { return KeepParsing(); }
bool ParseVOP3P(const FInstVOP3P& Inst) { return KeepParsing(); }
bool ParseVINTERP(const FInstVINTERP& Inst) { return KeepParsing(); }
bool ParseLDSGDS(const FInstLDSGDS& Inst) { return KeepParsing(); }
bool ParseMUBUF(const FInstMUBUF& Inst) { return KeepParsing(); }
bool ParseMTBUF(const FInstMTBUF& Inst) { return KeepParsing(); }
bool ParseEXPORT(const FInstEXPORT& Inst) { return KeepParsing(); }
bool ParseFSG(const FInstFSG& Inst) { return KeepParsing(); }
bool ParseVOP1_DPP16(const FInstVOP1& Inst, const FDPP16& DPP16)
{
if (IsDPPQuadPerm(DPP16))
{
bQuadMode = true;
if (bDebug)
{
RDNA2::PrintVOP1(Inst);
}
}
return KeepParsing();
}
bool ParseVOP2_DPP16(const FInstVOP2& Inst, const FDPP16& DPP16)
{
if (IsDPPQuadPerm(DPP16))
{
bQuadMode = true;
if (bDebug)
{
RDNA2::PrintVOP2(Inst);
}
}
return KeepParsing();
}
bool ParseVOPC_DPP16(const FInstVOPC& Inst, const FDPP16& DPP16)
{
if (IsDPPQuadPerm(DPP16))
{
bQuadMode = true;
if (bDebug)
{
RDNA2::PrintVOPC(Inst);
}
}
return KeepParsing();
}
bool ParseMIMG(const FInstMIMG& Inst)
{
const RDNA2::EMIMGOps Op = (const RDNA2::EMIMGOps)Inst.OP;
switch (Op)
{
case RDNA2::EMIMGOps::image_sample:
case RDNA2::EMIMGOps::image_sample_cl:
case RDNA2::EMIMGOps::image_sample_b:
case RDNA2::EMIMGOps::image_sample_b_cl:
case RDNA2::EMIMGOps::image_sample_c:
case RDNA2::EMIMGOps::image_sample_c_cl:
case RDNA2::EMIMGOps::image_sample_c_b:
case RDNA2::EMIMGOps::image_sample_c_b_cl:
case RDNA2::EMIMGOps::image_sample_o:
case RDNA2::EMIMGOps::image_sample_cl_o:
case RDNA2::EMIMGOps::image_sample_b_o:
case RDNA2::EMIMGOps::image_sample_b_cl_o:
case RDNA2::EMIMGOps::image_sample_c_o:
case RDNA2::EMIMGOps::image_sample_c_cl_o:
case RDNA2::EMIMGOps::image_sample_c_b_o:
case RDNA2::EMIMGOps::image_sample_c_b_cl_o:
case RDNA2::EMIMGOps::image_gather4:
case RDNA2::EMIMGOps::image_gather4_cl:
case RDNA2::EMIMGOps::image_gather4_b:
case RDNA2::EMIMGOps::image_gather4_b_cl:
case RDNA2::EMIMGOps::image_gather4_c:
case RDNA2::EMIMGOps::image_gather4_c_cl:
case RDNA2::EMIMGOps::image_gather4_c_b:
case RDNA2::EMIMGOps::image_gather4_c_b_cl:
case RDNA2::EMIMGOps::image_gather4_o:
case RDNA2::EMIMGOps::image_gather4_cl_o:
case RDNA2::EMIMGOps::image_gather4_b_o:
case RDNA2::EMIMGOps::image_gather4_b_cl_o:
case RDNA2::EMIMGOps::image_gather4_c_o:
case RDNA2::EMIMGOps::image_gather4_c_cl_o:
case RDNA2::EMIMGOps::image_gather4_c_b_o:
case RDNA2::EMIMGOps::image_gather4_c_b_cl_o:
case RDNA2::EMIMGOps::image_get_lod:
case RDNA2::EMIMGOps::image_gather4h:
case RDNA2::EMIMGOps::image_gather4h_pck:
case RDNA2::EMIMGOps::image_gather8h_pck:
{
if (bDebug)
{
RDNA2::PrintMIMG(Inst);
}
bQuadMode = true;
break;
}
default:
break;
}
return KeepParsing();
}
};
template <class PARSER>
bool PerformParsing(PARSER& Parser, const uint32* ReadPtr, const uint32* EndPtr)
{
bool bSuccess = true;
bool bParsing = true;
while (ReadPtr < EndPtr && bParsing)
{
uint32_t AdvanceAmount = uint32_t(EndPtr - ReadPtr);
EInstructionType InstructionType = DecodeInstructionType(ReadPtr, AdvanceAmount);
AdvanceAmount += Parser.AdjustAdvance(InstructionType, ReadPtr);
if (InstructionType == EInstructionType::UNKNOWN)
{
//UE_LOG(LogTemp, Error, TEXT("Failed ISA Parse - Unknown Instruction"));
bSuccess = false;
break;
}
else if (ReadPtr + AdvanceAmount >= EndPtr)
{
//UE_LOG(LogTemp, Error, TEXT("Failed ISA Parse - Overfetch"));
bSuccess = false;
break;
}
else if (InstructionType == EInstructionType::VOP1)
{
const FInstVOP1& Inst = *reinterpret_cast<const FInstVOP1*>(ReadPtr);
if (Inst.SRC0 == Operand_DPP16)
{
const FDPP16& DPP16 = *reinterpret_cast<const FDPP16*>(ReadPtr + 1);
bParsing = Parser.ParseVOP1_DPP16(Inst, DPP16);
}
else
{
bParsing = Parser.ParseVOP1(Inst);
}
}
else if (InstructionType == EInstructionType::VOP2)
{
const FInstVOP2& Inst = *reinterpret_cast<const FInstVOP2*>(ReadPtr);
if (Inst.SRC0 == Operand_DPP16)
{
const FDPP16& DPP16 = *reinterpret_cast<const FDPP16*>(ReadPtr + GetAdvanceAmount(EInstructionType::VOP2));
bParsing = Parser.ParseVOP2_DPP16(Inst, DPP16);
}
else
{
bParsing = Parser.ParseVOP2(Inst);
}
}
else if (InstructionType == EInstructionType::VOPC)
{
const FInstVOPC& Inst = *reinterpret_cast<const FInstVOPC*>(ReadPtr);
if (Inst.SRC0 == Operand_DPP16)
{
const FDPP16& DPP16 = *reinterpret_cast<const FDPP16*>(ReadPtr + 1);
bParsing = Parser.ParseVOPC_DPP16(Inst, DPP16);
}
else
{
bParsing = Parser.ParseVOPC(Inst);
}
}
#define PARSE_MICROCODE_FORMAT(FORMAT) \
else if (InstructionType == EInstructionType::FORMAT) \
{ \
bParsing = Parser.Parse##FORMAT(*reinterpret_cast<const FInst##FORMAT*>(ReadPtr)); \
}
PARSE_MICROCODE_FORMAT(SOP1)
PARSE_MICROCODE_FORMAT(SOP2)
PARSE_MICROCODE_FORMAT(SOPP)
PARSE_MICROCODE_FORMAT(SOPK)
PARSE_MICROCODE_FORMAT(SOPC)
PARSE_MICROCODE_FORMAT(SMEM)
PARSE_MICROCODE_FORMAT(VOP3)
PARSE_MICROCODE_FORMAT(VOP3P)
PARSE_MICROCODE_FORMAT(VINTERP)
PARSE_MICROCODE_FORMAT(LDSGDS)
PARSE_MICROCODE_FORMAT(MUBUF)
PARSE_MICROCODE_FORMAT(MTBUF)
PARSE_MICROCODE_FORMAT(EXPORT)
PARSE_MICROCODE_FORMAT(FSG)
PARSE_MICROCODE_FORMAT(MIMG)
#undef PARSE_MICROCODE_FORMAT
ReadPtr += AdvanceAmount;
}
return bSuccess;
}
#define DEBUG_DUMP_FAILURES 0
bool ISAParser::HasDerivativeOps(bool& bHasDerivativeOps, const char* Code, uint32 CodeLength, EInstructionSet InstructionSet)
{
const uint32* ReadPtr = reinterpret_cast<const uint32*>(Code);
const uint32* EndPtr = reinterpret_cast<const uint32*>(Code + CodeLength);
// Safe default, any error and behavior is unchanged
bHasDerivativeOps = true;
if (InstructionSet == EInstructionSet::RDNA1)
{
FQuadModeParserRDNA1 Parser;
if (PerformParsing(Parser, ReadPtr, EndPtr))
{
bHasDerivativeOps = Parser.bQuadMode;
}
else
{
#if DEBUG_DUMP_FAILURES
FDebugParserRDNA1 PrintParser;
PerformParsing(PrintParser, ReadPtr, EndPtr);
#endif
return false;
}
}
else if (InstructionSet == EInstructionSet::RDNA2)
{
FQuadModeParserRDNA2 Parser;
if (PerformParsing(Parser, ReadPtr, EndPtr))
{
bHasDerivativeOps = Parser.bQuadMode;
}
else
{
#if DEBUG_DUMP_FAILURES
FDebugParserRDNA2 PrintParser;
PerformParsing(PrintParser, ReadPtr, EndPtr);
#endif
return false;
}
}
else
{
checkNoEntry();
return false;
}
return true;
}