fp: fixed scalar instructions & implemented texture instructions

vp: implemented TXL instruction
minor improvements
This commit is contained in:
DHrpcs3
2016-01-06 15:47:54 +02:00
parent 139d8092b9
commit 53acafb457
9 changed files with 201 additions and 69 deletions

View File

@@ -55,7 +55,7 @@ namespace rsx
{
if (program.input_attributes & (1 << index))
{
result.code += "in vec4 " + rsx::fragment_program::input_attrib_map[index] + ";\n";
result.code += "in vec4 " + rsx::fragment_program::input_attrib_names[index] + ";\n";
}
}
break;
@@ -65,7 +65,7 @@ namespace rsx
{
if (program.input_attributes & (1 << index))
{
result.code += "in vec4 " + rsx::vertex_program::input_registers_table[index] + ";\n";
result.code += "in vec4 " + rsx::vertex_program::input_attrib_names[index] + ";\n";
}
}
break;

View File

@@ -57,9 +57,10 @@ namespace rsx
struct register_info
{
std::string name;
int id;
register_type type;
std::string name;
bool operator==(const register_info& rhs) const
{
@@ -106,6 +107,7 @@ namespace rsx
std::string entry_function;
std::string code;
std::uint64_t ucode_size;
std::uint64_t ucode_hash;
};

View File

@@ -2,6 +2,9 @@
#include "rsx_fp_ucode.h"
#include <glsl_language.h>
#include <map>
#include "../rsx_program_decompiler/endianness.h"
using namespace endianness;
namespace rsx
{
@@ -18,6 +21,8 @@ namespace rsx
template<int Count>
using float_point_expr = typename base::template float_point_expr<Count>;
using sampler2D_expr = typename base::template expression_from<typename base::sampler2D_t>;
template<int Count>
using float_point_t = typename base::template float_point_t<Count>;
@@ -62,10 +67,25 @@ namespace rsx
return info.name;
}
sampler2D_expr texture(int index)
{
texture_info info;
info.id = index;
info.name = "texture" + std::to_string(index);
program.textures.insert(info);
return info.name;
}
float_point_expr<4> texture_coords_modifier(int index)
{
return{ "texture" + std::to_string(index) + "_cm" };
}
float_point_expr<4> input(int index)
{
program.input_attributes |= (1 << index);
return input_attrib_map[index];
return input_attrib_names[index];
}
};
@@ -93,10 +113,10 @@ namespace rsx
{
instruction_t result;
result.data.dst._u32 = (data.dst._u32 << 16) | (data.dst._u32 >> 16);
result.data.src0._u32 = (data.src0._u32 << 16) | (data.src0._u32 >> 16);
result.data.src1._u32 = (data.src1._u32 << 16) | (data.src1._u32 >> 16);
result.data.src2._u32 = (data.src2._u32 << 16) | (data.src2._u32 >> 16);
(be_t<u32>&)result.data.dst._u32 = (data.dst._u32 << 16) | (data.dst._u32 >> 16);
(be_t<u32>&)result.data.src0._u32 = (data.src0._u32 << 16) | (data.src0._u32 >> 16);
(be_t<u32>&)result.data.src1._u32 = (data.src1._u32 << 16) | (data.src1._u32 >> 16);
(be_t<u32>&)result.data.src2._u32 = (data.src2._u32 << 16) | (data.src2._u32 >> 16);
return result;
}
@@ -153,7 +173,7 @@ namespace rsx
case src_reg_type_t::constant: return context.constant();
}
throw;
throw std::runtime_error("bad instruction argument (#" + std::to_string((u32)src.reg_type) + ") type.");
};
float_point_expr<4> result = get_variable(src);
@@ -178,6 +198,16 @@ namespace rsx
return result;
}
sampler2D_expr texture(context_t& context) const
{
return context.texture(data.dst.tex_num);
}
float_point_expr<4> texture_coords_modifier(context_t& context) const
{
return context.texture_coords_modifier(data.dst.tex_num);
}
std::string destination_swizzle() const
{
std::string swizzle;
@@ -267,7 +297,7 @@ namespace rsx
return base::compare_function::equal;
}
throw;
throw std::logic_error("");
}
boolean_expr<1> execution_condition(condition_operation operation)
@@ -307,9 +337,14 @@ namespace rsx
return base::custom_compare(function, (int)instruction.destination_swizzle().size(), a, b);
}
typename base::template expression_from<typename base::sampler2D_t> tex()
sampler2D_expr texture()
{
return{ "unk_tex" };
return instruction.texture(context);
}
float_point_expr<4> texture_coords(int src_index = 0)
{
return src(src_index) * instruction.texture_coords_modifier(context);
}
template<typename ExprType>
@@ -329,6 +364,7 @@ namespace rsx
{
none,
disable_swizzle_as_dst = 1,
allow_bx2
};
template<typename Type>
@@ -374,7 +410,7 @@ namespace rsx
break;
default:
throw std::runtime_error("fragment program decompiler: unimplemented precision.");
throw std::runtime_error("fragment program decompiler: unimplemented precision. (" + std::to_string(instruction.data.dst.prec) +").");
}
}
@@ -467,7 +503,7 @@ namespace rsx
if (instruction.data.dst.set_cond)
{
expression.assign(cond.with_mask(dst_swizzle) = expression);
expression.assign(modify_cond.with_mask(dst_swizzle) = expression);
}
result += base::if_(cond.swizzle(channel_to_index.at(entry.first)).template call_operator<boolean_t<1>>(operation, zero), expression);
@@ -494,7 +530,7 @@ namespace rsx
if (instruction.data.dst.set_cond)
{
src.assign(float_point_expr<4>(modify_cond.text, dest.mask) = src);
src.assign(modify_cond.with_mask(dest.mask) = src);
}
}
@@ -506,12 +542,16 @@ namespace rsx
builder::writer_t set_dst(const float_point_expr<1>& arg, u32 flags = none)
{
if (instruction.destination_swizzle().size() != 1)
switch (instruction.destination_swizzle().size())
{
return set_dst(float_point_t<4>::ctor(arg), flags);
}
case 1: return set_dst(float_point_expr<4>{ arg.to_string() }, flags | disable_swizzle_as_dst);
case 2: return set_dst(float_point_expr<4>{ float_point_t<2>::ctor(arg).to_string() }, flags);
case 3: return set_dst(float_point_expr<4>{ float_point_t<3>::ctor(arg).to_string() }, flags);
case 4: return set_dst(float_point_t<4>::ctor(arg), flags);
return set_dst(float_point_expr<4>{ arg.to_string() }, flags | disable_swizzle_as_dst);
default:
throw std::logic_error("bad destination swizzle.");
}
}
builder::writer_t set_dst(const boolean_expr<4>& arg, u32 flags = none)
@@ -528,7 +568,7 @@ namespace rsx
case 4: arg_string = float_point_t<4>::ctor(boolean_expr<4>{ arg.to_string() }).to_string(); break;
default:
throw;
throw std::logic_error("bad destination swizzle.");
}
return set_dst(float_point_expr<4>{ arg_string, std::string("xyzw"), is_single, 4 }, flags);
@@ -565,21 +605,21 @@ namespace rsx
case (u32)opcode_t::kil: return conditional(typename base::void_expr{ "discard;" });
case (u32)opcode_t::pk4: return base::unimplemented("PK4");
case (u32)opcode_t::up4: return base::unimplemented("UP4");
case (u32)opcode_t::ddx: return set_dst(base::ddx(src_swizzled_as_dst(0)), disable_swizzle_as_dst);
case (u32)opcode_t::ddy: return set_dst(base::ddy(src_swizzled_as_dst(0)), disable_swizzle_as_dst);
case (u32)opcode_t::tex: return set_dst(base::texture(tex(), src(0).xy()));
case (u32)opcode_t::txp: return set_dst(base::texture(tex(), src(0).xy() / src(0).w()));
case (u32)opcode_t::txd: return set_dst(base::texture_grad(tex(), src(0).xy(), src(1).xy(), src(2).xy()));
case (u32)opcode_t::rcp: return set_dst(float_point_t<1>::ctor(1.0f) / src_swizzled_as_dst(0), disable_swizzle_as_dst);
case (u32)opcode_t::rsq: return set_dst(base::rsqrt(src_swizzled_as_dst(0)), disable_swizzle_as_dst);
case (u32)opcode_t::ex2: return set_dst(base::exp2(src_swizzled_as_dst(0)), disable_swizzle_as_dst);
case (u32)opcode_t::lg2: return set_dst(base::log2(src_swizzled_as_dst(0)), disable_swizzle_as_dst);
//case (u32)opcode_t::ddx: return set_dst(base::ddx(src(0).xy()), disable_swizzle_as_dst);
//case (u32)opcode_t::ddy: return set_dst(base::ddy(src(0).xy()), disable_swizzle_as_dst);
case (u32)opcode_t::tex: return set_dst(base::texture(texture(), texture_coords().xy()), allow_bx2);
case (u32)opcode_t::txp: return set_dst(base::texture(texture(), texture_coords().xy() / src(0).w()), allow_bx2);
case (u32)opcode_t::txd: return set_dst(base::texture_grad(texture(), texture_coords().xy(), src(1).xy(), src(2).xy()), allow_bx2);
case (u32)opcode_t::rcp: return set_dst(float_point_t<1>::ctor(1.0f) / src(0).x(), disable_swizzle_as_dst);
case (u32)opcode_t::rsq: return set_dst(base::rsqrt(src(0).x()), disable_swizzle_as_dst);
case (u32)opcode_t::ex2: return set_dst(base::exp2(src(0).x()), disable_swizzle_as_dst);
case (u32)opcode_t::lg2: return set_dst(base::log2(src(0).x()), disable_swizzle_as_dst);
case (u32)opcode_t::lit: return base::unimplemented("LIT");
case (u32)opcode_t::lrp: return base::unimplemented("LRP");
case (u32)opcode_t::str: return set_dst(1.0f);
case (u32)opcode_t::sfl: return set_dst(0.0f);
case (u32)opcode_t::cos: return set_dst(base::cos(src_swizzled_as_dst(0)), disable_swizzle_as_dst);
case (u32)opcode_t::sin: return set_dst(base::sin(src_swizzled_as_dst(0)), disable_swizzle_as_dst);
case (u32)opcode_t::cos: return set_dst(base::cos(src(0).x()), disable_swizzle_as_dst);
case (u32)opcode_t::sin: return set_dst(base::sin(src(0).x()), disable_swizzle_as_dst);
case (u32)opcode_t::pk2: return base::unimplemented("PK2");
case (u32)opcode_t::up2: return base::unimplemented("UP2");
case (u32)opcode_t::pow: return set_dst(base::pow(src_swizzled_as_dst(0), src_swizzled_as_dst(1)), disable_swizzle_as_dst);
@@ -597,8 +637,8 @@ namespace rsx
return set_dst(float_point_t<4>::ctor(src_0.x() * src_1.x() + src_0.y() * src_1.y() + src(2).z()));
}
case (u32)opcode_t::txl: return set_dst(base::texture_lod(tex(), src(0).xy(), src(1).x()));
case (u32)opcode_t::txb: return set_dst(base::texture_bias(tex(), src(0).xy(), src(1).x()));
case (u32)opcode_t::txl: return set_dst(base::texture_lod(texture(), texture_coords().xy(), src(1).x()), allow_bx2);
case (u32)opcode_t::txb: return set_dst(base::texture_bias(texture(), texture_coords().xy(), src(1).x()), allow_bx2);
case (u32)opcode_t::texbem: return base::unimplemented("TEXBEM");
case (u32)opcode_t::txpbem: return base::unimplemented("TXPBEM");
case (u32)opcode_t::bemlum: return base::unimplemented("BEMLUM");
@@ -606,8 +646,8 @@ namespace rsx
case (u32)opcode_t::timeswtex: return base::unimplemented("TIMESWTEX");
case (u32)opcode_t::dp2: return set_dst(base::dot(src(0).xy(), src(1).xy()));
case (u32)opcode_t::nrm: return set_dst(base::normalize(src(0).xyz()).xyzx());
case (u32)opcode_t::div: return set_dst(src_swizzled_as_dst(0) / src_swizzled_as_dst(1), disable_swizzle_as_dst);
case (u32)opcode_t::divsq: return set_dst(src_swizzled_as_dst(0) / base::sqrt(src_swizzled_as_dst(1)), disable_swizzle_as_dst);
case (u32)opcode_t::div: return set_dst(src_swizzled_as_dst(0) / src(1).x(), disable_swizzle_as_dst);
case (u32)opcode_t::divsq: return set_dst(src_swizzled_as_dst(0) / base::sqrt(src(1).x()), disable_swizzle_as_dst);
case (u32)opcode_t::lif: return base::unimplemented("LIF");
case (u32)opcode_t::fenct: return base::comment("fenct");
case (u32)opcode_t::fencb: return base::comment("fencb");
@@ -639,7 +679,7 @@ namespace rsx
case (u32)opcode_t::ret: return conditional(typename base::void_expr("return;"));
}
throw;
throw std::runtime_error("bad instruction. (" + std::to_string(u32(instruction.data.dst.opcode) | (u32(instruction.data.src1.opcode_is_branch) << 6)) + ")");
}
decompiled_shader decompile(std::size_t offset, instruction_t* instructions)
@@ -657,16 +697,27 @@ namespace rsx
instruction = instructions[index].unpack();
base::writer += decode_instruction();
try
{
base::writer += decode_instruction();
}
catch (const std::runtime_error &ex)
{
base::writer += base::comment("exception: " + std::string(ex.what()));
}
if (instruction.data.dst.end)
{
context.offset += context.is_next_is_constant ? sizeof(instruction_t) * 2 : sizeof(instruction_t);
break;
}
}
context.program.entry_function = "func0";
base::writer.before(0, "void func0()\n{\n");
base::writer.after(base::writer.position, "}\n");
context.program.code = base::writer.finalize();
context.program.ucode_size = context.offset;
return context.program;
}

