[shader_recompiler] Rewrite ISBERD
This commit is contained in:
parent
191e4c75a1
commit
035f9d80b7
3 changed files with 91 additions and 100 deletions
|
@ -271,40 +271,4 @@ void TranslatorVisitor::ResetOFlag() {
|
||||||
SetOFlag(ir.Imm1(false));
|
SetOFlag(ir.Imm1(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
IR::U32 TranslatorVisitor::apply_ISBERD_shift(IR::U32 result, Isberd::Shift shift_value) {
|
|
||||||
if (shift_value != Isberd::Shift::Default) {
|
|
||||||
return ir.ShiftLeftLogical(result, ir.Imm32(1));
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
IR::U32 TranslatorVisitor::apply_ISBERD_size_read(IR::U32 address, Isberd::SZ sz) {
|
|
||||||
switch (sz) {
|
|
||||||
case Isberd::SZ::U8:
|
|
||||||
return ir.LoadGlobalU8(ir.UConvert(64, address));
|
|
||||||
case Isberd::SZ::U16:
|
|
||||||
return ir.LoadGlobalU16(ir.UConvert(64, address));
|
|
||||||
case Isberd::SZ::U32:
|
|
||||||
case Isberd::SZ::F32:
|
|
||||||
return ir.LoadGlobal32(ir.UConvert(64, address));
|
|
||||||
default:
|
|
||||||
UNREACHABLE();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IR::U32 TranslatorVisitor::compute_ISBERD_address(IR::Reg src_reg, u32 src_reg_num, u32 imm, u64 skew_value) {
|
|
||||||
IR::U32 address{};
|
|
||||||
if (src_reg_num == 0xFF) {
|
|
||||||
address = ir.Imm32(imm);
|
|
||||||
} else {
|
|
||||||
auto offset = ir.Imm32(imm);
|
|
||||||
address = ir.IAdd(X(src_reg), offset);
|
|
||||||
if (skew_value != 0) {
|
|
||||||
address = ir.IAdd(address, ir.LaneId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return address;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Shader::Maxwell
|
} // namespace Shader::Maxwell
|
||||||
|
|
|
@ -56,30 +56,6 @@ enum class FPCompareOp : u64 {
|
||||||
T,
|
T,
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace Isberd {
|
|
||||||
enum class Mode : u64 {
|
|
||||||
Default,
|
|
||||||
Patch,
|
|
||||||
Prim,
|
|
||||||
Attr,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class Shift : u64 {
|
|
||||||
Default,
|
|
||||||
U16,
|
|
||||||
B32,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class SZ : u64 {
|
|
||||||
U8,
|
|
||||||
U16,
|
|
||||||
U32,
|
|
||||||
F32,
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Isberd
|
|
||||||
|
|
||||||
|
|
||||||
class TranslatorVisitor {
|
class TranslatorVisitor {
|
||||||
public:
|
public:
|
||||||
explicit TranslatorVisitor(Environment& env_, IR::Block& block) : env{env_}, ir(block) {}
|
explicit TranslatorVisitor(Environment& env_, IR::Block& block) : env{env_}, ir(block) {}
|
||||||
|
@ -408,12 +384,6 @@ public:
|
||||||
void ResetSFlag();
|
void ResetSFlag();
|
||||||
void ResetCFlag();
|
void ResetCFlag();
|
||||||
void ResetOFlag();
|
void ResetOFlag();
|
||||||
|
|
||||||
private:
|
|
||||||
// Helper functions for various translator visitors
|
|
||||||
IR::U32 apply_ISBERD_shift(IR::U32 result, Isberd::Shift shift_value);
|
|
||||||
IR::U32 apply_ISBERD_size_read(IR::U32 address, Isberd::SZ sz_value);
|
|
||||||
IR::U32 compute_ISBERD_address(IR::Reg src_reg, u32 src_reg_num, u32 imm, u64 skew_value);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Shader::Maxwell
|
} // namespace Shader::Maxwell
|
||||||
|
|
|
@ -9,9 +9,52 @@
|
||||||
#include "shader_recompiler/frontend/maxwell/translate/impl/impl.h"
|
#include "shader_recompiler/frontend/maxwell/translate/impl/impl.h"
|
||||||
|
|
||||||
namespace Shader::Maxwell {
|
namespace Shader::Maxwell {
|
||||||
|
namespace {
|
||||||
|
enum class Mode : u64 {
|
||||||
|
Default,
|
||||||
|
Patch,
|
||||||
|
Prim,
|
||||||
|
Attr,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class SZ : u64 {
|
||||||
|
U8,
|
||||||
|
U16,
|
||||||
|
U32,
|
||||||
|
F32
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class Shift : u64 {
|
||||||
|
Default,
|
||||||
|
U16,
|
||||||
|
B32,
|
||||||
|
};
|
||||||
|
|
||||||
|
IR::U32 scaleIndex(IR::IREmitter& ir, IR::U32 index, Shift shift) {
|
||||||
|
switch (shift) {
|
||||||
|
case Shift::Default: return index;
|
||||||
|
case Shift::U16: return ir.ShiftLeftLogical(index, ir.Imm32(1));
|
||||||
|
case Shift::B32: return ir.ShiftLeftLogical(index, ir.Imm32(2));
|
||||||
|
default: UNREACHABLE();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U32 skewBytes(IR::IREmitter& ir, SZ sizeRead) {
|
||||||
|
const IR::U32 lane = ir.LaneId();
|
||||||
|
switch (sizeRead) {
|
||||||
|
case SZ::U8: return lane;
|
||||||
|
case SZ::U16: return ir.ShiftLeftLogical(lane, ir.Imm32(1));
|
||||||
|
case SZ::U32:
|
||||||
|
case SZ::F32: return ir.ShiftLeftLogical(lane, ir.Imm32(2));
|
||||||
|
default: UNREACHABLE();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // Anonymous namespace
|
||||||
|
|
||||||
// Valid only for GS, TI, VS and trap
|
|
||||||
void TranslatorVisitor::ISBERD(u64 insn) {
|
void TranslatorVisitor::ISBERD(u64 insn) {
|
||||||
|
LOG_DEBUG(Shader, "called with insn={:#X}", insn);
|
||||||
|
|
||||||
union {
|
union {
|
||||||
u64 raw;
|
u64 raw;
|
||||||
BitField<0, 8, IR::Reg> dest_reg;
|
BitField<0, 8, IR::Reg> dest_reg;
|
||||||
|
@ -20,49 +63,63 @@ void TranslatorVisitor::ISBERD(u64 insn) {
|
||||||
BitField<24, 8, u32> imm;
|
BitField<24, 8, u32> imm;
|
||||||
BitField<31, 1, u64> skew;
|
BitField<31, 1, u64> skew;
|
||||||
BitField<32, 1, u64> o;
|
BitField<32, 1, u64> o;
|
||||||
BitField<33, 2, Isberd::Mode> mode;
|
BitField<33, 2, Mode> mode;
|
||||||
BitField<36, 4, Isberd::SZ> sz;
|
BitField<36, 4, SZ> sz;
|
||||||
BitField<47, 2, Isberd::Shift> shift;
|
BitField<47, 2, Shift> shift;
|
||||||
} const isberd{insn};
|
} const isberd{insn};
|
||||||
|
|
||||||
auto address = compute_ISBERD_address(isberd.src_reg, isberd.src_reg_num, isberd.imm, isberd.skew);
|
IR::U32 index{};
|
||||||
if (isberd.o != 0) {
|
if (isberd.src_reg_num.Value() == 0xFF) {
|
||||||
auto result = apply_ISBERD_size_read(address, isberd.sz.Value());
|
index = ir.Imm32(isberd.imm.Value());
|
||||||
X(isberd.dest_reg, apply_ISBERD_shift(result, isberd.shift.Value()));
|
} else {
|
||||||
|
const IR::U32 scaledIndex = scaleIndex(ir, X(isberd.src_reg.Value()), isberd.shift.Value());
|
||||||
return;
|
index = ir.IAdd(scaledIndex, ir.Imm32(isberd.imm.Value()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isberd.mode != Isberd::Mode::Default) {
|
if (isberd.o.Value()) {
|
||||||
IR::F32 result_f32{};
|
if (isberd.skew.Value()) {
|
||||||
switch (isberd.mode.Value()) {
|
index = ir.IAdd(index, skewBytes(ir, isberd.sz.Value()));
|
||||||
case Isberd::Mode::Patch:
|
|
||||||
result_f32 = ir.GetPatch(address.Patch());
|
|
||||||
break;
|
|
||||||
case Isberd::Mode::Prim:
|
|
||||||
result_f32 = ir.GetAttribute(address.Attribute());
|
|
||||||
break;
|
|
||||||
case Isberd::Mode::Attr:
|
|
||||||
result_f32 = ir.GetAttributeIndexed(address);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
UNREACHABLE();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto result_u32 = ir.BitCast<IR::U32>(result_f32);
|
const IR::U64 index64 = ir.UConvert(64, index);
|
||||||
X(isberd.dest_reg, apply_ISBERD_shift(result_u32, isberd.shift.Value()));
|
IR::U32 globalLoaded{};
|
||||||
return;
|
switch (isberd.sz.Value()) {
|
||||||
}
|
case SZ::U8: globalLoaded = ir.LoadGlobalU8 (index64); break;
|
||||||
|
case SZ::U16: globalLoaded = ir.LoadGlobalU16(index64); break;
|
||||||
if (isberd.skew != 0) {
|
case SZ::U32:
|
||||||
auto result = ir.IAdd(X(isberd.src_reg), ir.LaneId());
|
case SZ::F32: globalLoaded = ir.LoadGlobal32(index64); break;
|
||||||
X(isberd.dest_reg, result);
|
default: UNREACHABLE();
|
||||||
|
}
|
||||||
|
X(isberd.dest_reg.Value(), globalLoaded);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fallback if nothing else applies
|
if (isberd.mode.Value() != Mode::Default) {
|
||||||
X(isberd.dest_reg, X(isberd.src_reg));
|
if (isberd.skew.Value()) {
|
||||||
|
index = ir.IAdd(index, skewBytes(ir, SZ::U32));
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::F32 float_index{};
|
||||||
|
switch (isberd.mode.Value()) {
|
||||||
|
case Mode::Patch: float_index = ir.GetPatch(index.Patch()); break;
|
||||||
|
case Mode::Prim: float_index = ir.GetAttribute(index.Attribute()); break;
|
||||||
|
case Mode::Attr: float_index = ir.GetAttributeIndexed(index); break;
|
||||||
|
default: UNREACHABLE();
|
||||||
|
}
|
||||||
|
X(isberd.dest_reg.Value(), ir.BitCast<IR::U32>(float_index));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isberd.skew.Value()) {
|
||||||
|
X(isberd.dest_reg.Value(), ir.IAdd(X(isberd.src_reg.Value()), ir.LaneId()));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback copy
|
||||||
|
X(isberd.dest_reg.Value(), X(isberd.src_reg.Value()));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Shader::Maxwell
|
} // namespace Shader::Maxwell
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue