mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-29 16:51:20 +00:00
shader: reuse operands and remove duplicate helpers
This commit is contained in:
1 parent
9f49ac8249
commit
839c172612
9 files changed
+57
-152
No files matched your search
@@ -7,6 +7,7 @@
|
|||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
#include <span>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
|
|
||||||
namespace Libs::Graphics::ShaderRecompiler::CFG {
|
namespace Libs::Graphics::ShaderRecompiler::CFG {
|
||||||
@@ -861,15 +862,15 @@ void ComputeNaturalLoops(Graph& graph) {
|
|||||||
loop.header = edge.to;
|
loop.header = edge.to;
|
||||||
loop.latch = edge.from;
|
loop.latch = edge.from;
|
||||||
loop.continue_block = edge.from;
|
loop.continue_block = edge.from;
|
||||||
loop.body_blocks = body;
|
loop.body_blocks = std::move(body);
|
||||||
|
|
||||||
for (auto block_id: body) {
|
for (auto block_id: loop.body_blocks) {
|
||||||
const auto* block = graph.FindBlock(block_id);
|
const auto* block = graph.FindBlock(block_id);
|
||||||
if (block == nullptr) {
|
if (block == nullptr) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for (auto succ: block->successors) {
|
for (auto succ: block->successors) {
|
||||||
if (!Contains(body, succ)) {
|
if (!Contains(loop.body_blocks, succ)) {
|
||||||
AddUnique(loop.exit_blocks, succ);
|
AddUnique(loop.exit_blocks, succ);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1749,7 +1750,7 @@ bool RouteOneSharedArm(Graph& graph, uint32_t original_block_count, uint32_t out
|
|||||||
inner_is_true ? outer->terminator.false_block : outer->terminator.true_block;
|
inner_is_true ? outer->terminator.false_block : outer->terminator.true_block;
|
||||||
const auto* inner = graph.FindBlock(inner_id);
|
const auto* inner = graph.FindBlock(inner_id);
|
||||||
if (inner == nullptr || inner->inst_begin == inner->inst_end ||
|
if (inner == nullptr || inner->inst_begin == inner->inst_end ||
|
||||||
inner->predecessors != std::vector<uint32_t> {outer_id} ||
|
inner->predecessors.size() != 1u || inner->predecessors.front() != outer_id ||
|
||||||
inner->terminator.kind != TerminatorKind::ConditionalBranch ||
|
inner->terminator.kind != TerminatorKind::ConditionalBranch ||
|
||||||
IsInnermostLoopControlConditional(graph, *inner)) {
|
IsInnermostLoopControlConditional(graph, *inner)) {
|
||||||
continue;
|
continue;
|
||||||
@@ -1941,9 +1942,9 @@ Graph BuildGraph(const Decoder::Program& program) {
|
|||||||
graph, FailureKind::InvalidBranchTarget, UINT32_MAX,
|
graph, FailureKind::InvalidBranchTarget, UINT32_MAX,
|
||||||
fmt::format("unsupported dynamic S_SETPC_B64 at pc 0x{:08x}", inst.pc));
|
fmt::format("unsupported dynamic S_SETPC_B64 at pc 0x{:08x}", inst.pc));
|
||||||
}
|
}
|
||||||
const auto& target_pcs = target_info.indirect
|
const auto target_pcs = target_info.indirect
|
||||||
? target_info.target_pcs
|
? std::span<const uint32_t>(target_info.target_pcs)
|
||||||
: std::vector<uint32_t> {target_info.target};
|
: std::span<const uint32_t>(&target_info.target, 1);
|
||||||
for (const auto target: target_pcs) {
|
for (const auto target: target_pcs) {
|
||||||
if (!IsValidTarget(target, instruction_pcs, first_pc, end_pc)) {
|
if (!IsValidTarget(target, instruction_pcs, first_pc, end_pc)) {
|
||||||
ExitBuildFailure(
|
ExitBuildFailure(
|
||||||
@@ -2103,11 +2104,7 @@ Graph BuildGraph(const Decoder::Program& program) {
|
|||||||
}
|
}
|
||||||
SortUnique(graph.code_table_load_pcs);
|
SortUnique(graph.code_table_load_pcs);
|
||||||
|
|
||||||
ComputeDominators(graph);
|
RecomputeAnalyses(graph);
|
||||||
ComputePostDominators(graph);
|
|
||||||
ComputeBackEdges(graph);
|
|
||||||
ComputeNaturalLoops(graph);
|
|
||||||
ComputeComponents(graph);
|
|
||||||
|
|
||||||
if (indirect_setpc) {
|
if (indirect_setpc) {
|
||||||
graph.irreducible = true;
|
graph.irreducible = true;
|
||||||
|
|||||||
@@ -714,57 +714,7 @@ void DecodeVop1Dpp(uint32_t pc, std::span<const uint32_t> code, uint32_t word_in
|
|||||||
ReadLiteralOperands(code, word_index, inst);
|
ReadLiteralOperands(code, word_index, inst);
|
||||||
}
|
}
|
||||||
|
|
||||||
using Vop1ModifierDecodeFn = void (*)(uint32_t pc, std::span<const uint32_t> code,
|
bool IsVop2FloatOpcode(Opcode opcode) {
|
||||||
uint32_t word_index, uint32_t opcode, uint32_t vdst,
|
|
||||||
Instruction& inst);
|
|
||||||
|
|
||||||
struct Vop1ModifierDecoder {
|
|
||||||
uint32_t escape = 0;
|
|
||||||
Vop1ModifierDecodeFn decode = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
constexpr Vop1ModifierDecoder VOP1_MODIFIER_DECODERS[] = {
|
|
||||||
{249u, DecodeVop1Sdwa},
|
|
||||||
{250u, DecodeVop1Dpp},
|
|
||||||
};
|
|
||||||
|
|
||||||
bool TryDecodeVop1Modifier(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index,
|
|
||||||
uint32_t src0, uint32_t opcode, uint32_t vdst, Instruction& inst) {
|
|
||||||
for (const auto& decoder: VOP1_MODIFIER_DECODERS) {
|
|
||||||
if (decoder.escape == src0) {
|
|
||||||
decoder.decode(pc, code, word_index, opcode, vdst, inst);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsVop2FloatSourceOpcode(Opcode opcode) {
|
|
||||||
switch (opcode) {
|
|
||||||
case Opcode::V_ADD_F32:
|
|
||||||
case Opcode::V_SUB_F32:
|
|
||||||
case Opcode::V_SUBREV_F32:
|
|
||||||
case Opcode::V_MUL_F32:
|
|
||||||
case Opcode::V_MIN_F32:
|
|
||||||
case Opcode::V_MAX_F32:
|
|
||||||
case Opcode::V_MAC_F32:
|
|
||||||
case Opcode::V_MADMK_F32:
|
|
||||||
case Opcode::V_MADAK_F32:
|
|
||||||
case Opcode::V_CVT_PKRTZ_F16_F32:
|
|
||||||
case Opcode::V_ADD_F16:
|
|
||||||
case Opcode::V_SUB_F16:
|
|
||||||
case Opcode::V_SUBREV_F16:
|
|
||||||
case Opcode::V_MUL_F16:
|
|
||||||
case Opcode::V_FMAC_F16:
|
|
||||||
case Opcode::V_FMAMK_F16:
|
|
||||||
case Opcode::V_FMAAK_F16:
|
|
||||||
case Opcode::V_MAX_F16:
|
|
||||||
case Opcode::V_MIN_F16: return true;
|
|
||||||
default: return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsVop2FloatResultOpcode(Opcode opcode) {
|
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
case Opcode::V_ADD_F32:
|
case Opcode::V_ADD_F32:
|
||||||
case Opcode::V_SUB_F32:
|
case Opcode::V_SUB_F32:
|
||||||
@@ -975,12 +925,12 @@ bool ValidateVop2Sdwa(Instruction& inst, uint32_t opcode, const Vop2SdwaFields&
|
|||||||
SetUnsupported(inst, Family::VOP2, opcode, "VOP2 SDWA selector is invalid");
|
SetUnsupported(inst, Family::VOP2, opcode, "VOP2 SDWA selector is invalid");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if ((fields.clamp != 0u || fields.omod != 0u) && !IsVop2FloatResultOpcode(inst.opcode)) {
|
if ((fields.clamp != 0u || fields.omod != 0u) && !IsVop2FloatOpcode(inst.opcode)) {
|
||||||
SetUnsupported(inst, Family::VOP2, opcode, "VOP2 SDWA output modifiers are not supported");
|
SetUnsupported(inst, Family::VOP2, opcode, "VOP2 SDWA output modifiers are not supported");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (IsFullWidthVop2Sdwa(fields)) {
|
if (IsFullWidthVop2Sdwa(fields)) {
|
||||||
if (!IsVop2FloatSourceOpcode(inst.opcode) && inst.opcode != Opcode::V_CNDMASK_B32 &&
|
if (!IsVop2FloatOpcode(inst.opcode) && inst.opcode != Opcode::V_CNDMASK_B32 &&
|
||||||
(fields.src0_neg != 0u || fields.src0_abs != 0u || fields.src1_neg != 0u ||
|
(fields.src0_neg != 0u || fields.src0_abs != 0u || fields.src1_neg != 0u ||
|
||||||
fields.src1_abs != 0u)) {
|
fields.src1_abs != 0u)) {
|
||||||
SetUnsupported(inst, Family::VOP2, opcode,
|
SetUnsupported(inst, Family::VOP2, opcode,
|
||||||
@@ -1098,7 +1048,7 @@ void DecodeVop2Dpp(uint32_t pc, std::span<const uint32_t> code, uint32_t word_in
|
|||||||
inst.src1.negate_hi = inst.src1.negate;
|
inst.src1.negate_hi = inst.src1.negate;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsVop2FloatSourceOpcode(inst.opcode) && !packed_fmac &&
|
if (!IsVop2FloatOpcode(inst.opcode) && !packed_fmac &&
|
||||||
(inst.src0.negate || inst.src0.absolute || inst.src1.negate || inst.src1.absolute)) {
|
(inst.src0.negate || inst.src0.absolute || inst.src1.negate || inst.src1.absolute)) {
|
||||||
SetUnsupported(inst, Family::VOP2, opcode,
|
SetUnsupported(inst, Family::VOP2, opcode,
|
||||||
"VOP2 DPP integer source modifiers are not supported");
|
"VOP2 DPP integer source modifiers are not supported");
|
||||||
@@ -1107,32 +1057,6 @@ void DecodeVop2Dpp(uint32_t pc, std::span<const uint32_t> code, uint32_t word_in
|
|||||||
FinalizeVop2Instruction(code, word_index, inst);
|
FinalizeVop2Instruction(code, word_index, inst);
|
||||||
}
|
}
|
||||||
|
|
||||||
using Vop2ModifierDecodeFn = void (*)(uint32_t pc, std::span<const uint32_t> code,
|
|
||||||
uint32_t word_index, uint32_t opcode, uint32_t vdst,
|
|
||||||
uint32_t vsrc1, Instruction& inst);
|
|
||||||
|
|
||||||
struct Vop2ModifierDecoder {
|
|
||||||
uint32_t escape = 0;
|
|
||||||
Vop2ModifierDecodeFn decode = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
constexpr Vop2ModifierDecoder VOP2_MODIFIER_DECODERS[] = {
|
|
||||||
{249u, DecodeVop2Sdwa},
|
|
||||||
{250u, DecodeVop2Dpp},
|
|
||||||
};
|
|
||||||
|
|
||||||
bool TryDecodeVop2Modifier(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index,
|
|
||||||
uint32_t src0, uint32_t opcode, uint32_t vdst, uint32_t vsrc1,
|
|
||||||
Instruction& inst) {
|
|
||||||
for (const auto& decoder: VOP2_MODIFIER_DECODERS) {
|
|
||||||
if (decoder.escape == src0) {
|
|
||||||
decoder.decode(pc, code, word_index, opcode, vdst, vsrc1, inst);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct VopcSdwaFields {
|
struct VopcSdwaFields {
|
||||||
uint32_t src0 = 0;
|
uint32_t src0 = 0;
|
||||||
uint32_t sdst = 0;
|
uint32_t sdst = 0;
|
||||||
@@ -1543,8 +1467,10 @@ void DecodeVop2(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index
|
|||||||
SetUnsupported(inst, Family::VOP2, opcode, "VOP2 opcode is not implemented");
|
SetUnsupported(inst, Family::VOP2, opcode, "VOP2 opcode is not implemented");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (TryDecodeVop2Modifier(pc, code, word_index, src0, opcode, vdst, vsrc1, inst)) {
|
switch (src0) {
|
||||||
return;
|
case 249u: DecodeVop2Sdwa(pc, code, word_index, opcode, vdst, vsrc1, inst); return;
|
||||||
|
case 250u: DecodeVop2Dpp(pc, code, word_index, opcode, vdst, vsrc1, inst); return;
|
||||||
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
DecodeVectorGpr(vdst, inst.dst);
|
DecodeVectorGpr(vdst, inst.dst);
|
||||||
@@ -1575,8 +1501,10 @@ void DecodeVop1(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index
|
|||||||
inst.src_count = 0;
|
inst.src_count = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (TryDecodeVop1Modifier(pc, code, word_index, src0, opcode, vdst, inst)) {
|
switch (src0) {
|
||||||
return;
|
case 249u: DecodeVop1Sdwa(pc, code, word_index, opcode, vdst, inst); return;
|
||||||
|
case 250u: DecodeVop1Dpp(pc, code, word_index, opcode, vdst, inst); return;
|
||||||
|
default: break;
|
||||||
}
|
}
|
||||||
const bool scalar_dst = UsesScalarDestination(inst.opcode);
|
const bool scalar_dst = UsesScalarDestination(inst.opcode);
|
||||||
if (scalar_dst) {
|
if (scalar_dst) {
|
||||||
|
|||||||
@@ -89,10 +89,10 @@ void Translator::V_CVT_16_F16(const Decoder::Instruction& inst, bool signed_valu
|
|||||||
if (signed_value) {
|
if (signed_value) {
|
||||||
const auto converted =
|
const auto converted =
|
||||||
ConvertF32ToI32Saturated(value, -32768.0f, 32768.0f, 32767.0f, 0xffff8000u, 0x7fffu);
|
ConvertF32ToI32Saturated(value, -32768.0f, 32768.0f, 32767.0f, 0xffff8000u, 0x7fffu);
|
||||||
WriteU16(DestinationOperand(inst), ir.BitwiseAnd(converted, IR::U32(IR::Value(0xffffu))));
|
Write16Bits(DestinationOperand(inst), ir.BitwiseAnd(converted, IR::U32(IR::Value(0xffffu))));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
WriteU16(DestinationOperand(inst),
|
Write16Bits(DestinationOperand(inst),
|
||||||
ConvertF32ToU32Saturated(value, 65536.0f, 65535.0f, 0xffffu));
|
ConvertF32ToU32Saturated(value, 65536.0f, 65535.0f, 0xffffu));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ bool Translator::Float16Unary(const Decoder::Instruction& inst, IR::ValueOpcode
|
|||||||
result = ApplyF32ResultModifiers(inst.dst, result);
|
result = ApplyF32ResultModifiers(inst.dst, result);
|
||||||
const auto bits = PackHalf2x16(result, IR::F32(IR::Value::F32(0.0f)));
|
const auto bits = PackHalf2x16(result, IR::F32(IR::Value::F32(0.0f)));
|
||||||
const auto invalid = IR::U32(IR::Value(inst.dst.clamp ? 0u : 0xfe00u));
|
const auto invalid = IR::U32(IR::Value(inst.dst.clamp ? 0u : 0xfe00u));
|
||||||
WriteU16(DestinationOperand(inst), ir.Select(negative, invalid, bits));
|
Write16Bits(DestinationOperand(inst), ir.Select(negative, invalid, bits));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,7 +95,7 @@ bool Translator::Float16Trig(const Decoder::Instruction& inst, IR::ValueOpcode o
|
|||||||
result = ApplyF32ResultModifiers(inst.dst, result);
|
result = ApplyF32ResultModifiers(inst.dst, result);
|
||||||
const auto bits = PackHalf2x16(result, IR::F32(IR::Value::F32(0.0f)));
|
const auto bits = PackHalf2x16(result, IR::F32(IR::Value::F32(0.0f)));
|
||||||
const auto invalid = IR::U32(IR::Value(inst.dst.clamp ? 0u : 0xfe00u));
|
const auto invalid = IR::U32(IR::Value(inst.dst.clamp ? 0u : 0xfe00u));
|
||||||
WriteU16(DestinationOperand(inst), ir.Select(infinite, invalid, bits));
|
Write16Bits(DestinationOperand(inst), ir.Select(infinite, invalid, bits));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,7 +111,7 @@ bool Translator::Float16Ternary(const Decoder::Instruction& inst, IR::ValueOpcod
|
|||||||
bool accumulator, bool mix) {
|
bool accumulator, bool mix) {
|
||||||
std::array<IR::Value, 3> args;
|
std::array<IR::Value, 3> args;
|
||||||
for (uint32_t index = 0; index < args.size(); index++) {
|
for (uint32_t index = 0; index < args.size(); index++) {
|
||||||
const auto operand = accumulator && index == 2u ? inst.dst : SourceAt(inst, index);
|
const auto& operand = accumulator && index == 2u ? inst.dst : SourceAt(inst, index);
|
||||||
args[index] = mix ? IR::Value(ReadMixF32(operand)) : IR::Value(ReadF16AsF32(operand));
|
args[index] = mix ? IR::Value(ReadMixF32(operand)) : IR::Value(ReadF16AsF32(operand));
|
||||||
}
|
}
|
||||||
WriteF16(DestinationOperand(inst), IR::F32(ir.Emit(opcode, {args[0], args[1], args[2]})));
|
WriteF16(DestinationOperand(inst), IR::F32(ir.Emit(opcode, {args[0], args[1], args[2]})));
|
||||||
@@ -128,7 +128,7 @@ bool Translator::FloatBinary(const Decoder::Instruction& inst, IR::ValueOpcode o
|
|||||||
bool reverse) {
|
bool reverse) {
|
||||||
std::array<IR::Value, 2> args;
|
std::array<IR::Value, 2> args;
|
||||||
for (uint32_t index = 0; index < args.size(); index++) {
|
for (uint32_t index = 0; index < args.size(); index++) {
|
||||||
const auto operand = SourceAt(inst, reverse ? 1u - index : index);
|
const auto& operand = SourceAt(inst, reverse ? 1u - index : index);
|
||||||
args[index] = ReadOperand(operand, IR::ArgTypeOf(opcode, index));
|
args[index] = ReadOperand(operand, IR::ArgTypeOf(opcode, index));
|
||||||
}
|
}
|
||||||
WriteOperand(DestinationOperand(inst), ir.Emit(opcode, {args[0], args[1]}));
|
WriteOperand(DestinationOperand(inst), ir.Emit(opcode, {args[0], args[1]}));
|
||||||
@@ -139,7 +139,7 @@ bool Translator::FloatTernary(const Decoder::Instruction& inst, IR::ValueOpcode
|
|||||||
bool accumulator, bool mix) {
|
bool accumulator, bool mix) {
|
||||||
std::array<IR::Value, 3> args;
|
std::array<IR::Value, 3> args;
|
||||||
for (uint32_t index = 0; index < args.size(); index++) {
|
for (uint32_t index = 0; index < args.size(); index++) {
|
||||||
const auto operand = accumulator && index == 2u ? inst.dst : SourceAt(inst, index);
|
const auto& operand = accumulator && index == 2u ? inst.dst : SourceAt(inst, index);
|
||||||
const auto type = IR::ArgTypeOf(opcode, index);
|
const auto type = IR::ArgTypeOf(opcode, index);
|
||||||
args[index] = type == IR::Type::F32 && mix ? IR::Value(ReadMixF32(operand))
|
args[index] = type == IR::Type::F32 && mix ? IR::Value(ReadMixF32(operand))
|
||||||
: ReadOperand(operand, type);
|
: ReadOperand(operand, type);
|
||||||
@@ -203,9 +203,6 @@ bool Translator::V_CUBEMA_F32(const Decoder::Instruction& inst) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Translator::FloatCube(const Decoder::Instruction& inst, uint32_t result_kind) {
|
bool Translator::FloatCube(const Decoder::Instruction& inst, uint32_t result_kind) {
|
||||||
const auto select_f32 = [&](IR::U1 condition, IR::F32 true_value, IR::F32 false_value) {
|
|
||||||
return IR::F32(ir.Emit(IR::ValueOpcode::SelectF32, {condition, true_value, false_value}));
|
|
||||||
};
|
|
||||||
const auto x = ReadMixF32(inst.src0);
|
const auto x = ReadMixF32(inst.src0);
|
||||||
const auto y = ReadMixF32(inst.src1);
|
const auto y = ReadMixF32(inst.src1);
|
||||||
const auto z = ReadMixF32(inst.src2);
|
const auto z = ReadMixF32(inst.src2);
|
||||||
@@ -223,18 +220,18 @@ bool Translator::FloatCube(const Decoder::Instruction& inst, uint32_t result_kin
|
|||||||
const auto y_neg = IR::U1(ir.Emit(IR::ValueOpcode::FPOrdLessThan32, {y, IR::Value::F32(0.0f)}));
|
const auto y_neg = IR::U1(ir.Emit(IR::ValueOpcode::FPOrdLessThan32, {y, IR::Value::F32(0.0f)}));
|
||||||
const auto z_neg = IR::U1(ir.Emit(IR::ValueOpcode::FPOrdLessThan32, {z, IR::Value::F32(0.0f)}));
|
const auto z_neg = IR::U1(ir.Emit(IR::ValueOpcode::FPOrdLessThan32, {z, IR::Value::F32(0.0f)}));
|
||||||
const auto select_face = [&](IR::F32 x_value, IR::F32 y_value, IR::F32 z_value) {
|
const auto select_face = [&](IR::F32 x_value, IR::F32 y_value, IR::F32 z_value) {
|
||||||
return select_f32(z_face, z_value, select_f32(y_face, y_value, x_value));
|
return SelectF32(z_face, z_value, SelectF32(y_face, y_value, x_value));
|
||||||
};
|
};
|
||||||
IR::F32 result;
|
IR::F32 result;
|
||||||
switch (result_kind) {
|
switch (result_kind) {
|
||||||
case 0u:
|
case 0u:
|
||||||
result = select_face(
|
result = select_face(
|
||||||
select_f32(x_neg, IR::F32(IR::Value::F32(1.0f)), IR::F32(IR::Value::F32(0.0f))),
|
SelectF32(x_neg, IR::F32(IR::Value::F32(1.0f)), IR::F32(IR::Value::F32(0.0f))),
|
||||||
select_f32(y_neg, IR::F32(IR::Value::F32(3.0f)), IR::F32(IR::Value::F32(2.0f))),
|
SelectF32(y_neg, IR::F32(IR::Value::F32(3.0f)), IR::F32(IR::Value::F32(2.0f))),
|
||||||
select_f32(z_neg, IR::F32(IR::Value::F32(5.0f)), IR::F32(IR::Value::F32(4.0f))));
|
SelectF32(z_neg, IR::F32(IR::Value::F32(5.0f)), IR::F32(IR::Value::F32(4.0f))));
|
||||||
break;
|
break;
|
||||||
case 1u: result = select_face(select_f32(x_neg, z, nz), x, select_f32(z_neg, nx, x)); break;
|
case 1u: result = select_face(SelectF32(x_neg, z, nz), x, SelectF32(z_neg, nx, x)); break;
|
||||||
case 2u: result = select_face(ny, select_f32(y_neg, nz, z), ny); break;
|
case 2u: result = select_face(ny, SelectF32(y_neg, nz, z), ny); break;
|
||||||
case 3u: {
|
case 3u: {
|
||||||
const auto two = IR::F32(IR::Value::F32(2.0f));
|
const auto two = IR::F32(IR::Value::F32(2.0f));
|
||||||
result = select_face(IR::F32(ir.Emit(IR::ValueOpcode::FPMul32, {x, two})),
|
result = select_face(IR::F32(ir.Emit(IR::ValueOpcode::FPMul32, {x, two})),
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ bool Translator::Integer16Shift(const Decoder::Instruction& inst, IR::ValueOpcod
|
|||||||
const auto value = ReadU16AsU32(inst.src1, arithmetic);
|
const auto value = ReadU16AsU32(inst.src1, arithmetic);
|
||||||
const auto count = ir.BitwiseAnd(ReadU16AsU32(inst.src0, false), IR::U32(IR::Value(15u)));
|
const auto count = ir.BitwiseAnd(ReadU16AsU32(inst.src0, false), IR::U32(IR::Value(15u)));
|
||||||
const auto result = IR::U32(ir.Emit(opcode, {value, count}));
|
const auto result = IR::U32(ir.Emit(opcode, {value, count}));
|
||||||
WriteU16(DestinationOperand(inst), ir.BitwiseAnd(result, IR::U32(IR::Value(0xffffu))));
|
Write16Bits(DestinationOperand(inst), ir.BitwiseAnd(result, IR::U32(IR::Value(0xffffu))));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@ bool Translator::Integer16Binary(const Decoder::Instruction& inst, IR::ValueOpco
|
|||||||
const auto lhs = ReadU16AsU32(inst.src0, sign);
|
const auto lhs = ReadU16AsU32(inst.src0, sign);
|
||||||
const auto rhs = ReadU16AsU32(inst.src1, sign);
|
const auto rhs = ReadU16AsU32(inst.src1, sign);
|
||||||
const auto result = IR::U32(ir.Emit(opcode, {lhs, rhs}));
|
const auto result = IR::U32(ir.Emit(opcode, {lhs, rhs}));
|
||||||
WriteU16(DestinationOperand(inst), ir.BitwiseAnd(result, IR::U32(IR::Value(0xffffu))));
|
Write16Bits(DestinationOperand(inst), ir.BitwiseAnd(result, IR::U32(IR::Value(0xffffu))));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -26,7 +26,7 @@ bool Translator::V_MED3_I16(const Decoder::Instruction& inst) {
|
|||||||
const auto result = IR::U32(ir.Emit(
|
const auto result = IR::U32(ir.Emit(
|
||||||
IR::ValueOpcode::SMedTri32, {ReadU16AsU32(inst.src0, true), ReadU16AsU32(inst.src1, true),
|
IR::ValueOpcode::SMedTri32, {ReadU16AsU32(inst.src0, true), ReadU16AsU32(inst.src1, true),
|
||||||
ReadU16AsU32(inst.src2, true)}));
|
ReadU16AsU32(inst.src2, true)}));
|
||||||
WriteU16(DestinationOperand(inst), ir.BitwiseAnd(result, IR::U32(IR::Value(0xffffu))));
|
Write16Bits(DestinationOperand(inst), ir.BitwiseAnd(result, IR::U32(IR::Value(0xffffu))));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,7 +143,7 @@ bool Translator::SimpleInteger(const Decoder::Instruction& inst, IR::ValueOpcode
|
|||||||
std::array<IR::Value, 3> args;
|
std::array<IR::Value, 3> args;
|
||||||
for (uint32_t index = 0; index < inst.src_count; index++) {
|
for (uint32_t index = 0; index < inst.src_count; index++) {
|
||||||
const auto arg_type = IR::ArgTypeOf(opcode, index);
|
const auto arg_type = IR::ArgTypeOf(opcode, index);
|
||||||
const auto operand = SourceAt(inst, reverse && index < 2u ? 1u - index : index);
|
const auto& operand = SourceAt(inst, reverse && index < 2u ? 1u - index : index);
|
||||||
args[index] = ReadOperand(operand, arg_type == IR::Type::Void ? type : arg_type);
|
args[index] = ReadOperand(operand, arg_type == IR::Type::Void ? type : arg_type);
|
||||||
if (mask_shift_count && index == 1u) {
|
if (mask_shift_count && index == 1u) {
|
||||||
args[index] = ir.BitwiseAnd(IR::U32(args[index]), IR::U32(IR::Value(31u)));
|
args[index] = ir.BitwiseAnd(IR::U32(args[index]), IR::U32(IR::Value(31u)));
|
||||||
@@ -563,10 +563,8 @@ bool Translator::PackB16(const Decoder::Instruction& inst, bool high0, bool high
|
|||||||
: ReadU32(inst.src0);
|
: ReadU32(inst.src0);
|
||||||
const auto hi = high1 ? ir.ShiftRightLogical(ReadU32(inst.src1), IR::U32(IR::Value(16u)))
|
const auto hi = high1 ? ir.ShiftRightLogical(ReadU32(inst.src1), IR::U32(IR::Value(16u)))
|
||||||
: ReadU32(inst.src1);
|
: ReadU32(inst.src1);
|
||||||
const auto low_bits = ir.BitwiseAnd(lo, IR::U32(IR::Value(0xffffu)));
|
const auto result = PackU16Lanes(lo, hi);
|
||||||
const auto high_bits = ir.ShiftLeftLogical(ir.BitwiseAnd(hi, IR::U32(IR::Value(0xffffu))),
|
WriteOperand(DestinationOperand(inst), result);
|
||||||
IR::U32(IR::Value(16u)));
|
|
||||||
WriteOperand(DestinationOperand(inst), ir.BitwiseOr(low_bits, high_bits));
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -71,16 +71,22 @@ ResourceKind FlatSegmentResourceKind(uint32_t segment) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsScalarAddressLoad(Decoder::Opcode opcode) {
|
||||||
|
switch (opcode) {
|
||||||
|
case Decoder::Opcode::S_LOAD_DWORD:
|
||||||
|
case Decoder::Opcode::S_LOAD_DWORDX2:
|
||||||
|
case Decoder::Opcode::S_LOAD_DWORDX4:
|
||||||
|
case Decoder::Opcode::S_LOAD_DWORDX8:
|
||||||
|
case Decoder::Opcode::S_LOAD_DWORDX16: return true;
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ResourceKind MemoryKind(const Decoder::Instruction& decoded) {
|
ResourceKind MemoryKind(const Decoder::Instruction& decoded) {
|
||||||
switch (decoded.family) {
|
switch (decoded.family) {
|
||||||
case Decoder::Family::SMEM:
|
case Decoder::Family::SMEM:
|
||||||
return decoded.opcode == Decoder::Opcode::S_LOAD_DWORD ||
|
return IsScalarAddressLoad(decoded.opcode) ? ResourceKind::ScalarAddress
|
||||||
decoded.opcode == Decoder::Opcode::S_LOAD_DWORDX2 ||
|
: ResourceKind::ScalarBuffer;
|
||||||
decoded.opcode == Decoder::Opcode::S_LOAD_DWORDX4 ||
|
|
||||||
decoded.opcode == Decoder::Opcode::S_LOAD_DWORDX8 ||
|
|
||||||
decoded.opcode == Decoder::Opcode::S_LOAD_DWORDX16
|
|
||||||
? ResourceKind::ScalarAddress
|
|
||||||
: ResourceKind::ScalarBuffer;
|
|
||||||
case Decoder::Family::MUBUF:
|
case Decoder::Family::MUBUF:
|
||||||
case Decoder::Family::MTBUF: return ResourceKind::Buffer;
|
case Decoder::Family::MTBUF: return ResourceKind::Buffer;
|
||||||
case Decoder::Family::FLAT: return FlatSegmentResourceKind(decoded.memory_segment);
|
case Decoder::Family::FLAT: return FlatSegmentResourceKind(decoded.memory_segment);
|
||||||
@@ -146,16 +152,6 @@ IR::MemoryInfo MemoryInfoFromDecoded(const Decoder::Instruction& decoded) {
|
|||||||
return memory;
|
return memory;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsScalarAddressLoad(Decoder::Opcode opcode) {
|
|
||||||
switch (opcode) {
|
|
||||||
case Decoder::Opcode::S_LOAD_DWORD:
|
|
||||||
case Decoder::Opcode::S_LOAD_DWORDX2:
|
|
||||||
case Decoder::Opcode::S_LOAD_DWORDX4:
|
|
||||||
case Decoder::Opcode::S_LOAD_DWORDX8:
|
|
||||||
case Decoder::Opcode::S_LOAD_DWORDX16: return true;
|
|
||||||
default: return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsScalarBufferLoad(Decoder::Opcode opcode) {
|
bool IsScalarBufferLoad(Decoder::Opcode opcode) {
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
namespace Libs::Graphics::ShaderRecompiler::Frontend {
|
namespace Libs::Graphics::ShaderRecompiler::Frontend {
|
||||||
|
|
||||||
Decoder::Operand Translator::SourceAt(const Decoder::Instruction& inst, uint32_t index) {
|
const Decoder::Operand& Translator::SourceAt(const Decoder::Instruction& inst, uint32_t index) {
|
||||||
switch (index) {
|
switch (index) {
|
||||||
case 0: return inst.src0;
|
case 0: return inst.src0;
|
||||||
case 1: return inst.src1;
|
case 1: return inst.src1;
|
||||||
@@ -25,7 +25,7 @@ Decoder::Operand Translator::DestinationOperand(const Decoder::Instruction& inst
|
|||||||
return destination;
|
return destination;
|
||||||
}
|
}
|
||||||
for (uint32_t index = 0; index < std::min(inst.src_count, 3u); index++) {
|
for (uint32_t index = 0; index < std::min(inst.src_count, 3u); index++) {
|
||||||
const auto source = SourceAt(inst, index);
|
const auto& source = SourceAt(inst, index);
|
||||||
if (!source.dpp) {
|
if (!source.dpp) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -440,10 +440,6 @@ void Translator::WriteF16(const Decoder::Operand& operand, IR::F32 value) {
|
|||||||
Write16Bits(operand, bits);
|
Write16Bits(operand, bits);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Translator::WriteU16(const Decoder::Operand& operand, IR::U32 value) {
|
|
||||||
Write16Bits(operand, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
IR::U32 Translator::ReadU32(const Decoder::Operand& operand) {
|
IR::U32 Translator::ReadU32(const Decoder::Operand& operand) {
|
||||||
return IR::U32(ReadOperand(operand, IR::Type::U32));
|
return IR::U32(ReadOperand(operand, IR::Type::U32));
|
||||||
}
|
}
|
||||||
@@ -604,10 +600,6 @@ IR::U1 Translator::ThreadBit(const std::array<IR::U32, 2>& mask) {
|
|||||||
IR::U32(IR::Value(0u)));
|
IR::U32(IR::Value(0u)));
|
||||||
}
|
}
|
||||||
|
|
||||||
IR::U1 Translator::ReadCondition(const Decoder::Operand& operand) {
|
|
||||||
return IR::U1(ReadOperand(operand, IR::Type::U1));
|
|
||||||
}
|
|
||||||
|
|
||||||
IR::U32 Translator::ConditionBit(const Decoder::Operand& operand) {
|
IR::U32 Translator::ConditionBit(const Decoder::Operand& operand) {
|
||||||
return ir.Select(ReadMask(operand), IR::U32(IR::Value(1u)), IR::U32(IR::Value(0u)));
|
return ir.Select(ReadMask(operand), IR::U32(IR::Value(1u)), IR::U32(IR::Value(0u)));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ public:
|
|||||||
void AddBranchCondition(const CFG::BasicBlock& source, IR::BlockInfo& info);
|
void AddBranchCondition(const CFG::BasicBlock& source, IR::BlockInfo& info);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Decoder::Operand SourceAt(const Decoder::Instruction& inst, uint32_t index);
|
const Decoder::Operand& SourceAt(const Decoder::Instruction& inst, uint32_t index);
|
||||||
Decoder::Operand DestinationOperand(const Decoder::Instruction& inst);
|
Decoder::Operand DestinationOperand(const Decoder::Instruction& inst);
|
||||||
Decoder::Operand OffsetOperand(const Decoder::Operand& operand, uint32_t offset);
|
Decoder::Operand OffsetOperand(const Decoder::Operand& operand, uint32_t offset);
|
||||||
Decoder::Operand ScalarDestinationOperand(const Decoder::Operand& operand, uint32_t offset);
|
Decoder::Operand ScalarDestinationOperand(const Decoder::Operand& operand, uint32_t offset);
|
||||||
@@ -35,7 +35,6 @@ private:
|
|||||||
IR::U32 PackHalf2x16(IR::F32 low, IR::F32 high);
|
IR::U32 PackHalf2x16(IR::F32 low, IR::F32 high);
|
||||||
void Write16Bits(const Decoder::Operand& operand, IR::U32 value);
|
void Write16Bits(const Decoder::Operand& operand, IR::U32 value);
|
||||||
void WriteF16(const Decoder::Operand& operand, IR::F32 value);
|
void WriteF16(const Decoder::Operand& operand, IR::F32 value);
|
||||||
void WriteU16(const Decoder::Operand& operand, IR::U32 value);
|
|
||||||
IR::U32 ReadU32(const Decoder::Operand& operand);
|
IR::U32 ReadU32(const Decoder::Operand& operand);
|
||||||
std::array<IR::U32, 2> ReadU32Pair(const Decoder::Operand& operand);
|
std::array<IR::U32, 2> ReadU32Pair(const Decoder::Operand& operand);
|
||||||
IR::U64 ReadU64(const Decoder::Operand& operand);
|
IR::U64 ReadU64(const Decoder::Operand& operand);
|
||||||
@@ -48,7 +47,6 @@ private:
|
|||||||
IR::U32 ReadF16LaneBits(const Decoder::Operand& operand, bool high_lane);
|
IR::U32 ReadF16LaneBits(const Decoder::Operand& operand, bool high_lane);
|
||||||
std::array<IR::U32, 2> ExtractU64(IR::U64 value);
|
std::array<IR::U32, 2> ExtractU64(IR::U64 value);
|
||||||
void WriteU32Pair(const Decoder::Operand& operand, const std::array<IR::U32, 2>& value);
|
void WriteU32Pair(const Decoder::Operand& operand, const std::array<IR::U32, 2>& value);
|
||||||
IR::U1 ReadCondition(const Decoder::Operand& operand);
|
|
||||||
IR::U32 ConditionBit(const Decoder::Operand& operand);
|
IR::U32 ConditionBit(const Decoder::Operand& operand);
|
||||||
IR::U1 ReadMask(const Decoder::Operand& operand);
|
IR::U1 ReadMask(const Decoder::Operand& operand);
|
||||||
IR::U1 ReadMaskValid(const Decoder::Operand& operand);
|
IR::U1 ReadMaskValid(const Decoder::Operand& operand);
|
||||||
|
|||||||
@@ -280,8 +280,7 @@ private:
|
|||||||
return finish(false);
|
return finish(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (op == ValueOpcode::GetBufferResource || op == ValueOpcode::GetImageResource ||
|
if (IsDescriptorHandle(op)) {
|
||||||
op == ValueOpcode::GetSamplerResource || op == ValueOpcode::GetAddressResource) {
|
|
||||||
size_t expected = 4u;
|
size_t expected = 4u;
|
||||||
if (op == ValueOpcode::GetImageResource) {
|
if (op == ValueOpcode::GetImageResource) {
|
||||||
expected = 8u;
|
expected = 8u;
|
||||||
|
|||||||
Reference in new issue
Block a user