View File

@@ -4,24 +4,24 @@ namespace rsx
{
namespace fragment_program
{
const std::string input_attrib_map[16] =
const std::string input_attrib_names[16] =
{
"in_wpos", //0
"in_col0", //1
"in_col1", //2
"in_fogc", //3
"in_tex0", //4
"in_tex1", //5
"in_tex2", //6
"in_tex3", //7
"in_tex4", //8
"in_tex5", //9
"in_tex6", //10
"in_tex7", //11
"in_tex8", //12
"in_tex9", //13
"in_ssa", //14
"in_unk" //15
"wpos", //0
"col0", //1
"col1", //2
"fogc", //3
"tex0", //4
"tex1", //5
"tex2", //6
"tex3", //7
"tex4", //8
"tex5", //9
"tex6", //10
"tex7", //11
"tex8", //12
"tex9", //13
"ssa", //14
"unk" //15
};
const std::string instructions_names[128] =

View File

@@ -233,6 +233,6 @@ namespace rsx
std::uint64_t hash(const ucode_instr *ucode);
extern const std::string instructions_names[128];
extern const std::string input_attrib_map[16];
extern const std::string input_attrib_names[16];
}
}

View File

@@ -18,6 +18,8 @@ namespace rsx
template<int Count>
using float_point_expr = typename base::template float_point_expr<Count>;
using sampler2D_expr = typename base::template expression_from<typename base::sampler2D_t>;
template<int Count>
using integer_expr = typename base::template integer_expr<Count>;
@@ -62,13 +64,23 @@ namespace rsx
+ "]";
}
sampler2D_expr texture(int index)
{
texture_info info;
info.id = index;
info.name = "vtexture" + std::to_string(index);
program.textures.insert(info);
return info.name;
}
float_point_expr<4> output(u32 index)
{
program.output_attributes |= (1 << index);
register_info info;
info.id = index;
info.type = register_type::single_float_point;
info.name = rsx::fragment_program::input_attrib_map[index];//"o" + std::to_string(index);
info.name = "o" + std::to_string(index);
program.temporary_registers.insert(info);
return info.name;
}
@@ -97,7 +109,7 @@ namespace rsx
float_point_expr<4> input(int index)
{
program.input_attributes |= (1 << index);
return input_registers_table[index];
return input_attrib_names[index];
}
};
@@ -178,6 +190,11 @@ namespace rsx
return float_point_expr<4>(arg.text, arg_mask, arg.is_single, arg.base_count);
}
sampler2D_expr texture()
{
return context.texture(instruction.unpack_src(0).tmp_src & 0x3);
}
float_point_expr<4> src(int index, bool is_swizzle_as_dst = false)
{
SRC src = instruction.unpack_src(index);
@@ -426,14 +443,18 @@ namespace rsx
return result;
}
typename base::writer_t set_dst(float_point_expr<1> arg)
builder::writer_t set_dst(const float_point_expr<1>& arg)
{
if (destination_swizzle().size() != 1)
switch (destination_swizzle().size())
{
return set_dst(float_point_t<4>::ctor(arg));
}
case 1: return set_dst(float_point_expr<4>{ arg.to_string() });
case 2: return set_dst(float_point_expr<4>{ float_point_t<2>::ctor(arg).to_string() });
case 3: return set_dst(float_point_expr<4>{ float_point_t<3>::ctor(arg).to_string() });
case 4: return set_dst(float_point_t<4>::ctor(arg));
return set_dst(float_point_expr<4>{ arg.to_string() });
default:
throw;
}
}
typename base::writer_t set_dst(boolean_expr<4> arg)
@@ -598,7 +619,7 @@ namespace rsx
case (u32)vec_opcode_t::add: return set_dst(src_swizzled_as_dst(0) + src_swizzled_as_dst(2));
case (u32)vec_opcode_t::mad: return set_dst((src_swizzled_as_dst(0) * src_swizzled_as_dst(1)).without_scope() + src_swizzled_as_dst(2));
case (u32)vec_opcode_t::dp3: return set_dst(base::dot(src(0).xyz(), src(1).xyz()));
case (u32)vec_opcode_t::dph: break;
case (u32)vec_opcode_t::dph: return set_dst(base::dot(float_point_t<4>::ctor(src(0).xyz(), 1.0), src(1))); break;
case (u32)vec_opcode_t::dp4: return set_dst(base::dot(src(0), src(1)));
case (u32)vec_opcode_t::dst: break;
case (u32)vec_opcode_t::min: return set_dst(base::min(src_swizzled_as_dst(0), src_swizzled_as_dst(1)));
@@ -615,7 +636,11 @@ namespace rsx
case (u32)vec_opcode_t::sne: return set_dst(compare(base::compare_function::not_equal, src_swizzled_as_dst(0), src_swizzled_as_dst(1)));
case (u32)vec_opcode_t::str: return set_dst(1.0f);
case (u32)vec_opcode_t::ssg: break;
case (u32)vec_opcode_t::txl: break;
case (u32)vec_opcode_t::txl:
{
auto src_1 = src(1);
return set_dst(base::texture_lod(texture(), src_1.xy(), src_1.w()));
}
default:
throw;
@@ -649,14 +674,27 @@ namespace rsx
public:
decompiled_shader decompile(std::size_t offset, instruction_t *instructions)
{
context.program.ucode_size = 0;
for (std::size_t i = offset; i < 512; ++i, base::writer.next())
{
instruction = instructions[i].unpack();
base::writer += decode_instruction();
try
{
base::writer += decode_instruction();
}
catch (...)
{
base::writer += base::comment("exception!");
}
context.program.ucode_size += sizeof(instruction_t);
if (instruction.data.d3.end)
{
break;
}
}
context.program.entry_function = "func0";

View File

@@ -4,7 +4,7 @@ namespace rsx
{
namespace vertex_program
{
const std::string input_registers_table[0x10] =
const std::string input_attrib_names[0x10] =
{
"in_pos", "in_weight", "in_normal",
"in_diff_color", "in_spec_color",
@@ -14,6 +14,32 @@ namespace rsx
"in_tc4", "in_tc5", "in_tc6", "in_tc7"
};
static const std::string output_attrib_names[22] =
{
"front_diffuse_color",
"front_specular_color",
"back_diffuse_color",
"back_specular_color",
"fog",
"point_size",
"uc0",
"uc1",
"uc2",
"uc3",
"uc4",
"uc5",
"tex8",
"tex9",
"tex0",
"tex1",
"tex2",
"tex3",
"tex4",
"tex5",
"tex6",
"tex7",
};
const std::string sca_op_names[0x20] =
{
"NOP", "MOV", "RCP", "RCC", "RSQ", "EXP", "LOG",

View File

@@ -58,7 +58,11 @@ namespace rsx
sne = 0x14,
str = 0x15,
ssg = 0x16,
txl = 0x19
arr = 0x17,
ara = 0x18,
txl = 0x19,
psh = 0x1a,
pop = 0x1b,
};
enum class src_register_type : u32
@@ -206,7 +210,8 @@ namespace rsx
std::uint64_t hash(const ucode_instr *ucode);
extern const std::string input_registers_table[0x10];
extern const std::string input_attrib_names[0x10];
extern const std::string output_attrib_names[22];
extern const std::string sca_op_names[0x20];
extern const std::string vec_op_names[0x20];
}

View File

@@ -1,5 +1,15 @@
#pragma once
#include <common/StrFmt.h>
#include <cstdint>
using u8 = uint8_t;
using u16 = uint16_t;
using u32 = uint32_t;
using u64 = uint64_t;
using s8 = int8_t;
using s16 = int16_t;
using s32 = int32_t;
using s64 = int64_t;
namespace endianness
{