rsx/common/d3d12/gl: Add some texture info to RSXFragmentProgram

This commit is contained in:
Vincent Lejeune 2016-01-24 22:24:28 +01:00
parent 40fa836b81
commit 24255f7883
9 changed files with 100 additions and 50 deletions

View File

@ -5,12 +5,11 @@
#include "FragmentProgramDecompiler.h" #include "FragmentProgramDecompiler.h"
FragmentProgramDecompiler::FragmentProgramDecompiler(const RSXFragmentProgram &prog, u32& size) : FragmentProgramDecompiler::FragmentProgramDecompiler(const RSXFragmentProgram &prog, u32& size) :
m_addr(prog.addr), m_prog(prog),
m_size(size), m_size(size),
m_const_index(0), m_const_index(0),
m_location(0), m_location(0),
m_ctrl(prog.ctrl), m_ctrl(prog.ctrl)
m_texture_dimensions(prog.texture_dimensions)
{ {
m_size = 0; m_size = 0;
} }
@ -114,7 +113,7 @@ std::string FragmentProgramDecompiler::AddConst()
return name; return name;
} }
auto data = vm::ps3::ptr<u32>::make(m_addr + m_size + 4 * SIZE_32(u32)); auto data = vm::ps3::ptr<u32>::make(m_prog.addr + m_size + 4 * SIZE_32(u32));
m_offset = 2 * 4 * sizeof(u32); m_offset = 2 * 4 * sizeof(u32);
u32 x = GetData(data[0]); u32 x = GetData(data[0]);
@ -128,7 +127,20 @@ std::string FragmentProgramDecompiler::AddConst()
std::string FragmentProgramDecompiler::AddTex() std::string FragmentProgramDecompiler::AddTex()
{ {
return m_parr.AddParam(PF_PARAM_UNIFORM, (m_texture_dimensions[dst.tex_num] == texture_dimension::texture_dimension_cubemap) ? "samplerCube" : "sampler2D", std::string("tex") + std::to_string(dst.tex_num)); std::string sampler;
switch (m_prog.get_texture_dimension(dst.tex_num))
{
case texture_dimension::texture_dimension_cubemap:
sampler = "samplerCube";
break;
case texture_dimension::texture_dimension_2d:
sampler = "sampler2D";
break;
case texture_dimension::texture_dimension_3d:
sampler = "sampler3D";
break;
}
return m_parr.AddParam(PF_PARAM_UNIFORM, sampler, std::string("tex") + std::to_string(dst.tex_num));
} }
std::string FragmentProgramDecompiler::Format(const std::string& code) std::string FragmentProgramDecompiler::Format(const std::string& code)
@ -425,12 +437,7 @@ bool FragmentProgramDecompiler::handle_tex_srb(u32 opcode)
case RSX_FP_OPCODE_NRM: SetDst("normalize($0)"); return true; case RSX_FP_OPCODE_NRM: SetDst("normalize($0)"); return true;
case RSX_FP_OPCODE_BEM: LOG_ERROR(RSX, "Unimplemented TEX_SRB instruction: BEM"); return true; case RSX_FP_OPCODE_BEM: LOG_ERROR(RSX, "Unimplemented TEX_SRB instruction: BEM"); return true;
case RSX_FP_OPCODE_TEX: case RSX_FP_OPCODE_TEX:
if (dst.tex_num >= m_texture_dimensions.size()) switch (m_prog.get_texture_dimension(dst.tex_num))
{
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE));
return true;
}
switch (m_texture_dimensions[dst.tex_num])
{ {
case texture_dimension::texture_dimension_2d: case texture_dimension::texture_dimension_2d:
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE)); SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE));
@ -438,16 +445,14 @@ bool FragmentProgramDecompiler::handle_tex_srb(u32 opcode)
case texture_dimension::texture_dimension_cubemap: case texture_dimension::texture_dimension_cubemap:
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_CUBE_SAMPLE)); SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_CUBE_SAMPLE));
return true; return true;
case texture_dimension::texture_dimension_3d:
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE3D));
return true;
} }
return false; return false;
case RSX_FP_OPCODE_TEXBEM: SetDst("texture($t, $0.xy, $1.x)"); return true; case RSX_FP_OPCODE_TEXBEM: SetDst("texture($t, $0.xy, $1.x)"); return true;
case RSX_FP_OPCODE_TXP: case RSX_FP_OPCODE_TXP:
if (dst.tex_num >= m_texture_dimensions.size()) switch (m_prog.get_texture_dimension(dst.tex_num))
{
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE_PROJ));
return true;
}
switch (m_texture_dimensions[dst.tex_num])
{ {
case texture_dimension::texture_dimension_2d: case texture_dimension::texture_dimension_2d:
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE_PROJ)); SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE_PROJ));
@ -455,18 +460,16 @@ bool FragmentProgramDecompiler::handle_tex_srb(u32 opcode)
case texture_dimension::texture_dimension_cubemap: case texture_dimension::texture_dimension_cubemap:
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_CUBE_SAMPLE_PROJ)); SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_CUBE_SAMPLE_PROJ));
return true; return true;
case texture_dimension::texture_dimension_3d:
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE3D_PROJ));
return true;
} }
return false; return false;
case RSX_FP_OPCODE_TXPBEM: SetDst("textureProj($t, $0.xyz, $1.x)"); return true; case RSX_FP_OPCODE_TXPBEM: SetDst("textureProj($t, $0.xyz, $1.x)"); return true;
case RSX_FP_OPCODE_TXD: LOG_ERROR(RSX, "Unimplemented TEX_SRB instruction: TXD"); return true; case RSX_FP_OPCODE_TXD: LOG_ERROR(RSX, "Unimplemented TEX_SRB instruction: TXD"); return true;
case RSX_FP_OPCODE_TXB: SetDst("texture($t, $0.xy, $1.x)"); return true; case RSX_FP_OPCODE_TXB: SetDst("texture($t, $0.xy, $1.x)"); return true;
case RSX_FP_OPCODE_TXL: case RSX_FP_OPCODE_TXL:
if (dst.tex_num >= m_texture_dimensions.size()) switch (m_prog.get_texture_dimension(dst.tex_num))
{
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE_LOD));
return true;
}
switch (m_texture_dimensions[dst.tex_num])
{ {
case texture_dimension::texture_dimension_2d: case texture_dimension::texture_dimension_2d:
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE_LOD)); SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE_LOD));
@ -474,6 +477,9 @@ bool FragmentProgramDecompiler::handle_tex_srb(u32 opcode)
case texture_dimension::texture_dimension_cubemap: case texture_dimension::texture_dimension_cubemap:
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_CUBE_SAMPLE_LOD)); SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_CUBE_SAMPLE_LOD));
return true; return true;
case texture_dimension::texture_dimension_3d:
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE3D_LOD));
return true;
} }
return false; return false;
case RSX_FP_OPCODE_UP2: SetDst("unpackSnorm2x16($0)"); return true; // TODO: More testing (Sonic The Hedgehog (NPUB-30442/NPEB-00478)) case RSX_FP_OPCODE_UP2: SetDst("unpackSnorm2x16($0)"); return true; // TODO: More testing (Sonic The Hedgehog (NPUB-30442/NPEB-00478))
@ -487,7 +493,7 @@ bool FragmentProgramDecompiler::handle_tex_srb(u32 opcode)
std::string FragmentProgramDecompiler::Decompile() std::string FragmentProgramDecompiler::Decompile()
{ {
auto data = vm::ps3::ptr<u32>::make(m_addr); auto data = vm::ps3::ptr<u32>::make(m_prog.addr);
m_size = 0; m_size = 0;
m_location = 0; m_location = 0;
m_loop_count = 0; m_loop_count = 0;

View File

@ -25,9 +25,8 @@ class FragmentProgramDecompiler
SRC2 src2; SRC2 src2;
std::string main; std::string main;
u32 m_addr;
u32& m_size; u32& m_size;
const std::vector<texture_dimension> m_texture_dimensions; const RSXFragmentProgram &m_prog;
u32 m_const_index; u32 m_const_index;
u32 m_offset; u32 m_offset;
u32 m_location; u32 m_location;

View File

@ -19,6 +19,9 @@ enum class FUNCTION {
FUNCTION_TEXTURE_CUBE_SAMPLE, FUNCTION_TEXTURE_CUBE_SAMPLE,
FUNCTION_TEXTURE_CUBE_SAMPLE_PROJ, FUNCTION_TEXTURE_CUBE_SAMPLE_PROJ,
FUNCTION_TEXTURE_CUBE_SAMPLE_LOD, FUNCTION_TEXTURE_CUBE_SAMPLE_LOD,
FUNCTION_TEXTURE_SAMPLE3D,
FUNCTION_TEXTURE_SAMPLE3D_PROJ,
FUNCTION_TEXTURE_SAMPLE3D_LOD,
}; };
enum class COMPARE { enum class COMPARE {

View File

@ -47,13 +47,19 @@ std::string getFunctionImp(FUNCTION f)
case FUNCTION::FUNCTION_TEXTURE_SAMPLE_PROJ: case FUNCTION::FUNCTION_TEXTURE_SAMPLE_PROJ:
return "$t.Sample($tsampler, ($0.xy / $0.w) * $t_scale)"; return "$t.Sample($tsampler, ($0.xy / $0.w) * $t_scale)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE_LOD: case FUNCTION::FUNCTION_TEXTURE_SAMPLE_LOD:
return "$t.SampleLevel($tsampler, ($0.xy / $0.w) * $t_scale, $1)"; return "$t.SampleLevel($tsampler, $0.xy * $t_scale, $1)";
case FUNCTION::FUNCTION_TEXTURE_CUBE_SAMPLE: case FUNCTION::FUNCTION_TEXTURE_CUBE_SAMPLE:
return "$t.Sample($tsampler, $0.xyz)"; return "$t.Sample($tsampler, $0.xyz)";
case FUNCTION::FUNCTION_TEXTURE_CUBE_SAMPLE_PROJ: case FUNCTION::FUNCTION_TEXTURE_CUBE_SAMPLE_PROJ:
return "$t.Sample($tsampler, ($0.xyz / $0.w))"; return "$t.Sample($tsampler, ($0.xyz / $0.w))";
case FUNCTION::FUNCTION_TEXTURE_CUBE_SAMPLE_LOD: case FUNCTION::FUNCTION_TEXTURE_CUBE_SAMPLE_LOD:
return "$t.SampleLevel($tsampler, ($0.xyz / $0.w), $1)"; return "$t.SampleLevel($tsampler, $0.xyz, $1)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE3D:
return "$t.Sample($tsampler, $0.xyz)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE3D_PROJ:
return "$t.Sample($tsampler, ($0.xyz / $0.w))";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE3D_LOD:
return "$t.SampleLevel($tsampler, $0.xyz, $1)";
case FUNCTION::FUNCTION_DFDX: case FUNCTION::FUNCTION_DFDX:
return "ddx($0)"; return "ddx($0)";
case FUNCTION::FUNCTION_DFDY: case FUNCTION::FUNCTION_DFDY:

View File

@ -107,16 +107,16 @@ void D3D12FragmentDecompiler::insertConstants(std::stringstream & OS)
{ {
OS << "cbuffer CONSTANT : register(b2)" << std::endl; OS << "cbuffer CONSTANT : register(b2)" << std::endl;
OS << "{" << std::endl; OS << "{" << std::endl;
for (ParamType PT : m_parr.params[PF_PARAM_UNIFORM]) for (const ParamType &PT : m_parr.params[PF_PARAM_UNIFORM])
{ {
if (PT.type == "sampler2D" || PT.type == "samplerCube") if (PT.type == "sampler2D" || PT.type == "samplerCube" || PT.type == "sampler3D")
continue; continue;
for (ParamItem PI : PT.items) for (ParamItem PI : PT.items)
OS << " " << PT.type << " " << PI.name << ";" << std::endl; OS << " " << PT.type << " " << PI.name << ";" << std::endl;
} }
OS << "};" << std::endl << std::endl; OS << "};" << std::endl << std::endl;
for (ParamType PT : m_parr.params[PF_PARAM_UNIFORM]) for (const ParamType &PT : m_parr.params[PF_PARAM_UNIFORM])
{ {
if (PT.type == "sampler2D") if (PT.type == "sampler2D")
{ {
@ -127,9 +127,18 @@ void D3D12FragmentDecompiler::insertConstants(std::stringstream & OS)
OS << "sampler " << PI.name << "sampler : register(s" << textureIndex << ");" << std::endl; OS << "sampler " << PI.name << "sampler : register(s" << textureIndex << ");" << std::endl;
} }
} }
else if (PT.type == "sampler3D")
{
for (const ParamItem &PI : PT.items)
{
size_t textureIndex = atoi(PI.name.data() + 3);
OS << "Texture3D " << PI.name << " : register(t" << textureIndex + 16 << ");" << std::endl;
OS << "sampler " << PI.name << "sampler : register(s" << textureIndex << ");" << std::endl;
}
}
else if (PT.type == "samplerCube") else if (PT.type == "samplerCube")
{ {
for (ParamItem PI : PT.items) for (const ParamItem &PI : PT.items)
{ {
size_t textureIndex = atoi(PI.name.data() + 3); size_t textureIndex = atoi(PI.name.data() + 3);
OS << "TextureCube " << PI.name << " : register(t" << textureIndex << ");" << std::endl; OS << "TextureCube " << PI.name << " : register(t" << textureIndex << ");" << std::endl;
@ -166,23 +175,23 @@ void D3D12FragmentDecompiler::insertMainStart(std::stringstream & OS)
}; };
OS << "void ps_impl(PixelInput In, inout float4 r0, inout float4 h0, inout float4 r1, inout float4 h2, inout float4 r2, inout float4 h4, inout float4 r3, inout float4 h6, inout float4 r4, inout float4 h8)" << std::endl; OS << "void ps_impl(PixelInput In, inout float4 r0, inout float4 h0, inout float4 r1, inout float4 h2, inout float4 r2, inout float4 h4, inout float4 r3, inout float4 h6, inout float4 r4, inout float4 h8)" << std::endl;
OS << "{" << std::endl; OS << "{" << std::endl;
for (ParamType PT : m_parr.params[PF_PARAM_IN]) for (const ParamType &PT : m_parr.params[PF_PARAM_IN])
{ {
for (ParamItem PI : PT.items) for (const ParamItem &PI : PT.items)
OS << " " << PT.type << " " << PI.name << " = In." << PI.name << ";" << std::endl; OS << " " << PT.type << " " << PI.name << " = In." << PI.name << ";" << std::endl;
} }
// A bit unclean, but works. // A bit unclean, but works.
OS << " " << "float4 gl_Position = In.Position;" << std::endl; OS << " " << "float4 gl_Position = In.Position;" << std::endl;
// Declare output // Declare output
for (ParamType PT : m_parr.params[PF_PARAM_NONE]) for (const ParamType &PT : m_parr.params[PF_PARAM_NONE])
{ {
for (ParamItem PI : PT.items) for (const ParamItem &PI : PT.items)
if (output_value.find(PI.name) == output_value.end()) if (output_value.find(PI.name) == output_value.end())
OS << " " << PT.type << " " << PI.name << " = float4(0., 0., 0., 0.);" << std::endl; OS << " " << PT.type << " " << PI.name << " = float4(0., 0., 0., 0.);" << std::endl;
} }
// Declare texture coordinate scaling component (to handle unormalized texture coordinates) // Declare texture coordinate scaling component (to handle unormalized texture coordinates)
for (ParamType PT : m_parr.params[PF_PARAM_UNIFORM]) for (const ParamType &PT : m_parr.params[PF_PARAM_UNIFORM])
{ {
if (PT.type != "sampler2D") if (PT.type != "sampler2D")
continue; continue;

View File

@ -44,17 +44,20 @@ void D3D12GSRender::load_program()
m_fragment_program.offset = shader_program & ~0x3; m_fragment_program.offset = shader_program & ~0x3;
m_fragment_program.addr = rsx::get_address(m_fragment_program.offset, (shader_program & 0x3) - 1); m_fragment_program.addr = rsx::get_address(m_fragment_program.offset, (shader_program & 0x3) - 1);
m_fragment_program.ctrl = rsx::method_registers[NV4097_SET_SHADER_CONTROL]; m_fragment_program.ctrl = rsx::method_registers[NV4097_SET_SHADER_CONTROL];
m_fragment_program.texture_dimensions.clear();
std::array<texture_dimension, 16> texture_dimensions;
for (u32 i = 0; i < rsx::limits::textures_count; ++i) for (u32 i = 0; i < rsx::limits::textures_count; ++i)
{ {
if (!textures[i].enabled()) if (!textures[i].enabled())
m_fragment_program.texture_dimensions.push_back(texture_dimension::texture_dimension_2d); texture_dimensions[i] = texture_dimension::texture_dimension_2d;
else if (textures[i].cubemap()) else if (textures[i].cubemap())
m_fragment_program.texture_dimensions.push_back(texture_dimension::texture_dimension_cubemap); texture_dimensions[i] = texture_dimension::texture_dimension_cubemap;
else if (textures[i].dimension() == 3)
texture_dimensions[i] = texture_dimension::texture_dimension_3d;
else else
m_fragment_program.texture_dimensions.push_back(texture_dimension::texture_dimension_2d); texture_dimensions[i] = texture_dimension::texture_dimension_2d;
} }
m_fragment_program.set_texture_dimension(texture_dimensions);
D3D12PipelineProperties prop = {}; D3D12PipelineProperties prop = {};
prop.Topology = get_primitive_topology_type(draw_mode); prop.Topology = get_primitive_topology_type(draw_mode);

View File

@ -155,7 +155,7 @@ struct D3D12Traits
{ {
for (const ParamItem PI : PT.items) for (const ParamItem PI : PT.items)
{ {
if (PT.type == "sampler2D" || PT.type == "samplerCube") if (PT.type == "sampler2D" || PT.type == "samplerCube" || PT.type == "sampler3D")
{ {
size_t texture_unit = atoi(PI.name.c_str() + 3); size_t texture_unit = atoi(PI.name.c_str() + 3);
fragmentProgramData.m_textureCount = std::max(texture_unit + 1, fragmentProgramData.m_textureCount); fragmentProgramData.m_textureCount = std::max(texture_unit + 1, fragmentProgramData.m_textureCount);

View File

@ -745,15 +745,19 @@ bool GLGSRender::load_program()
fragment_program.addr = rsx::get_address(fragment_program.offset, (shader_program & 0x3) - 1); fragment_program.addr = rsx::get_address(fragment_program.offset, (shader_program & 0x3) - 1);
fragment_program.ctrl = rsx::method_registers[NV4097_SET_SHADER_CONTROL]; fragment_program.ctrl = rsx::method_registers[NV4097_SET_SHADER_CONTROL];
std::array<texture_dimension, 16> texture_dimensions;
for (u32 i = 0; i < rsx::limits::textures_count; ++i) for (u32 i = 0; i < rsx::limits::textures_count; ++i)
{ {
if (!textures[i].enabled()) if (!textures[i].enabled())
fragment_program.texture_dimensions.push_back(texture_dimension::texture_dimension_2d); texture_dimensions[i] = texture_dimension::texture_dimension_2d;
else if (textures[i].cubemap()) else if (textures[i].cubemap())
fragment_program.texture_dimensions.push_back(texture_dimension::texture_dimension_cubemap); texture_dimensions[i] = texture_dimension::texture_dimension_cubemap;
else if (textures[i].dimension() == 3)
texture_dimensions[i] = texture_dimension::texture_dimension_3d;
else else
fragment_program.texture_dimensions.push_back(texture_dimension::texture_dimension_2d); texture_dimensions[i] = texture_dimension::texture_dimension_2d;
} }
fragment_program.set_texture_dimension(texture_dimensions);
__glcheck m_program = &m_prog_buffer.getGraphicPipelineState(vertex_program, fragment_program, nullptr); __glcheck m_program = &m_prog_buffer.getGraphicPipelineState(vertex_program, fragment_program, nullptr);
__glcheck m_program->use(); __glcheck m_program->use();

View File

@ -204,11 +204,11 @@ static const std::string rsx_fp_op_names[] =
"NULL", "BRK", "CAL", "IFE", "LOOP", "REP", "RET" "NULL", "BRK", "CAL", "IFE", "LOOP", "REP", "RET"
}; };
enum class texture_dimension enum class texture_dimension : u8
{ {
texture_dimension_2d, texture_dimension_2d = 0,
texture_dimension_2d_array, texture_dimension_cubemap = 1,
texture_dimension_cubemap, texture_dimension_3d = 2,
}; };
struct RSXFragmentProgram struct RSXFragmentProgram
@ -217,13 +217,33 @@ struct RSXFragmentProgram
u32 addr; u32 addr;
u32 offset; u32 offset;
u32 ctrl; u32 ctrl;
std::vector<texture_dimension> texture_dimensions; u16 unnormalized_coords;
u32 texture_dimensions;
texture_dimension get_texture_dimension(u8 id) const
{
return (texture_dimension)((texture_dimensions >> (id * 2)) & 0x3);
}
void set_texture_dimension(const std::array<texture_dimension, 16> &dimensions)
{
size_t id = 0;
for (const texture_dimension &dim : dimensions)
{
texture_dimensions &= ~(0x3 << (id * 2));
u8 d = (u8)dim;
texture_dimensions |= ((d & 0x3) << (id * 2));
id++;
}
}
RSXFragmentProgram() RSXFragmentProgram()
: size(0) : size(0)
, addr(0) , addr(0)
, offset(0) , offset(0)
, ctrl(0) , ctrl(0)
, unnormalized_coords(0)
, texture_dimensions(0)
{ {
} }
}; };