mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 02:47:02 +02:00
shader: port 64-bit ALU and atomic opcodes
This commit is contained in:
@@ -244,7 +244,8 @@ Emitter::SpirvRequirements Emitter::AnalyzeProgramRequirements(const IR::Program
|
||||
if (kind != IR::ResourceKind::Lds && kind != IR::ResourceKind::Gds) {
|
||||
Fail(program, "shared operation has invalid resource kind");
|
||||
}
|
||||
if (inst.GetOpcode() == IR::ValueOpcode::SharedAtomicOr64) {
|
||||
if (shared_access == IR::SharedAccess::Atomic &&
|
||||
IR::SharedComponentCount(inst.GetOpcode()) == 2u) {
|
||||
if (kind != IR::ResourceKind::Lds || program.stage != ShaderType::Compute) {
|
||||
Fail(program, "64-bit shared atomics require compute LDS");
|
||||
}
|
||||
|
||||
@@ -444,6 +444,18 @@ uint32_t EmitUGreaterThan64(EmitterState& state, uint32_t arg0, uint32_t arg1) {
|
||||
return CompareOrdered64(state, arg0, arg1, spv::OpUGreaterThan, spv::OpUGreaterThan);
|
||||
}
|
||||
|
||||
uint32_t EmitSLessThanEqual64(EmitterState& state, uint32_t arg0, uint32_t arg1) {
|
||||
return CompareOrdered64(state, arg0, arg1, spv::OpSLessThan, spv::OpULessThanEqual);
|
||||
}
|
||||
|
||||
uint32_t EmitULessThanEqual64(EmitterState& state, uint32_t arg0, uint32_t arg1) {
|
||||
return CompareOrdered64(state, arg0, arg1, spv::OpULessThan, spv::OpULessThanEqual);
|
||||
}
|
||||
|
||||
uint32_t EmitUGreaterThanEqual64(EmitterState& state, uint32_t arg0, uint32_t arg1) {
|
||||
return CompareOrdered64(state, arg0, arg1, spv::OpUGreaterThan, spv::OpUGreaterThanEqual);
|
||||
}
|
||||
|
||||
uint32_t EmitFPIsNan32(EmitterState& state, uint32_t arg0) {
|
||||
return EmitNative<spv::OpFUnordNotEqual, IR::Type::U1>(state, arg0, arg0);
|
||||
}
|
||||
|
||||
@@ -543,7 +543,9 @@ spv::Op ImageAtomicOpcode(IR::ValueOpcode opcode) {
|
||||
switch (opcode) {
|
||||
case IR::ValueOpcode::ImageAtomicSwap32: return spv::OpAtomicExchange;
|
||||
case IR::ValueOpcode::ImageAtomicIAdd32: return spv::OpAtomicIAdd;
|
||||
case IR::ValueOpcode::ImageAtomicSMin32: return spv::OpAtomicSMin;
|
||||
case IR::ValueOpcode::ImageAtomicUMin32: return spv::OpAtomicUMin;
|
||||
case IR::ValueOpcode::ImageAtomicSMax32: return spv::OpAtomicSMax;
|
||||
case IR::ValueOpcode::ImageAtomicUMax32: return spv::OpAtomicUMax;
|
||||
case IR::ValueOpcode::ImageAtomicAnd32: return spv::OpAtomicAnd;
|
||||
case IR::ValueOpcode::ImageAtomicOr32: return spv::OpAtomicOr;
|
||||
|
||||
@@ -111,6 +111,9 @@ uint32_t EmitIEqual64(EmitterState& state, uint32_t arg0, uint32_t arg1);
|
||||
uint32_t EmitINotEqual64(EmitterState& state, uint32_t arg0, uint32_t arg1);
|
||||
uint32_t EmitULessThan64(EmitterState& state, uint32_t arg0, uint32_t arg1);
|
||||
uint32_t EmitSLessThan64(EmitterState& state, uint32_t arg0, uint32_t arg1);
|
||||
uint32_t EmitSLessThanEqual64(EmitterState& state, uint32_t arg0, uint32_t arg1);
|
||||
uint32_t EmitULessThanEqual64(EmitterState& state, uint32_t arg0, uint32_t arg1);
|
||||
uint32_t EmitUGreaterThanEqual64(EmitterState& state, uint32_t arg0, uint32_t arg1);
|
||||
uint32_t EmitUGreaterThan64(EmitterState& state, uint32_t arg0, uint32_t arg1);
|
||||
EMIT_NATIVE(LogicalOr, OpLogicalOr, U1, uint32_t, uint32_t)
|
||||
EMIT_NATIVE(LogicalAnd, OpLogicalAnd, U1, uint32_t, uint32_t)
|
||||
@@ -134,6 +137,8 @@ uint32_t EmitFloatCompare32(ValueEmitContext& ctx, const IR::Inst& inst) {
|
||||
}
|
||||
inline constexpr auto EmitFPOrdEqual32 = EmitFloatCompare32<spv::OpFOrdEqual>;
|
||||
EMIT_NATIVE(FPOrdEqual64, OpFOrdEqual, U1, uint32_t, uint32_t)
|
||||
EMIT_NATIVE(FPOrdLessThanEqual64, OpFOrdLessThanEqual, U1, uint32_t, uint32_t)
|
||||
EMIT_NATIVE(FPOrdGreaterThanEqual64, OpFOrdGreaterThanEqual, U1, uint32_t, uint32_t)
|
||||
inline constexpr auto EmitFPUnordEqual32 = EmitFloatCompare32<spv::OpFUnordEqual>;
|
||||
inline constexpr auto EmitFPOrdNotEqual32 = EmitFloatCompare32<spv::OpFOrdNotEqual>;
|
||||
inline constexpr auto EmitFPUnordNotEqual32 = EmitFloatCompare32<spv::OpFUnordNotEqual>;
|
||||
@@ -150,6 +155,7 @@ inline constexpr auto EmitFPCmpClass32 = EmitClassMaskF32;
|
||||
EMIT_NATIVE(FPAdd32, OpFAdd, F32, uint32_t, uint32_t)
|
||||
EMIT_NATIVE(FPSub32, OpFSub, F32, uint32_t, uint32_t)
|
||||
EMIT_NATIVE(FPMul32, OpFMul, F32, uint32_t, uint32_t)
|
||||
EMIT_NATIVE(FPAdd64, OpFAdd, F64, uint32_t, uint32_t)
|
||||
EMIT_NATIVE(FPMul64, OpFMul, F64, uint32_t, uint32_t)
|
||||
inline constexpr auto EmitFPFma64 =
|
||||
EmitGlsl<GLSLstd450Fma, IR::Type::F64, uint32_t, uint32_t, uint32_t>;
|
||||
@@ -223,7 +229,7 @@ void EmitLoadMemory(ValueEmitContext& ctx, const IR::Inst& inst
|
||||
void EmitStoreMemory(ValueEmitContext& ctx, const IR::Inst& inst);
|
||||
uint32_t EmitAtomic32(ValueEmitContext& ctx, const IR::Inst& inst);
|
||||
uint32_t EmitBufferAtomic64(ValueEmitContext& ctx, const IR::Inst& inst);
|
||||
void EmitSharedAtomicOr64(ValueEmitContext& ctx, const IR::Inst& inst);
|
||||
void EmitSharedAtomic64(ValueEmitContext& ctx, const IR::Inst& inst);
|
||||
uint32_t EmitBufferFloatAtomic(ValueEmitContext& ctx, const IR::Inst& inst);
|
||||
void EmitSharedFloatAtomic(ValueEmitContext& ctx, const IR::Inst& inst);
|
||||
uint32_t EmitSharedIncDec(ValueEmitContext& ctx, const IR::Inst& inst);
|
||||
@@ -259,6 +265,7 @@ inline constexpr auto EmitBufferAtomicUMin32 = EmitAtomic32;
|
||||
inline constexpr auto EmitBufferAtomicSMax32 = EmitAtomic32;
|
||||
inline constexpr auto EmitBufferAtomicUMax32 = EmitAtomic32;
|
||||
inline constexpr auto EmitBufferAtomicAnd32 = EmitAtomic32;
|
||||
inline constexpr auto EmitBufferAtomicAnd64 = EmitBufferAtomic64;
|
||||
inline constexpr auto EmitBufferAtomicOr32 = EmitAtomic32;
|
||||
inline constexpr auto EmitBufferAtomicOr64 = EmitBufferAtomic64;
|
||||
inline constexpr auto EmitBufferAtomicXor32 = EmitAtomic32;
|
||||
@@ -280,6 +287,7 @@ inline constexpr auto EmitSharedAtomicFMin32 = EmitSharedFloatAtomic;
|
||||
inline constexpr auto EmitSharedAtomicFMax32 = EmitSharedFloatAtomic;
|
||||
inline constexpr auto EmitSharedAtomicSwap32 = EmitAtomic32;
|
||||
inline constexpr auto EmitSharedAtomicIAdd32 = EmitAtomic32;
|
||||
inline constexpr auto EmitSharedAtomicIAdd64 = EmitSharedAtomic64;
|
||||
inline constexpr auto EmitSharedAtomicISub32 = EmitAtomic32;
|
||||
inline constexpr auto EmitSharedAtomicInc32 = EmitSharedIncDec;
|
||||
inline constexpr auto EmitSharedAtomicDec32 = EmitSharedIncDec;
|
||||
@@ -289,6 +297,7 @@ inline constexpr auto EmitSharedAtomicSMax32 = EmitAtomic32;
|
||||
inline constexpr auto EmitSharedAtomicUMax32 = EmitAtomic32;
|
||||
inline constexpr auto EmitSharedAtomicAnd32 = EmitAtomic32;
|
||||
inline constexpr auto EmitSharedAtomicOr32 = EmitAtomic32;
|
||||
inline constexpr auto EmitSharedAtomicOr64 = EmitSharedAtomic64;
|
||||
inline constexpr auto EmitSharedAtomicXor32 = EmitAtomic32;
|
||||
inline constexpr auto EmitDataAppend = EmitAppendConsume;
|
||||
inline constexpr auto EmitDataConsume = EmitAppendConsume;
|
||||
@@ -303,7 +312,9 @@ inline constexpr auto EmitImageSampleRaw = EmitImage;
|
||||
inline constexpr auto EmitImageGatherRaw = EmitImage;
|
||||
inline constexpr auto EmitImageAtomicSwap32 = EmitImage;
|
||||
inline constexpr auto EmitImageAtomicIAdd32 = EmitImage;
|
||||
inline constexpr auto EmitImageAtomicSMin32 = EmitImage;
|
||||
inline constexpr auto EmitImageAtomicUMin32 = EmitImage;
|
||||
inline constexpr auto EmitImageAtomicSMax32 = EmitImage;
|
||||
inline constexpr auto EmitImageAtomicUMax32 = EmitImage;
|
||||
inline constexpr auto EmitImageAtomicAnd32 = EmitImage;
|
||||
inline constexpr auto EmitImageAtomicOr32 = EmitImage;
|
||||
|
||||
@@ -562,6 +562,7 @@ spv::Op SpirvAtomicOpcode(IR::ValueOpcode opcode) {
|
||||
case IR::ValueOpcode::BufferAtomicSwap64:
|
||||
case IR::ValueOpcode::SharedAtomicSwap32: return spv::OpAtomicExchange;
|
||||
case IR::ValueOpcode::BufferAtomicIAdd32:
|
||||
case IR::ValueOpcode::SharedAtomicIAdd64:
|
||||
case IR::ValueOpcode::SharedAtomicIAdd32: return spv::OpAtomicIAdd;
|
||||
case IR::ValueOpcode::BufferAtomicISub32:
|
||||
case IR::ValueOpcode::SharedAtomicISub32: return spv::OpAtomicISub;
|
||||
@@ -574,6 +575,7 @@ spv::Op SpirvAtomicOpcode(IR::ValueOpcode opcode) {
|
||||
case IR::ValueOpcode::BufferAtomicUMax32:
|
||||
case IR::ValueOpcode::SharedAtomicUMax32: return spv::OpAtomicUMax;
|
||||
case IR::ValueOpcode::BufferAtomicAnd32:
|
||||
case IR::ValueOpcode::BufferAtomicAnd64:
|
||||
case IR::ValueOpcode::SharedAtomicAnd32: return spv::OpAtomicAnd;
|
||||
case IR::ValueOpcode::BufferAtomicOr32:
|
||||
case IR::ValueOpcode::BufferAtomicOr64:
|
||||
@@ -1115,7 +1117,7 @@ uint32_t EmitBufferAtomic64(ValueEmitContext& ctx, const IR::Inst& inst) {
|
||||
});
|
||||
}
|
||||
|
||||
void EmitSharedAtomicOr64(ValueEmitContext& ctx, const IR::Inst& inst) {
|
||||
void EmitSharedAtomic64(ValueEmitContext& ctx, const IR::Inst& inst) {
|
||||
auto& state = ctx.state;
|
||||
const auto& mem = ctx.Memory(inst);
|
||||
EnsureLdsStorage(state);
|
||||
|
||||
@@ -193,7 +193,9 @@ constexpr MimgGatherInfo MIMG_GATHER_OPCODE_LIST[] = {
|
||||
constexpr Detail::OpcodeMap MIMG_ATOMIC_OPCODE_LIST[] = {
|
||||
{0x0fu, Opcode::IMAGE_ATOMIC_SWAP},
|
||||
{0x11u, Opcode::IMAGE_ATOMIC_ADD},
|
||||
{0x14u, Opcode::IMAGE_ATOMIC_SMIN},
|
||||
{0x15u, Opcode::IMAGE_ATOMIC_UMIN},
|
||||
{0x16u, Opcode::IMAGE_ATOMIC_SMAX},
|
||||
{0x17u, Opcode::IMAGE_ATOMIC_UMAX},
|
||||
{0x18u, Opcode::IMAGE_ATOMIC_AND},
|
||||
{0x19u, Opcode::IMAGE_ATOMIC_OR},
|
||||
|
||||
@@ -61,6 +61,7 @@ constexpr MemoryOpcodeInfo MUBUF_OPCODE_LIST[] = {
|
||||
{0x3fu, Opcode::BUFFER_ATOMIC_FMIN, 1, 32},
|
||||
{0x40u, Opcode::BUFFER_ATOMIC_FMAX, 1, 32},
|
||||
{0x50u, Opcode::BUFFER_ATOMIC_SWAP_X2, 2, 32},
|
||||
{0x59u, Opcode::BUFFER_ATOMIC_AND_X2, 2, 32},
|
||||
{0x5au, Opcode::BUFFER_ATOMIC_OR_X2, 2, 32},
|
||||
};
|
||||
|
||||
@@ -106,7 +107,7 @@ constexpr MemoryOpcodeInfo DS_OPCODE_LIST[] = {
|
||||
{0x39u, Opcode::DS_READ_I8, 1, 8, true}, {0x3au, Opcode::DS_READ_U8, 1, 8},
|
||||
{0x3bu, Opcode::DS_READ_I16, 1, 16, true}, {0x3cu, Opcode::DS_READ_U16, 1, 16},
|
||||
{0x3du, Opcode::DS_CONSUME, 1, 32}, {0x3eu, Opcode::DS_APPEND, 1, 32},
|
||||
{0x4au, Opcode::DS_OR_B64, 2, 32},
|
||||
{0x40u, Opcode::DS_ADD_U64, 2, 32}, {0x4au, Opcode::DS_OR_B64, 2, 32},
|
||||
{0x4du, Opcode::DS_WRITE_B64, 2, 32}, {0x4eu, Opcode::DS_WRITE2_B64, 4, 32},
|
||||
{0x4fu, Opcode::DS_WRITE2ST64_B64, 4, 32}, {0x76u, Opcode::DS_READ_B64, 2, 32},
|
||||
{0x77u, Opcode::DS_READ2_B64, 4, 32}, {0x78u, Opcode::DS_READ2ST64_B64, 4, 32},
|
||||
@@ -168,6 +169,7 @@ bool IsDsWriteOpcode(Opcode opcode) {
|
||||
bool IsDsAtomicOpcode(Opcode opcode) {
|
||||
switch (opcode) {
|
||||
case Opcode::DS_ADD_U32:
|
||||
case Opcode::DS_ADD_U64:
|
||||
case Opcode::DS_ADD_RTN_U32:
|
||||
case Opcode::DS_SUB_U32:
|
||||
case Opcode::DS_SUB_RTN_U32:
|
||||
|
||||
@@ -46,6 +46,7 @@ constexpr OpcodeMap SOP1_OPCODE_LIST[] = {
|
||||
{0x09u, Opcode::S_WQM_B32},
|
||||
{0x0au, Opcode::S_WQM_B64},
|
||||
{0x0bu, Opcode::S_BREV_B32},
|
||||
{0x0cu, Opcode::S_BREV_B64},
|
||||
{0x0fu, Opcode::S_BCNT1_I32_B32},
|
||||
{0x10u, Opcode::S_BCNT1_I32_B64},
|
||||
{0x13u, Opcode::S_FF1_I32_B32},
|
||||
|
||||
@@ -504,6 +504,7 @@ std::string InstructionToString(const Instruction& inst) {
|
||||
OperandToString(inst.src0).c_str()));
|
||||
case Opcode::S_ABS_I32:
|
||||
case Opcode::S_BREV_B32:
|
||||
case Opcode::S_BREV_B64:
|
||||
case Opcode::S_BCNT1_I32_B32:
|
||||
case Opcode::S_FLBIT_I32_B32:
|
||||
case Opcode::S_FF1_I32_B32:
|
||||
@@ -575,7 +576,9 @@ std::string InstructionToString(const Instruction& inst) {
|
||||
case Opcode::IMAGE_STORE_MIP:
|
||||
case Opcode::IMAGE_ATOMIC_SWAP:
|
||||
case Opcode::IMAGE_ATOMIC_ADD:
|
||||
case Opcode::IMAGE_ATOMIC_SMIN:
|
||||
case Opcode::IMAGE_ATOMIC_UMIN:
|
||||
case Opcode::IMAGE_ATOMIC_SMAX:
|
||||
case Opcode::IMAGE_ATOMIC_UMAX:
|
||||
case Opcode::IMAGE_ATOMIC_AND:
|
||||
case Opcode::IMAGE_ATOMIC_OR:
|
||||
@@ -642,6 +645,7 @@ std::string InstructionToString(const Instruction& inst) {
|
||||
case Opcode::BUFFER_ATOMIC_SMAX:
|
||||
case Opcode::BUFFER_ATOMIC_UMAX:
|
||||
case Opcode::BUFFER_ATOMIC_AND:
|
||||
case Opcode::BUFFER_ATOMIC_AND_X2:
|
||||
case Opcode::BUFFER_ATOMIC_OR:
|
||||
case Opcode::BUFFER_ATOMIC_OR_X2:
|
||||
case Opcode::BUFFER_ATOMIC_XOR:
|
||||
@@ -664,6 +668,7 @@ std::string InstructionToString(const Instruction& inst) {
|
||||
case Opcode::FLAT_STORE_DWORDX3:
|
||||
case Opcode::FLAT_STORE_DWORDX4:
|
||||
case Opcode::DS_ADD_U32:
|
||||
case Opcode::DS_ADD_U64:
|
||||
case Opcode::DS_ADD_RTN_U32:
|
||||
case Opcode::DS_SUB_U32:
|
||||
case Opcode::DS_SUB_RTN_U32:
|
||||
|
||||
@@ -47,6 +47,7 @@ enum class Opcode {
|
||||
S_ABS_I32,
|
||||
S_ABSDIFF_I32,
|
||||
S_BREV_B32,
|
||||
S_BREV_B64,
|
||||
S_BCNT1_I32_B32,
|
||||
S_BCNT1_I32_B64,
|
||||
S_FF1_I32_B32,
|
||||
@@ -244,6 +245,7 @@ enum class Opcode {
|
||||
V_MAD_U32_U24,
|
||||
V_MAD_U64_U32,
|
||||
V_FMA_F64,
|
||||
V_ADD_F64,
|
||||
V_MUL_F64,
|
||||
V_FMA_F32,
|
||||
V_FMA_F16,
|
||||
@@ -360,6 +362,9 @@ enum class Opcode {
|
||||
V_CMP_NLT_F32,
|
||||
V_CMP_TRU_F32,
|
||||
V_CMP_EQ_F64,
|
||||
V_CMP_LE_F64,
|
||||
V_CMPX_LE_F64,
|
||||
V_CMPX_GE_F64,
|
||||
V_CMPX_LT_F32,
|
||||
V_CMPX_EQ_F32,
|
||||
V_CMPX_LE_F32,
|
||||
@@ -390,12 +395,18 @@ enum class Opcode {
|
||||
V_CMP_NE_I16,
|
||||
V_CMP_GE_I16,
|
||||
V_CMPX_LT_I16,
|
||||
V_CMPX_EQ_I16,
|
||||
V_CMPX_LE_I16,
|
||||
V_CMPX_GT_I16,
|
||||
V_CMPX_NE_I16,
|
||||
V_CMPX_GE_I16,
|
||||
V_CMP_LT_F16,
|
||||
V_CMP_EQ_F16,
|
||||
V_CMP_LE_F16,
|
||||
V_CMP_GT_F16,
|
||||
V_CMP_LG_F16,
|
||||
V_CMP_GE_F16,
|
||||
V_CMP_NGE_F16,
|
||||
V_CMP_NGT_F16,
|
||||
V_CMP_NEQ_F16,
|
||||
V_CMP_NLT_F16,
|
||||
@@ -432,11 +443,16 @@ enum class Opcode {
|
||||
V_CMP_GE_U32,
|
||||
V_CMP_T_U32,
|
||||
V_CMP_EQ_I64,
|
||||
V_CMP_LT_I64,
|
||||
V_CMP_LE_I64,
|
||||
V_CMP_LT_U64,
|
||||
V_CMP_EQ_U64,
|
||||
V_CMP_LE_U64,
|
||||
V_CMP_GT_U64,
|
||||
V_CMP_NE_U64,
|
||||
V_CMP_GE_U64,
|
||||
V_CMPX_NE_I64,
|
||||
V_CMPX_LE_U64,
|
||||
V_CMPX_NE_U64,
|
||||
V_CMPX_LT_U32,
|
||||
V_CMPX_EQ_U32,
|
||||
@@ -496,6 +512,7 @@ enum class Opcode {
|
||||
BUFFER_ATOMIC_SMAX,
|
||||
BUFFER_ATOMIC_UMAX,
|
||||
BUFFER_ATOMIC_AND,
|
||||
BUFFER_ATOMIC_AND_X2,
|
||||
BUFFER_ATOMIC_OR,
|
||||
BUFFER_ATOMIC_OR_X2,
|
||||
BUFFER_ATOMIC_XOR,
|
||||
@@ -516,6 +533,7 @@ enum class Opcode {
|
||||
FLAT_STORE_DWORDX3,
|
||||
FLAT_STORE_DWORDX4,
|
||||
DS_ADD_U32,
|
||||
DS_ADD_U64,
|
||||
DS_ADD_RTN_U32,
|
||||
DS_SUB_U32,
|
||||
DS_SUB_RTN_U32,
|
||||
@@ -582,7 +600,9 @@ enum class Opcode {
|
||||
IMAGE_STORE_MIP,
|
||||
IMAGE_ATOMIC_SWAP,
|
||||
IMAGE_ATOMIC_ADD,
|
||||
IMAGE_ATOMIC_SMIN,
|
||||
IMAGE_ATOMIC_UMIN,
|
||||
IMAGE_ATOMIC_SMAX,
|
||||
IMAGE_ATOMIC_UMAX,
|
||||
IMAGE_ATOMIC_AND,
|
||||
IMAGE_ATOMIC_OR,
|
||||
|
||||
@@ -228,7 +228,8 @@ constexpr VopcOpcodeInfo VOPC_OPCODE_LIST[] = {
|
||||
{0x19u, Opcode::V_CMPX_NGE_F32}, {0x1au, Opcode::V_CMPX_NLG_F32},
|
||||
{0x1bu, Opcode::V_CMPX_NGT_F32}, {0x1cu, Opcode::V_CMPX_NLE_F32},
|
||||
{0x1du, Opcode::V_CMPX_NEQ_F32}, {0x1eu, Opcode::V_CMPX_NLT_F32},
|
||||
{0x22u, Opcode::V_CMP_EQ_F64, false},
|
||||
{0x22u, Opcode::V_CMP_EQ_F64, false}, {0x23u, Opcode::V_CMP_LE_F64, false},
|
||||
{0x33u, Opcode::V_CMPX_LE_F64, false}, {0x36u, Opcode::V_CMPX_GE_F64, false},
|
||||
{0x80u, Opcode::V_CMP_F_I32}, {0x81u, Opcode::V_CMP_LT_I32},
|
||||
{0x82u, Opcode::V_CMP_EQ_I32}, {0x83u, Opcode::V_CMP_LE_I32},
|
||||
{0x84u, Opcode::V_CMP_GT_I32}, {0x85u, Opcode::V_CMP_NE_I32},
|
||||
@@ -240,7 +241,9 @@ constexpr VopcOpcodeInfo VOPC_OPCODE_LIST[] = {
|
||||
{0x92u, Opcode::V_CMPX_EQ_I32}, {0x93u, Opcode::V_CMPX_LE_I32},
|
||||
{0x94u, Opcode::V_CMPX_GT_I32}, {0x95u, Opcode::V_CMPX_NE_I32},
|
||||
{0x96u, Opcode::V_CMPX_GE_I32}, {0x98u, Opcode::V_CMPX_CLASS_F32},
|
||||
{0x99u, Opcode::V_CMPX_LT_I16, false},
|
||||
{0x99u, Opcode::V_CMPX_LT_I16, false}, {0x9au, Opcode::V_CMPX_EQ_I16, false},
|
||||
{0x9bu, Opcode::V_CMPX_LE_I16, false}, {0x9cu, Opcode::V_CMPX_GT_I16, false},
|
||||
{0x9du, Opcode::V_CMPX_NE_I16, false}, {0x9eu, Opcode::V_CMPX_GE_I16, false},
|
||||
{0xa9u, Opcode::V_CMP_LT_U16}, {0xaau, Opcode::V_CMP_EQ_U16},
|
||||
{0xabu, Opcode::V_CMP_LE_U16}, {0xacu, Opcode::V_CMP_GT_U16},
|
||||
{0xadu, Opcode::V_CMP_NE_U16}, {0xaeu, Opcode::V_CMP_GE_U16},
|
||||
@@ -250,16 +253,19 @@ constexpr VopcOpcodeInfo VOPC_OPCODE_LIST[] = {
|
||||
{0xc3u, Opcode::V_CMP_LE_U32}, {0xc4u, Opcode::V_CMP_GT_U32},
|
||||
{0xc5u, Opcode::V_CMP_NE_U32}, {0xc6u, Opcode::V_CMP_GE_U32},
|
||||
{0xc7u, Opcode::V_CMP_T_U32}, {0xa2u, Opcode::V_CMP_EQ_I64, false},
|
||||
{0xa1u, Opcode::V_CMP_LT_I64, false}, {0xa3u, Opcode::V_CMP_LE_I64, false},
|
||||
{0xb5u, Opcode::V_CMPX_NE_I64, false}, {0xd1u, Opcode::V_CMPX_LT_U32},
|
||||
{0xd2u, Opcode::V_CMPX_EQ_U32}, {0xd3u, Opcode::V_CMPX_LE_U32},
|
||||
{0xd4u, Opcode::V_CMPX_GT_U32}, {0xd5u, Opcode::V_CMPX_NE_U32},
|
||||
{0xd6u, Opcode::V_CMPX_GE_U32}, {0xe1u, Opcode::V_CMP_LT_U64, false},
|
||||
{0xe2u, Opcode::V_CMP_EQ_U64, false}, {0xe4u, Opcode::V_CMP_GT_U64, false},
|
||||
{0xe5u, Opcode::V_CMP_NE_U64, false},
|
||||
{0xe2u, Opcode::V_CMP_EQ_U64, false}, {0xe3u, Opcode::V_CMP_LE_U64, false},
|
||||
{0xe4u, Opcode::V_CMP_GT_U64, false}, {0xe5u, Opcode::V_CMP_NE_U64, false},
|
||||
{0xe6u, Opcode::V_CMP_GE_U64, false}, {0xf3u, Opcode::V_CMPX_LE_U64, false},
|
||||
{0xf5u, Opcode::V_CMPX_NE_U64, false}, {0xc9u, Opcode::V_CMP_LT_F16},
|
||||
{0xcau, Opcode::V_CMP_EQ_F16}, {0xcbu, Opcode::V_CMP_LE_F16},
|
||||
{0xccu, Opcode::V_CMP_GT_F16}, {0xcdu, Opcode::V_CMP_LG_F16},
|
||||
{0xceu, Opcode::V_CMP_GE_F16}, {0xebu, Opcode::V_CMP_NGT_F16},
|
||||
{0xceu, Opcode::V_CMP_GE_F16}, {0xe9u, Opcode::V_CMP_NGE_F16},
|
||||
{0xebu, Opcode::V_CMP_NGT_F16},
|
||||
{0xedu, Opcode::V_CMP_NEQ_F16}, {0xeeu, Opcode::V_CMP_NLT_F16},
|
||||
{0xd9u, Opcode::V_CMPX_LT_F16}, {0xdau, Opcode::V_CMPX_EQ_F16},
|
||||
{0xdbu, Opcode::V_CMPX_LE_F16}, {0xdcu, Opcode::V_CMPX_GT_F16},
|
||||
@@ -281,6 +287,7 @@ constexpr OpcodeMap VOP3_OPCODE_LIST[] = {
|
||||
{0x147u, Opcode::V_CUBEMA_F32},
|
||||
{0x14bu, Opcode::V_FMA_F32},
|
||||
{0x14cu, Opcode::V_FMA_F64},
|
||||
{0x164u, Opcode::V_ADD_F64},
|
||||
{0x165u, Opcode::V_MUL_F64},
|
||||
{0x148u, Opcode::V_BFE_U32},
|
||||
{0x149u, Opcode::V_BFE_I32},
|
||||
@@ -831,6 +838,9 @@ bool IsVopcFloatCompareOpcode(Opcode opcode) {
|
||||
case Opcode::V_CMP_LT_F32:
|
||||
case Opcode::V_CMP_EQ_F32:
|
||||
case Opcode::V_CMP_EQ_F64:
|
||||
case Opcode::V_CMP_LE_F64:
|
||||
case Opcode::V_CMPX_LE_F64:
|
||||
case Opcode::V_CMPX_GE_F64:
|
||||
case Opcode::V_CMP_LE_F32:
|
||||
case Opcode::V_CMP_GT_F32:
|
||||
case Opcode::V_CMP_LG_F32:
|
||||
@@ -863,6 +873,7 @@ bool IsVopcFloatCompareOpcode(Opcode opcode) {
|
||||
case Opcode::V_CMP_GT_F16:
|
||||
case Opcode::V_CMP_LG_F16:
|
||||
case Opcode::V_CMP_GE_F16:
|
||||
case Opcode::V_CMP_NGE_F16:
|
||||
case Opcode::V_CMP_NGT_F16:
|
||||
case Opcode::V_CMP_NEQ_F16:
|
||||
case Opcode::V_CMP_NLT_F16:
|
||||
@@ -1141,7 +1152,9 @@ VopcSdwaFields DecodeVopcSdwaFields(uint32_t modifier) {
|
||||
}
|
||||
|
||||
bool SupportsVopcSdwa(Opcode opcode) {
|
||||
return opcode != Opcode::UNSUPPORTED && opcode != Opcode::V_CMP_EQ_F64;
|
||||
return opcode != Opcode::UNSUPPORTED && opcode != Opcode::V_CMP_EQ_F64 &&
|
||||
opcode != Opcode::V_CMP_LE_F64 && opcode != Opcode::V_CMPX_LE_F64 &&
|
||||
opcode != Opcode::V_CMPX_GE_F64;
|
||||
}
|
||||
|
||||
void DecodeVopcSdwa(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index,
|
||||
@@ -1206,6 +1219,7 @@ void DecodeVopcDpp(uint32_t pc, std::span<const uint32_t> code, uint32_t word_in
|
||||
|
||||
uint32_t NativeVop3SourceCount(Opcode opcode) {
|
||||
switch (opcode) {
|
||||
case Opcode::V_ADD_F64:
|
||||
case Opcode::V_MUL_F64:
|
||||
case Opcode::V_MUL_LO_U32:
|
||||
case Opcode::V_MUL_HI_U32:
|
||||
@@ -1357,6 +1371,7 @@ bool SupportsNativeVop3SourceModifiers(Opcode opcode) {
|
||||
case Opcode::V_MAX_F32:
|
||||
case Opcode::V_MAC_F32:
|
||||
case Opcode::V_MAD_F32:
|
||||
case Opcode::V_ADD_F64:
|
||||
case Opcode::V_MUL_F64:
|
||||
case Opcode::V_FMA_F64:
|
||||
case Opcode::V_FMA_F32:
|
||||
@@ -1462,6 +1477,8 @@ void ApplyNativeVop3SourceModifiers(Instruction& inst, uint32_t abs, uint32_t ne
|
||||
|
||||
bool IsVopcCompareExec(Opcode opcode) {
|
||||
switch (opcode) {
|
||||
case Opcode::V_CMPX_LE_F64:
|
||||
case Opcode::V_CMPX_GE_F64:
|
||||
case Opcode::V_CMPX_LT_F32:
|
||||
case Opcode::V_CMPX_EQ_F32:
|
||||
case Opcode::V_CMPX_LE_F32:
|
||||
@@ -1489,8 +1506,14 @@ bool IsVopcCompareExec(Opcode opcode) {
|
||||
case Opcode::V_CMPX_NE_U32:
|
||||
case Opcode::V_CMPX_GE_U32:
|
||||
case Opcode::V_CMPX_NE_I64:
|
||||
case Opcode::V_CMPX_LE_U64:
|
||||
case Opcode::V_CMPX_NE_U64:
|
||||
case Opcode::V_CMPX_LT_I16:
|
||||
case Opcode::V_CMPX_EQ_I16:
|
||||
case Opcode::V_CMPX_LE_I16:
|
||||
case Opcode::V_CMPX_GT_I16:
|
||||
case Opcode::V_CMPX_NE_I16:
|
||||
case Opcode::V_CMPX_GE_I16:
|
||||
case Opcode::V_CMPX_LT_U16:
|
||||
case Opcode::V_CMPX_EQ_U16:
|
||||
case Opcode::V_CMPX_GT_U16:
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "graphics/shader/recompiler/frontend/translate/Translator.h"
|
||||
|
||||
#include <bit>
|
||||
|
||||
namespace Libs::Graphics::ShaderRecompiler::Frontend {
|
||||
|
||||
void Translator::EmitCompareResult(const Decoder::Instruction& inst, IR::U1 value, bool scalar,
|
||||
@@ -26,9 +28,20 @@ void Translator::EmitCompareConstant(const Decoder::Instruction& inst, bool valu
|
||||
|
||||
void Translator::EmitIntegerCompare(const Decoder::Instruction& inst, IR::ValueOpcode opcode,
|
||||
IR::Type type, bool scalar, bool cmpx) {
|
||||
const auto lhs = ReadOperand(inst.src0, type);
|
||||
const auto rhs = ReadOperand(inst.src1, type);
|
||||
EmitCompareResult(inst, IR::U1(ir.Emit(opcode, {lhs, rhs})), scalar, cmpx);
|
||||
const bool signed_64 = opcode == IR::ValueOpcode::SLessThan64 ||
|
||||
opcode == IR::ValueOpcode::SLessThanEqual64 ||
|
||||
inst.opcode == Decoder::Opcode::V_CMP_EQ_I64 ||
|
||||
inst.opcode == Decoder::Opcode::V_CMPX_NE_I64;
|
||||
const auto read = [&](const Decoder::Operand& operand) {
|
||||
// RDNA2 expands signed 64-bit integer literals by sign extension.
|
||||
if (signed_64 && operand.kind == Decoder::OperandKind::LiteralConstant) {
|
||||
return IR::Value(static_cast<uint64_t>(
|
||||
static_cast<int64_t>(std::bit_cast<int32_t>(operand.value))));
|
||||
}
|
||||
return ReadOperand(operand, type);
|
||||
};
|
||||
EmitCompareResult(inst, IR::U1(ir.Emit(opcode, {read(inst.src0), read(inst.src1)})), scalar,
|
||||
cmpx);
|
||||
}
|
||||
|
||||
void Translator::EmitInteger16Compare(const Decoder::Instruction& inst, IR::ValueOpcode opcode,
|
||||
|
||||
@@ -966,6 +966,8 @@ void Translator::EmitMemory(const Decoder::Instruction& inst) {
|
||||
return BUFFER_ATOMIC(inst, IR::ValueOpcode::BufferAtomicUMax32);
|
||||
case Decoder::Opcode::BUFFER_ATOMIC_AND:
|
||||
return BUFFER_ATOMIC(inst, IR::ValueOpcode::BufferAtomicAnd32);
|
||||
case Decoder::Opcode::BUFFER_ATOMIC_AND_X2:
|
||||
return BUFFER_ATOMIC(inst, IR::ValueOpcode::BufferAtomicAnd64);
|
||||
case Decoder::Opcode::BUFFER_ATOMIC_OR:
|
||||
return BUFFER_ATOMIC(inst, IR::ValueOpcode::BufferAtomicOr32);
|
||||
case Decoder::Opcode::BUFFER_ATOMIC_OR_X2:
|
||||
@@ -979,6 +981,8 @@ void Translator::EmitMemory(const Decoder::Instruction& inst) {
|
||||
|
||||
case Decoder::Opcode::DS_ADD_U32:
|
||||
return DS_ATOMIC(inst, IR::ValueOpcode::SharedAtomicIAdd32, false);
|
||||
case Decoder::Opcode::DS_ADD_U64:
|
||||
return DS_ATOMIC(inst, IR::ValueOpcode::SharedAtomicIAdd64, false);
|
||||
case Decoder::Opcode::DS_ADD_RTN_U32:
|
||||
return DS_ATOMIC(inst, IR::ValueOpcode::SharedAtomicIAdd32, true);
|
||||
case Decoder::Opcode::DS_SUB_U32:
|
||||
@@ -1030,8 +1034,12 @@ void Translator::EmitMemory(const Decoder::Instruction& inst) {
|
||||
return IMAGE_ATOMIC(inst, IR::ValueOpcode::ImageAtomicSwap32);
|
||||
case Decoder::Opcode::IMAGE_ATOMIC_ADD:
|
||||
return IMAGE_ATOMIC(inst, IR::ValueOpcode::ImageAtomicIAdd32);
|
||||
case Decoder::Opcode::IMAGE_ATOMIC_SMIN:
|
||||
return IMAGE_ATOMIC(inst, IR::ValueOpcode::ImageAtomicSMin32);
|
||||
case Decoder::Opcode::IMAGE_ATOMIC_UMIN:
|
||||
return IMAGE_ATOMIC(inst, IR::ValueOpcode::ImageAtomicUMin32);
|
||||
case Decoder::Opcode::IMAGE_ATOMIC_SMAX:
|
||||
return IMAGE_ATOMIC(inst, IR::ValueOpcode::ImageAtomicSMax32);
|
||||
case Decoder::Opcode::IMAGE_ATOMIC_UMAX:
|
||||
return IMAGE_ATOMIC(inst, IR::ValueOpcode::ImageAtomicUMax32);
|
||||
case Decoder::Opcode::IMAGE_ATOMIC_AND:
|
||||
|
||||
@@ -155,6 +155,12 @@ void Translator::EmitScalar(const Decoder::Instruction& inst) {
|
||||
case O::S_BREV_B32:
|
||||
return SimpleInteger(inst, IR::ValueOpcode::BitReverse32, IR::Type::U32, false, false,
|
||||
false);
|
||||
case O::S_BREV_B64: {
|
||||
const auto value = ReadU32Pair(inst.src0);
|
||||
WriteU32Pair(inst.dst, {IR::U32(ir.Emit(IR::ValueOpcode::BitReverse32, {value[1]})),
|
||||
IR::U32(ir.Emit(IR::ValueOpcode::BitReverse32, {value[0]}))});
|
||||
return;
|
||||
}
|
||||
case O::S_BCNT1_I32_B32:
|
||||
return SimpleInteger(inst, IR::ValueOpcode::BitCount32, IR::Type::U32, false, false,
|
||||
true);
|
||||
|
||||
@@ -894,10 +894,26 @@ void IncludeInstructionVectorRegisters(const Decoder::Instruction& inst, uint32_
|
||||
case Decoder::Opcode::V_CVT_F64_F32:
|
||||
case Decoder::Opcode::V_CVT_F64_U32: include_vector(inst.dst, 2u); break;
|
||||
case Decoder::Opcode::V_FMA_F64: include_vector(inst.src2, 2u); [[fallthrough]];
|
||||
case Decoder::Opcode::V_ADD_F64:
|
||||
case Decoder::Opcode::V_MUL_F64: include_vector(inst.src1, 2u); [[fallthrough]];
|
||||
case Decoder::Opcode::V_RCP_F64: include_vector(inst.dst, 2u); [[fallthrough]];
|
||||
case Decoder::Opcode::V_CVT_F32_F64: include_vector(inst.src0, 2u); break;
|
||||
case Decoder::Opcode::V_CMP_EQ_F64:
|
||||
case Decoder::Opcode::V_CMP_LE_F64:
|
||||
case Decoder::Opcode::V_CMPX_LE_F64:
|
||||
case Decoder::Opcode::V_CMPX_GE_F64:
|
||||
case Decoder::Opcode::V_CMP_EQ_I64:
|
||||
case Decoder::Opcode::V_CMP_LT_I64:
|
||||
case Decoder::Opcode::V_CMP_LE_I64:
|
||||
case Decoder::Opcode::V_CMP_LT_U64:
|
||||
case Decoder::Opcode::V_CMP_EQ_U64:
|
||||
case Decoder::Opcode::V_CMP_LE_U64:
|
||||
case Decoder::Opcode::V_CMP_GT_U64:
|
||||
case Decoder::Opcode::V_CMP_NE_U64:
|
||||
case Decoder::Opcode::V_CMP_GE_U64:
|
||||
case Decoder::Opcode::V_CMPX_NE_I64:
|
||||
case Decoder::Opcode::V_CMPX_LE_U64:
|
||||
case Decoder::Opcode::V_CMPX_NE_U64:
|
||||
include_vector(inst.src0, 2u);
|
||||
include_vector(inst.src1, 2u);
|
||||
break;
|
||||
@@ -905,6 +921,8 @@ void IncludeInstructionVectorRegisters(const Decoder::Instruction& inst, uint32_
|
||||
}
|
||||
if (inst.family == Decoder::Family::DS) {
|
||||
switch (inst.opcode) {
|
||||
case Decoder::Opcode::DS_ADD_U64:
|
||||
case Decoder::Opcode::DS_OR_B64:
|
||||
case Decoder::Opcode::DS_WRITE_B64:
|
||||
case Decoder::Opcode::DS_WRITE_B96:
|
||||
case Decoder::Opcode::DS_WRITE_B128: include_vector(inst.src1, inst.data_dwords); break;
|
||||
|
||||
@@ -114,18 +114,40 @@ void Translator::EmitVector(const Decoder::Instruction& inst) {
|
||||
EmitIntegerCompare(inst, IR::ValueOpcode::INotEqual64, IR::Type::U64, false, true);
|
||||
return;
|
||||
|
||||
case O::V_CMP_LT_I64:
|
||||
EmitIntegerCompare(inst, IR::ValueOpcode::SLessThan64, IR::Type::U64, false, false);
|
||||
return;
|
||||
case O::V_CMP_LE_I64:
|
||||
EmitIntegerCompare(inst, IR::ValueOpcode::SLessThanEqual64, IR::Type::U64, false, false);
|
||||
return;
|
||||
case O::V_CMP_LE_U64:
|
||||
EmitIntegerCompare(inst, IR::ValueOpcode::ULessThanEqual64, IR::Type::U64, false, false);
|
||||
return;
|
||||
case O::V_CMPX_LE_U64:
|
||||
EmitIntegerCompare(inst, IR::ValueOpcode::ULessThanEqual64, IR::Type::U64, false, true);
|
||||
return;
|
||||
case O::V_CMP_GE_U64:
|
||||
EmitIntegerCompare(inst, IR::ValueOpcode::UGreaterThanEqual64, IR::Type::U64, false, false);
|
||||
return;
|
||||
|
||||
case O::V_CMP_EQ_U16:
|
||||
EmitInteger16Compare(inst, IR::ValueOpcode::IEqual32, false, false);
|
||||
return;
|
||||
case O::V_CMP_EQ_I16:
|
||||
EmitInteger16Compare(inst, IR::ValueOpcode::IEqual32, true, false);
|
||||
return;
|
||||
case O::V_CMPX_EQ_I16:
|
||||
EmitInteger16Compare(inst, IR::ValueOpcode::IEqual32, true, true);
|
||||
return;
|
||||
case O::V_CMP_NE_U16:
|
||||
EmitInteger16Compare(inst, IR::ValueOpcode::INotEqual32, false, false);
|
||||
return;
|
||||
case O::V_CMP_NE_I16:
|
||||
EmitInteger16Compare(inst, IR::ValueOpcode::INotEqual32, true, false);
|
||||
return;
|
||||
case O::V_CMPX_NE_I16:
|
||||
EmitInteger16Compare(inst, IR::ValueOpcode::INotEqual32, true, true);
|
||||
return;
|
||||
case O::V_CMP_GT_U16:
|
||||
EmitInteger16Compare(inst, IR::ValueOpcode::UGreaterThan32, false, false);
|
||||
return;
|
||||
@@ -150,9 +172,15 @@ void Translator::EmitVector(const Decoder::Instruction& inst) {
|
||||
case O::V_CMP_GT_I16:
|
||||
EmitInteger16Compare(inst, IR::ValueOpcode::SGreaterThan32, true, false);
|
||||
return;
|
||||
case O::V_CMPX_GT_I16:
|
||||
EmitInteger16Compare(inst, IR::ValueOpcode::SGreaterThan32, true, true);
|
||||
return;
|
||||
case O::V_CMP_GE_I16:
|
||||
EmitInteger16Compare(inst, IR::ValueOpcode::SGreaterThanEqual32, true, false);
|
||||
return;
|
||||
case O::V_CMPX_GE_I16:
|
||||
EmitInteger16Compare(inst, IR::ValueOpcode::SGreaterThanEqual32, true, true);
|
||||
return;
|
||||
case O::V_CMP_LT_I16:
|
||||
EmitInteger16Compare(inst, IR::ValueOpcode::SLessThan32, true, false);
|
||||
return;
|
||||
@@ -162,6 +190,9 @@ void Translator::EmitVector(const Decoder::Instruction& inst) {
|
||||
case O::V_CMP_LE_I16:
|
||||
EmitInteger16Compare(inst, IR::ValueOpcode::SLessThanEqual32, true, false);
|
||||
return;
|
||||
case O::V_CMPX_LE_I16:
|
||||
EmitInteger16Compare(inst, IR::ValueOpcode::SLessThanEqual32, true, true);
|
||||
return;
|
||||
|
||||
case O::V_CMP_F_F32: EmitCompareConstant(inst, false, false, false); return;
|
||||
case O::V_CMP_TRU_F32: EmitCompareConstant(inst, true, false, false); return;
|
||||
@@ -171,6 +202,15 @@ void Translator::EmitVector(const Decoder::Instruction& inst) {
|
||||
case O::V_CMP_EQ_F64:
|
||||
EmitFloatCompare(inst, IR::ValueOpcode::FPOrdEqual64, false, false);
|
||||
return;
|
||||
case O::V_CMP_LE_F64:
|
||||
EmitFloatCompare(inst, IR::ValueOpcode::FPOrdLessThanEqual64, false, false);
|
||||
return;
|
||||
case O::V_CMPX_LE_F64:
|
||||
EmitFloatCompare(inst, IR::ValueOpcode::FPOrdLessThanEqual64, false, true);
|
||||
return;
|
||||
case O::V_CMPX_GE_F64:
|
||||
EmitFloatCompare(inst, IR::ValueOpcode::FPOrdGreaterThanEqual64, false, true);
|
||||
return;
|
||||
case O::V_CMPX_EQ_F32:
|
||||
EmitFloatCompare(inst, IR::ValueOpcode::FPOrdEqual32, false, true);
|
||||
return;
|
||||
@@ -273,6 +313,9 @@ void Translator::EmitVector(const Decoder::Instruction& inst) {
|
||||
case O::V_CMPX_LE_F16:
|
||||
EmitFloatCompare(inst, IR::ValueOpcode::FPOrdLessThanEqual32, true, true);
|
||||
return;
|
||||
case O::V_CMP_NGE_F16:
|
||||
EmitFloatCompare(inst, IR::ValueOpcode::FPUnordLessThan32, true, false);
|
||||
return;
|
||||
case O::V_CMP_NGT_F16:
|
||||
EmitFloatCompare(inst, IR::ValueOpcode::FPUnordLessThanEqual32, true, false);
|
||||
return;
|
||||
@@ -424,6 +467,7 @@ void Translator::EmitVector(const Decoder::Instruction& inst) {
|
||||
case O::V_SUB_F32: return FloatBinary(inst, IR::ValueOpcode::FPSub32, false);
|
||||
case O::V_SUBREV_F32: return FloatBinary(inst, IR::ValueOpcode::FPSub32, true);
|
||||
case O::V_MUL_F32: return FloatBinary(inst, IR::ValueOpcode::FPMul32, false);
|
||||
case O::V_ADD_F64: return FloatBinary(inst, IR::ValueOpcode::FPAdd64, false);
|
||||
case O::V_MUL_F64: return FloatBinary(inst, IR::ValueOpcode::FPMul64, false);
|
||||
case O::V_MIN_F32: return FloatBinary(inst, IR::ValueOpcode::FPMin32, false);
|
||||
case O::V_MAX_F32: return FloatBinary(inst, IR::ValueOpcode::FPMax32, false);
|
||||
|
||||
@@ -123,6 +123,7 @@ BufferAccess BufferAccessOf(ValueOpcode opcode) {
|
||||
case ValueOpcode::BufferAtomicSMax32:
|
||||
case ValueOpcode::BufferAtomicUMax32:
|
||||
case ValueOpcode::BufferAtomicAnd32:
|
||||
case ValueOpcode::BufferAtomicAnd64:
|
||||
case ValueOpcode::BufferAtomicOr32:
|
||||
case ValueOpcode::BufferAtomicOr64:
|
||||
case ValueOpcode::BufferAtomicXor32:
|
||||
@@ -135,6 +136,7 @@ BufferAccess BufferAccessOf(ValueOpcode opcode) {
|
||||
uint32_t BufferComponentCount(ValueOpcode opcode) {
|
||||
switch (opcode) {
|
||||
case ValueOpcode::BufferAtomicSwap64:
|
||||
case ValueOpcode::BufferAtomicAnd64:
|
||||
case ValueOpcode::BufferAtomicOr64:
|
||||
case ValueOpcode::LoadBufferU32x2:
|
||||
case ValueOpcode::StoreBufferU32x2: return 2u;
|
||||
@@ -164,6 +166,7 @@ SharedAccess SharedAccessOf(ValueOpcode opcode) {
|
||||
case ValueOpcode::SharedAtomicFMax32:
|
||||
case ValueOpcode::SharedAtomicSwap32:
|
||||
case ValueOpcode::SharedAtomicIAdd32:
|
||||
case ValueOpcode::SharedAtomicIAdd64:
|
||||
case ValueOpcode::SharedAtomicISub32:
|
||||
case ValueOpcode::SharedAtomicInc32:
|
||||
case ValueOpcode::SharedAtomicDec32:
|
||||
@@ -183,6 +186,7 @@ SharedAccess SharedAccessOf(ValueOpcode opcode) {
|
||||
|
||||
uint32_t SharedComponentCount(ValueOpcode opcode) {
|
||||
switch (opcode) {
|
||||
case ValueOpcode::SharedAtomicIAdd64:
|
||||
case ValueOpcode::SharedAtomicOr64:
|
||||
case ValueOpcode::LoadSharedU32x2:
|
||||
case ValueOpcode::WriteSharedU32x2: return 2u;
|
||||
@@ -218,7 +222,9 @@ ImageOpcodeInfo ImageOpcodeInfoOf(ValueOpcode opcode) {
|
||||
return {ImageAccess::Write, ImageResourceClass::Storage, false};
|
||||
case ValueOpcode::ImageAtomicSwap32:
|
||||
case ValueOpcode::ImageAtomicIAdd32:
|
||||
case ValueOpcode::ImageAtomicSMin32:
|
||||
case ValueOpcode::ImageAtomicUMin32:
|
||||
case ValueOpcode::ImageAtomicSMax32:
|
||||
case ValueOpcode::ImageAtomicUMax32:
|
||||
case ValueOpcode::ImageAtomicAnd32:
|
||||
case ValueOpcode::ImageAtomicOr32:
|
||||
|
||||
@@ -137,6 +137,9 @@ VALUE_OPCODE(SMedTri32, U32, U32, U32, U32)
|
||||
VALUE_OPCODE(UMedTri32, U32, U32, U32, U32)
|
||||
VALUE_OPCODE(SLessThan32, U1, U32, U32)
|
||||
VALUE_OPCODE(SLessThan64, U1, U64, U64)
|
||||
VALUE_OPCODE(SLessThanEqual64, U1, U64, U64)
|
||||
VALUE_OPCODE(ULessThanEqual64, U1, U64, U64)
|
||||
VALUE_OPCODE(UGreaterThanEqual64, U1, U64, U64)
|
||||
VALUE_OPCODE(ULessThan32, U1, U32, U32)
|
||||
VALUE_OPCODE(ULessThan64, U1, U64, U64)
|
||||
VALUE_OPCODE(IEqual32, U1, U32, U32)
|
||||
@@ -156,6 +159,8 @@ VALUE_OPCODE(LogicalXor, U1, U1, U1)
|
||||
VALUE_OPCODE(LogicalNot, U1, U1)
|
||||
VALUE_OPCODE(FPOrdEqual32, U1, F32, F32)
|
||||
VALUE_OPCODE(FPOrdEqual64, U1, F64, F64)
|
||||
VALUE_OPCODE(FPOrdLessThanEqual64, U1, F64, F64)
|
||||
VALUE_OPCODE(FPOrdGreaterThanEqual64, U1, F64, F64)
|
||||
VALUE_OPCODE(FPUnordEqual32, U1, F32, F32)
|
||||
VALUE_OPCODE(FPOrdNotEqual32, U1, F32, F32)
|
||||
VALUE_OPCODE(FPUnordNotEqual32, U1, F32, F32)
|
||||
@@ -174,6 +179,7 @@ VALUE_OPCODE(FPAdd32, F32, F32, F32)
|
||||
VALUE_OPCODE(FPSub32, F32, F32, F32)
|
||||
VALUE_OPCODE(FPFma32, F32, F32, F32, F32)
|
||||
VALUE_OPCODE(FPMul32, F32, F32, F32)
|
||||
VALUE_OPCODE(FPAdd64, F64, F64, F64)
|
||||
VALUE_OPCODE(FPMul64, F64, F64, F64)
|
||||
VALUE_OPCODE(FPFma64, F64, F64, F64, F64)
|
||||
VALUE_OPCODE(FPRecip64, F64, F64)
|
||||
@@ -246,6 +252,7 @@ VALUE_OPCODE(BufferAtomicUMin32, U32, BufferResource, U32, U32, U32, U32, U1)
|
||||
VALUE_OPCODE(BufferAtomicSMax32, U32, BufferResource, U32, U32, U32, U32, U1)
|
||||
VALUE_OPCODE(BufferAtomicUMax32, U32, BufferResource, U32, U32, U32, U32, U1)
|
||||
VALUE_OPCODE(BufferAtomicAnd32, U32, BufferResource, U32, U32, U32, U32, U1)
|
||||
VALUE_OPCODE(BufferAtomicAnd64, U64, BufferResource, U32, U32, U32, U64, U1)
|
||||
VALUE_OPCODE(BufferAtomicOr32, U32, BufferResource, U32, U32, U32, U32, U1)
|
||||
VALUE_OPCODE(BufferAtomicOr64, U64, BufferResource, U32, U32, U32, U64, U1)
|
||||
VALUE_OPCODE(BufferAtomicXor32, U32, BufferResource, U32, U32, U32, U32, U1)
|
||||
@@ -268,6 +275,7 @@ VALUE_OPCODE(SharedAtomicFMin32, Void, U32, U32, U32, U1)
|
||||
VALUE_OPCODE(SharedAtomicFMax32, Void, U32, U32, U32, U1)
|
||||
VALUE_OPCODE(SharedAtomicSwap32, U32, U32, U32, U1)
|
||||
VALUE_OPCODE(SharedAtomicIAdd32, U32, U32, U32, U1)
|
||||
VALUE_OPCODE(SharedAtomicIAdd64, Void, U32, U64, U1)
|
||||
VALUE_OPCODE(SharedAtomicISub32, U32, U32, U32, U1)
|
||||
VALUE_OPCODE(SharedAtomicInc32, U32, U32, U32, U1)
|
||||
VALUE_OPCODE(SharedAtomicDec32, U32, U32, U32, U1)
|
||||
@@ -292,7 +300,9 @@ VALUE_OPCODE(ImageSampleRaw, U32x4, ImageResource, SamplerResource, ImageAddress
|
||||
VALUE_OPCODE(ImageGatherRaw, U32x4, ImageResource, SamplerResource, ImageAddress)
|
||||
VALUE_OPCODE(ImageAtomicSwap32, U32, ImageResource, ImageAddress, U32, U1)
|
||||
VALUE_OPCODE(ImageAtomicIAdd32, U32, ImageResource, ImageAddress, U32, U1)
|
||||
VALUE_OPCODE(ImageAtomicSMin32, U32, ImageResource, ImageAddress, U32, U1)
|
||||
VALUE_OPCODE(ImageAtomicUMin32, U32, ImageResource, ImageAddress, U32, U1)
|
||||
VALUE_OPCODE(ImageAtomicSMax32, U32, ImageResource, ImageAddress, U32, U1)
|
||||
VALUE_OPCODE(ImageAtomicUMax32, U32, ImageResource, ImageAddress, U32, U1)
|
||||
VALUE_OPCODE(ImageAtomicAnd32, U32, ImageResource, ImageAddress, U32, U1)
|
||||
VALUE_OPCODE(ImageAtomicOr32, U32, ImageResource, ImageAddress, U32, U1)
|
||||
|
||||
@@ -575,6 +575,17 @@ void FoldInstruction(Block& block, Block::iterator instruction,
|
||||
case ValueOpcode::UGreaterThan64:
|
||||
FoldU64Compare(inst, [](uint64_t a, uint64_t b) { return a > b; });
|
||||
return;
|
||||
case ValueOpcode::ULessThanEqual64:
|
||||
FoldU64Compare(inst, [](uint64_t a, uint64_t b) { return a <= b; });
|
||||
return;
|
||||
case ValueOpcode::UGreaterThanEqual64:
|
||||
FoldU64Compare(inst, [](uint64_t a, uint64_t b) { return a >= b; });
|
||||
return;
|
||||
case ValueOpcode::SLessThanEqual64:
|
||||
FoldU64Compare(inst, [](uint64_t a, uint64_t b) {
|
||||
return std::bit_cast<int64_t>(a) <= std::bit_cast<int64_t>(b);
|
||||
});
|
||||
return;
|
||||
case ValueOpcode::SLessThan64:
|
||||
FoldU64Compare(inst, [](uint64_t a, uint64_t b) {
|
||||
return std::bit_cast<int64_t>(a) < std::bit_cast<int64_t>(b);
|
||||
|
||||
Reference in New Issue
Block a user