mirror of
https://git.suyu.dev/suyu/suyu.git
synced 2024-11-30 10:42:47 +01:00
shader_decode: Use BitfieldExtract instead of shift + and
This commit is contained in:
parent
52223313b1
commit
2faad9bf23
8 changed files with 37 additions and 48 deletions
|
@ -985,6 +985,11 @@ private:
|
||||||
Type::Int);
|
Type::Int);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <Type type>
|
||||||
|
std::string BitfieldExtract(Operation operation) {
|
||||||
|
return GenerateTernary(operation, "bitfieldExtract", type, type, Type::Int, Type::Int);
|
||||||
|
}
|
||||||
|
|
||||||
template <Type type>
|
template <Type type>
|
||||||
std::string BitCount(Operation operation) {
|
std::string BitCount(Operation operation) {
|
||||||
return GenerateUnary(operation, "bitCount", type, type, false);
|
return GenerateUnary(operation, "bitCount", type, type, false);
|
||||||
|
@ -1369,6 +1374,7 @@ private:
|
||||||
&GLSLDecompiler::BitwiseXor<Type::Int>,
|
&GLSLDecompiler::BitwiseXor<Type::Int>,
|
||||||
&GLSLDecompiler::BitwiseNot<Type::Int>,
|
&GLSLDecompiler::BitwiseNot<Type::Int>,
|
||||||
&GLSLDecompiler::BitfieldInsert<Type::Int>,
|
&GLSLDecompiler::BitfieldInsert<Type::Int>,
|
||||||
|
&GLSLDecompiler::BitfieldExtract<Type::Int>,
|
||||||
&GLSLDecompiler::BitCount<Type::Int>,
|
&GLSLDecompiler::BitCount<Type::Int>,
|
||||||
|
|
||||||
&GLSLDecompiler::Add<Type::Uint>,
|
&GLSLDecompiler::Add<Type::Uint>,
|
||||||
|
@ -1386,6 +1392,7 @@ private:
|
||||||
&GLSLDecompiler::BitwiseXor<Type::Uint>,
|
&GLSLDecompiler::BitwiseXor<Type::Uint>,
|
||||||
&GLSLDecompiler::BitwiseNot<Type::Uint>,
|
&GLSLDecompiler::BitwiseNot<Type::Uint>,
|
||||||
&GLSLDecompiler::BitfieldInsert<Type::Uint>,
|
&GLSLDecompiler::BitfieldInsert<Type::Uint>,
|
||||||
|
&GLSLDecompiler::BitfieldExtract<Type::Uint>,
|
||||||
&GLSLDecompiler::BitCount<Type::Uint>,
|
&GLSLDecompiler::BitCount<Type::Uint>,
|
||||||
|
|
||||||
&GLSLDecompiler::Add<Type::HalfFloat>,
|
&GLSLDecompiler::Add<Type::HalfFloat>,
|
||||||
|
|
|
@ -57,10 +57,9 @@ u32 ShaderIR::DecodeArithmeticInteger(BasicBlock& bb, u32 pc) {
|
||||||
case IAdd3Height::None:
|
case IAdd3Height::None:
|
||||||
return value;
|
return value;
|
||||||
case IAdd3Height::LowerHalfWord:
|
case IAdd3Height::LowerHalfWord:
|
||||||
return Operation(OperationCode::IBitwiseAnd, NO_PRECISE, value, Immediate(0xffff));
|
return BitfieldExtract(value, 0, 16);
|
||||||
case IAdd3Height::UpperHalfWord:
|
case IAdd3Height::UpperHalfWord:
|
||||||
return Operation(OperationCode::ILogicalShiftRight, NO_PRECISE, value,
|
return BitfieldExtract(value, 16, 16);
|
||||||
Immediate(16));
|
|
||||||
default:
|
default:
|
||||||
UNIMPLEMENTED_MSG("Unhandled IADD3 height: {}", static_cast<u32>(height));
|
UNIMPLEMENTED_MSG("Unhandled IADD3 height: {}", static_cast<u32>(height));
|
||||||
return Immediate(0);
|
return Immediate(0);
|
||||||
|
|
|
@ -28,13 +28,8 @@ u32 ShaderIR::DecodeBfi(BasicBlock& bb, u32 pc) {
|
||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
const Node insert = GetRegister(instr.gpr8);
|
const Node insert = GetRegister(instr.gpr8);
|
||||||
|
const Node offset = BitfieldExtract(packed_shift, 0, 8);
|
||||||
const Node offset =
|
const Node bits = BitfieldExtract(packed_shift, 8, 8);
|
||||||
Operation(OperationCode::UBitwiseAnd, NO_PRECISE, packed_shift, Immediate(0xff));
|
|
||||||
|
|
||||||
Node bits =
|
|
||||||
Operation(OperationCode::ULogicalShiftRight, NO_PRECISE, packed_shift, Immediate(8));
|
|
||||||
bits = Operation(OperationCode::UBitwiseAnd, NO_PRECISE, bits, Immediate(0xff));
|
|
||||||
|
|
||||||
const Node value =
|
const Node value =
|
||||||
Operation(OperationCode::UBitfieldInsert, PRECISE, base, insert, offset, bits);
|
Operation(OperationCode::UBitfieldInsert, PRECISE, base, insert, offset, bits);
|
||||||
|
|
|
@ -27,20 +27,18 @@ u32 ShaderIR::DecodeRegisterSetPredicate(BasicBlock& bb, u32 pc) {
|
||||||
return Immediate(static_cast<u32>(instr.r2p.immediate_mask));
|
return Immediate(static_cast<u32>(instr.r2p.immediate_mask));
|
||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
const Node mask =
|
const Node mask = GetRegister(instr.gpr8);
|
||||||
Operation(OperationCode::ULogicalShiftRight, NO_PRECISE, GetRegister(instr.gpr8),
|
const auto offset = static_cast<u32>(instr.r2p.byte) * 8;
|
||||||
Immediate(static_cast<u32>(instr.r2p.byte)));
|
|
||||||
|
|
||||||
constexpr u32 programmable_preds = 7;
|
constexpr u32 programmable_preds = 7;
|
||||||
for (u64 pred = 0; pred < programmable_preds; ++pred) {
|
for (u64 pred = 0; pred < programmable_preds; ++pred) {
|
||||||
const Node shift = Immediate(1u << static_cast<u32>(pred));
|
const auto shift = static_cast<u32>(pred);
|
||||||
|
|
||||||
const Node apply_compare =
|
const Node apply_compare = BitfieldExtract(apply_mask, shift, 1);
|
||||||
Operation(OperationCode::UBitwiseAnd, NO_PRECISE, apply_mask, shift);
|
|
||||||
const Node condition =
|
const Node condition =
|
||||||
Operation(OperationCode::LogicalUNotEqual, apply_compare, Immediate(0));
|
Operation(OperationCode::LogicalUNotEqual, apply_compare, Immediate(0));
|
||||||
|
|
||||||
const Node value_compare = Operation(OperationCode::UBitwiseAnd, NO_PRECISE, mask, shift);
|
const Node value_compare = BitfieldExtract(mask, offset + shift, 1);
|
||||||
const Node value = Operation(OperationCode::LogicalUNotEqual, value_compare, Immediate(0));
|
const Node value = Operation(OperationCode::LogicalUNotEqual, value_compare, Immediate(0));
|
||||||
|
|
||||||
const Node code = Operation(OperationCode::LogicalAssign, GetPredicate(pred), value);
|
const Node code = Operation(OperationCode::LogicalAssign, GetPredicate(pred), value);
|
||||||
|
|
|
@ -88,21 +88,15 @@ u32 ShaderIR::DecodeVideo(BasicBlock& bb, u32 pc) {
|
||||||
Node ShaderIR::GetVideoOperand(Node op, bool is_chunk, bool is_signed,
|
Node ShaderIR::GetVideoOperand(Node op, bool is_chunk, bool is_signed,
|
||||||
Tegra::Shader::VideoType type, u64 byte_height) {
|
Tegra::Shader::VideoType type, u64 byte_height) {
|
||||||
if (!is_chunk) {
|
if (!is_chunk) {
|
||||||
const auto offset = static_cast<u32>(byte_height * 8);
|
return BitfieldExtract(op, static_cast<u32>(byte_height * 8), 8);
|
||||||
const Node shift = SignedOperation(OperationCode::ILogicalShiftRight, is_signed, NO_PRECISE,
|
|
||||||
op, Immediate(offset));
|
|
||||||
return SignedOperation(OperationCode::IBitwiseAnd, is_signed, NO_PRECISE, shift,
|
|
||||||
Immediate(0xff));
|
|
||||||
}
|
}
|
||||||
const Node zero = Immediate(0);
|
const Node zero = Immediate(0);
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case Tegra::Shader::VideoType::Size16_Low:
|
case Tegra::Shader::VideoType::Size16_Low:
|
||||||
return SignedOperation(OperationCode::IBitwiseAnd, is_signed, NO_PRECISE, op,
|
return BitfieldExtract(op, 0, 16);
|
||||||
Immediate(0xffff));
|
|
||||||
case Tegra::Shader::VideoType::Size16_High:
|
case Tegra::Shader::VideoType::Size16_High:
|
||||||
return SignedOperation(OperationCode::ILogicalShiftRight, is_signed, NO_PRECISE, op,
|
return BitfieldExtract(op, 16, 16);
|
||||||
Immediate(16));
|
|
||||||
case Tegra::Shader::VideoType::Size32:
|
case Tegra::Shader::VideoType::Size32:
|
||||||
// TODO(Rodrigo): From my hardware tests it becomes a bit "mad" when this type is used
|
// TODO(Rodrigo): From my hardware tests it becomes a bit "mad" when this type is used
|
||||||
// (1 * 1 + 0 == 0x5b800000). Until a better explanation is found: abort.
|
// (1 * 1 + 0 == 0x5b800000). Until a better explanation is found: abort.
|
||||||
|
|
|
@ -47,22 +47,10 @@ u32 ShaderIR::DecodeXmad(BasicBlock& bb, u32 pc) {
|
||||||
return {false, Immediate(0), Immediate(0)};
|
return {false, Immediate(0), Immediate(0)};
|
||||||
}();
|
}();
|
||||||
|
|
||||||
if (instr.xmad.high_a) {
|
op_a = BitfieldExtract(op_a, instr.xmad.high_a ? 16 : 0, 16);
|
||||||
op_a = SignedOperation(OperationCode::ILogicalShiftRight, is_signed_a, NO_PRECISE, op_a,
|
|
||||||
Immediate(16));
|
|
||||||
} else {
|
|
||||||
op_a = SignedOperation(OperationCode::IBitwiseAnd, is_signed_a, NO_PRECISE, op_a,
|
|
||||||
Immediate(0xffff));
|
|
||||||
}
|
|
||||||
|
|
||||||
const Node original_b = op_b;
|
const Node original_b = op_b;
|
||||||
if (instr.xmad.high_b) {
|
op_b = BitfieldExtract(op_b, instr.xmad.high_b ? 16 : 0, 16);
|
||||||
op_b = SignedOperation(OperationCode::ILogicalShiftRight, is_signed_b, NO_PRECISE, op_a,
|
|
||||||
Immediate(16));
|
|
||||||
} else {
|
|
||||||
op_b = SignedOperation(OperationCode::IBitwiseAnd, is_signed_b, NO_PRECISE, op_b,
|
|
||||||
Immediate(0xffff));
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(Rodrigo): Use an appropiate sign for this operation
|
// TODO(Rodrigo): Use an appropiate sign for this operation
|
||||||
Node product = Operation(OperationCode::IMul, NO_PRECISE, op_a, op_b);
|
Node product = Operation(OperationCode::IMul, NO_PRECISE, op_a, op_b);
|
||||||
|
@ -75,11 +63,9 @@ u32 ShaderIR::DecodeXmad(BasicBlock& bb, u32 pc) {
|
||||||
case Tegra::Shader::XmadMode::None:
|
case Tegra::Shader::XmadMode::None:
|
||||||
return op_c;
|
return op_c;
|
||||||
case Tegra::Shader::XmadMode::CLo:
|
case Tegra::Shader::XmadMode::CLo:
|
||||||
return SignedOperation(OperationCode::IBitwiseAnd, is_signed_c, NO_PRECISE, op_c,
|
return BitfieldExtract(op_c, 0, 16);
|
||||||
Immediate(0xffff));
|
|
||||||
case Tegra::Shader::XmadMode::CHi:
|
case Tegra::Shader::XmadMode::CHi:
|
||||||
return SignedOperation(OperationCode::ILogicalShiftRight, is_signed_c, NO_PRECISE, op_c,
|
return BitfieldExtract(op_c, 16, 16);
|
||||||
Immediate(16));
|
|
||||||
case Tegra::Shader::XmadMode::CBcc: {
|
case Tegra::Shader::XmadMode::CBcc: {
|
||||||
const Node shifted_b = SignedOperation(OperationCode::ILogicalShiftLeft, is_signed_b,
|
const Node shifted_b = SignedOperation(OperationCode::ILogicalShiftLeft, is_signed_b,
|
||||||
NO_PRECISE, original_b, Immediate(16));
|
NO_PRECISE, original_b, Immediate(16));
|
||||||
|
@ -94,9 +80,9 @@ u32 ShaderIR::DecodeXmad(BasicBlock& bb, u32 pc) {
|
||||||
// TODO(Rodrigo): Use an appropiate sign for this operation
|
// TODO(Rodrigo): Use an appropiate sign for this operation
|
||||||
Node sum = Operation(OperationCode::IAdd, product, op_c);
|
Node sum = Operation(OperationCode::IAdd, product, op_c);
|
||||||
if (is_merge) {
|
if (is_merge) {
|
||||||
const Node a = Operation(OperationCode::IBitwiseAnd, NO_PRECISE, sum, Immediate(0xffff));
|
const Node a = BitfieldExtract(sum, 0, 16);
|
||||||
const Node b =
|
const Node b =
|
||||||
Operation(OperationCode::ILogicalShiftLeft, NO_PRECISE, original_b, Immediate(0xffff));
|
Operation(OperationCode::ILogicalShiftLeft, NO_PRECISE, original_b, Immediate(16));
|
||||||
sum = Operation(OperationCode::IBitwiseOr, NO_PRECISE, a, b);
|
sum = Operation(OperationCode::IBitwiseOr, NO_PRECISE, a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -348,6 +348,11 @@ void ShaderIR::SetLocalMemory(BasicBlock& bb, Node address, Node value) {
|
||||||
bb.push_back(Operation(OperationCode::Assign, GetLocalMemory(address), value));
|
bb.push_back(Operation(OperationCode::Assign, GetLocalMemory(address), value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Node ShaderIR::BitfieldExtract(Node value, u32 offset, u32 bits) {
|
||||||
|
return Operation(OperationCode::UBitfieldExtract, NO_PRECISE, value, Immediate(offset),
|
||||||
|
Immediate(bits));
|
||||||
|
}
|
||||||
|
|
||||||
/*static*/ OperationCode ShaderIR::SignedToUnsignedCode(OperationCode operation_code,
|
/*static*/ OperationCode ShaderIR::SignedToUnsignedCode(OperationCode operation_code,
|
||||||
bool is_signed) {
|
bool is_signed) {
|
||||||
if (is_signed) {
|
if (is_signed) {
|
||||||
|
|
|
@ -88,6 +88,7 @@ enum class OperationCode {
|
||||||
IBitwiseXor, /// (MetaArithmetic, int a, int b) -> int
|
IBitwiseXor, /// (MetaArithmetic, int a, int b) -> int
|
||||||
IBitwiseNot, /// (MetaArithmetic, int a) -> int
|
IBitwiseNot, /// (MetaArithmetic, int a) -> int
|
||||||
IBitfieldInsert, /// (MetaArithmetic, int base, int insert, int offset, int bits) -> int
|
IBitfieldInsert, /// (MetaArithmetic, int base, int insert, int offset, int bits) -> int
|
||||||
|
IBitfieldExtract, /// (MetaArithmetic, int value, int offset, int offset) -> int
|
||||||
IBitCount, /// (MetaArithmetic, int) -> int
|
IBitCount, /// (MetaArithmetic, int) -> int
|
||||||
|
|
||||||
UAdd, /// (MetaArithmetic, uint a, uint b) -> uint
|
UAdd, /// (MetaArithmetic, uint a, uint b) -> uint
|
||||||
|
@ -105,6 +106,7 @@ enum class OperationCode {
|
||||||
UBitwiseXor, /// (MetaArithmetic, uint a, uint b) -> uint
|
UBitwiseXor, /// (MetaArithmetic, uint a, uint b) -> uint
|
||||||
UBitwiseNot, /// (MetaArithmetic, uint a) -> uint
|
UBitwiseNot, /// (MetaArithmetic, uint a) -> uint
|
||||||
UBitfieldInsert, /// (MetaArithmetic, uint base, uint insert, int offset, int bits) -> uint
|
UBitfieldInsert, /// (MetaArithmetic, uint base, uint insert, int offset, int bits) -> uint
|
||||||
|
UBitfieldExtract, /// (MetaArithmetic, uint value, int offset, int offset) -> uint
|
||||||
UBitCount, /// (MetaArithmetic, uint) -> uint
|
UBitCount, /// (MetaArithmetic, uint) -> uint
|
||||||
|
|
||||||
HAdd, /// (MetaHalfArithmetic, f16vec2 a, f16vec2 b) -> f16vec2
|
HAdd, /// (MetaHalfArithmetic, f16vec2 a, f16vec2 b) -> f16vec2
|
||||||
|
@ -689,6 +691,9 @@ private:
|
||||||
const Sampler& GetSampler(const Tegra::Shader::Sampler& sampler,
|
const Sampler& GetSampler(const Tegra::Shader::Sampler& sampler,
|
||||||
Tegra::Shader::TextureType type, bool is_array, bool is_shadow);
|
Tegra::Shader::TextureType type, bool is_array, bool is_shadow);
|
||||||
|
|
||||||
|
/// Extracts a sequence of bits from a node
|
||||||
|
Node BitfieldExtract(Node value, u32 offset, u32 bits);
|
||||||
|
|
||||||
void WriteTexsInstructionFloat(BasicBlock& bb, Tegra::Shader::Instruction instr, Node texture);
|
void WriteTexsInstructionFloat(BasicBlock& bb, Tegra::Shader::Instruction instr, Node texture);
|
||||||
void WriteTexsInstructionHalfFloat(BasicBlock& bb, Tegra::Shader::Instruction instr,
|
void WriteTexsInstructionHalfFloat(BasicBlock& bb, Tegra::Shader::Instruction instr,
|
||||||
Node texture);
|
Node texture);
|
||||||
|
|
Loading…
Reference in a new issue