Shaders decompiler: support non 2D textures

Do not validate programs with undefined textures uniforms
Minor fix
This commit is contained in:
DH 2016-06-25 22:17:40 +03:00
parent d69a4173fa
commit e296f81a37
5 changed files with 214 additions and 12 deletions

View File

@ -311,7 +311,7 @@ void GLGSRender::end()
for (int i = 0; i < rsx::limits::textures_count; ++i) for (int i = 0; i < rsx::limits::textures_count; ++i)
{ {
int location; int location;
if (m_program->uniforms.has_location("texture" + std::to_string(i), &location)) if (m_program->uniforms.has_location("ftexture" + std::to_string(i), &location))
{ {
if (!textures[i].enabled()) if (!textures[i].enabled())
{ {
@ -330,7 +330,7 @@ void GLGSRender::end()
//texture_index++; //texture_index++;
if (m_program->uniforms.has_location("texture" + std::to_string(i) + "_cm", &location)) if (m_program->uniforms.has_location("ftexture" + std::to_string(i) + "_cm", &location))
{ {
if (textures[i].format() & CELL_GCM_TEXTURE_UN) if (textures[i].format() & CELL_GCM_TEXTURE_UN)
{ {
@ -657,6 +657,15 @@ static void fill_matrix_buffer(glsl_matrix_buffer *buffer)
bool GLGSRender::load_program() bool GLGSRender::load_program()
{ {
if (0)
{
RSXVertexProgram vertex_program = get_current_vertex_program();
RSXFragmentProgram fragment_program = get_current_fragment_program();
GLProgramBuffer prog_buffer;
__glcheck prog_buffer.getGraphicPipelineState(vertex_program, fragment_program, nullptr);
}
rsx::program_info info = programs_cache.get(get_raw_program(), rsx::decompile_language::glsl); rsx::program_info info = programs_cache.get(get_raw_program(), rsx::decompile_language::glsl);
m_program = (gl::glsl::program*)info.program; m_program = (gl::glsl::program*)info.program;
m_program->use(); m_program->use();

View File

@ -3,6 +3,162 @@
#include "gl_helpers.h" #include "gl_helpers.h"
#include "../GCM.h" #include "../GCM.h"
static void insert_texture_fetch_function(std::string &dst, const rsx::decompiled_shader &shader, const rsx::program_state &state)
{
if (shader.textures.empty())
{
return;
}
dst += "vec4 texture_fetch(int index, vec4 coord)\n{\n";
dst += "\tswitch (index)\n\t{\n";
for (auto &texture : shader.textures)
{
dst += "\tcase " + std::to_string(texture.id) + ": return ";
switch (state.textures[texture.id])
{
case rsx::texture_target::none: dst += "vec4(0.0)"; break;
case rsx::texture_target::_1: dst += "texture(" + texture.name + ", coord.x)"; break;
case rsx::texture_target::_2: dst += "texture(" + texture.name + ", coord.xy)"; break;
case rsx::texture_target::cube:
case rsx::texture_target::_3: dst += "texture(" + texture.name + ", coord.xyz)"; break;
}
dst += ";\n";
}
dst += "\t}\n";
dst += "}\n";
}
static void insert_texture_bias_fetch_function(std::string &dst, const rsx::decompiled_shader &shader, const rsx::program_state &state)
{
if (shader.textures.empty())
{
return;
}
dst += "vec4 texture_bias_fetch(int index, vec4 coord, float bias)\n{\n";
dst += "\tswitch (index)\n\t{\n";
for (auto &texture : shader.textures)
{
dst += "\tcase " + std::to_string(texture.id) + ": return ";
switch (state.textures[texture.id])
{
case rsx::texture_target::none: dst += "vec4(0.0)"; break;
case rsx::texture_target::_1: dst += "texture(" + texture.name + ", coord.x, bias)"; break;
case rsx::texture_target::_2: dst += "texture(" + texture.name + ", coord.xy, bias)"; break;
case rsx::texture_target::cube:
case rsx::texture_target::_3: dst += "texture(" + texture.name + ", coord.xyz, bias)"; break;
}
dst += ";\n";
}
dst += "\t}\n";
dst += "}\n";
}
static void insert_texture_grad_fetch_function(std::string &dst, const rsx::decompiled_shader &shader, const rsx::program_state &state)
{
if (shader.textures.empty())
{
return;
}
dst += "vec4 texture_grad_fetch(int index, vec4 coord, vec4 dPdx, vec4 dPdy)\n{\n";
dst += "\tswitch (index)\n\t{\n";
for (auto &texture : shader.textures)
{
dst += "\tcase " + std::to_string(texture.id) + ": return ";
switch (state.textures[texture.id])
{
case rsx::texture_target::none: dst += "vec4(0.0)"; break;
case rsx::texture_target::_1: dst += "textureGrad(" + texture.name + ", coord.x, dPdx.x, dPdy.x)"; break;
case rsx::texture_target::_2: dst += "textureGrad(" + texture.name + ", coord.xy, dPdx.xy, dPdy.xy)"; break;
case rsx::texture_target::cube:
case rsx::texture_target::_3: dst += "textureGrad(" + texture.name + ", coord.xyz, dPdx.xyz, dPdy.xyz)"; break;
}
dst += ";\n";
}
dst += "\t}\n";
dst += "}\n";
}
static void insert_texture_lod_fetch_function(std::string &dst, const rsx::decompiled_shader &shader, const rsx::program_state &state)
{
if (shader.textures.empty())
{
return;
}
dst += "vec4 texture_lod_fetch(int index, vec4 coord, float lod)\n{\n";
dst += "\tswitch (index)\n\t{\n";
for (auto &texture : shader.textures)
{
dst += "\tcase " + std::to_string(texture.id) + ": return ";
switch (state.textures[texture.id])
{
case rsx::texture_target::none: dst += "vec4(0.0)"; break;
case rsx::texture_target::_1: dst += "textureLod(" + texture.name + ", coord.x, lod)"; break;
case rsx::texture_target::_2: dst += "textureLod(" + texture.name + ", coord.xy, lod)"; break;
case rsx::texture_target::cube:
case rsx::texture_target::_3: dst += "textureLod(" + texture.name + ", coord.xyz, lod)"; break;
}
dst += ";\n";
}
dst += "\t}\n";
dst += "}\n";
}
static void insert_texture_proj_fetch_function(std::string &dst, const rsx::decompiled_shader &shader, const rsx::program_state &state)
{
if (shader.textures.empty())
{
return;
}
dst += "vec4 texture_proj_fetch(int index, vec4 coord, float bias)\n{\n";
dst += "\tswitch (index)\n\t{\n";
for (auto &texture : shader.textures)
{
dst += "\tcase " + std::to_string(texture.id) + ": return ";
switch (state.textures[texture.id])
{
case rsx::texture_target::cube:
case rsx::texture_target::none: dst += "vec4(0.0)"; break;
case rsx::texture_target::_1: dst += "textureProj(" + texture.name + ", coord.xy, bias)"; break;
case rsx::texture_target::_2: dst += "textureProj(" + texture.name + ", coord.xyz, bias)"; break;
case rsx::texture_target::_3: dst += "textureProj(" + texture.name + ", coord, bias)"; break;
}
dst += ";\n";
}
dst += "\t}\n";
dst += "}\n";
}
rsx::complete_shader glsl_complete_shader(const rsx::decompiled_shader &shader, rsx::program_state state) rsx::complete_shader glsl_complete_shader(const rsx::decompiled_shader &shader, rsx::program_state state)
{ {
rsx::complete_shader result; rsx::complete_shader result;
@ -75,7 +231,21 @@ rsx::complete_shader glsl_complete_shader(const rsx::decompiled_shader &shader,
for (const rsx::texture_info& texture : shader.textures) for (const rsx::texture_info& texture : shader.textures)
{ {
result.code += "uniform vec4 " + texture.name + "_cm = vec4(1.0);\n"; result.code += "uniform vec4 " + texture.name + "_cm = vec4(1.0);\n";
result.code += "uniform sampler2D " + texture.name + ";\n";
rsx::texture_target target = state.textures[texture.id];
result.code += "uniform sampler";
switch (target)
{
default:
case rsx::texture_target::_1: result.code += "1D"; break;
case rsx::texture_target::_2: result.code += "2D"; break;
case rsx::texture_target::_3: result.code += "3D"; break;
case rsx::texture_target::cube: result.code += "Cube"; break;
}
result.code += " " + texture.name + ";\n";
} }
std::string prepare; std::string prepare;
@ -85,6 +255,13 @@ rsx::complete_shader glsl_complete_shader(const rsx::decompiled_shader &shader,
switch (shader.raw->type) switch (shader.raw->type)
{ {
case rsx::program_type::fragment: case rsx::program_type::fragment:
insert_texture_fetch_function(result.code, shader, state);
insert_texture_bias_fetch_function(result.code, shader, state);
insert_texture_grad_fetch_function(result.code, shader, state);
insert_texture_lod_fetch_function(result.code, shader, state);
insert_texture_proj_fetch_function(result.code, shader, state);
result.code += "\n";
result.code += "layout(location = 0) out vec4 ocol;\n"; result.code += "layout(location = 0) out vec4 ocol;\n";
if (state.ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS) if (state.ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS)
@ -243,7 +420,6 @@ rsx::complete_shader glsl_complete_shader(const rsx::decompiled_shader &shader,
break; break;
case rsx::program_type::vertex: case rsx::program_type::vertex:
result.code += "out vec4 wpos;\n"; result.code += "out vec4 wpos;\n";
// TODO // TODO
@ -266,9 +442,6 @@ rsx::complete_shader glsl_complete_shader(const rsx::decompiled_shader &shader,
{ {
if (shader.input_attributes & (1 << index)) if (shader.input_attributes & (1 << index))
{ {
// result.code += "in vec4 " + rsx::vertex_program::input_attrib_names[index] + ";\n";
// TODO: use actual information about vertex inputs
const std::string &attrib_name = rsx::vertex_program::input_attrib_names[index]; const std::string &attrib_name = rsx::vertex_program::input_attrib_names[index];
result.code += "uniform "; result.code += "uniform ";
@ -446,7 +619,6 @@ void* glsl_make_program(const void *vertex_shader, const void *fragment_shader)
result->attach(*(gl::glsl::shader*)fragment_shader); result->attach(*(gl::glsl::shader*)fragment_shader);
result->link(); result->link();
result->validate();
return result; return result;
} }

View File

@ -747,7 +747,7 @@ namespace rsx
raw_program thread::get_raw_program() const raw_program thread::get_raw_program() const
{ {
raw_program result; raw_program result{};
u32 fp_info = rsx::method_registers[NV4097_SET_SHADER_PROGRAM]; u32 fp_info = rsx::method_registers[NV4097_SET_SHADER_PROGRAM];
@ -785,6 +785,27 @@ namespace rsx
} }
} }
for (u8 index = 0; index < rsx::limits::textures_count; ++index)
{
if (!textures[index].enabled())
{
result.state.textures[index] = rsx::texture_target::none;
continue;
}
switch (textures[index].get_extended_texture_dimension())
{
case rsx::texture_dimension_extended::texture_dimension_1d: result.state.textures[index] = rsx::texture_target::_1; break;
case rsx::texture_dimension_extended::texture_dimension_2d: result.state.textures[index] = rsx::texture_target::_2; break;
case rsx::texture_dimension_extended::texture_dimension_3d: result.state.textures[index] = rsx::texture_target::_3; break;
case rsx::texture_dimension_extended::texture_dimension_cubemap: result.state.textures[index] = rsx::texture_target::cube; break;
default:
result.state.textures[index] = rsx::texture_target::none;
break;
}
}
result.vertex_shader.ucode_ptr = transform_program; result.vertex_shader.ucode_ptr = transform_program;
result.vertex_shader.offset = rsx::method_registers[NV4097_SET_TRANSFORM_PROGRAM_START]; result.vertex_shader.offset = rsx::method_registers[NV4097_SET_TRANSFORM_PROGRAM_START];

View File

@ -92,7 +92,7 @@ namespace rsx
program_info result; program_info result;
result.vertex_shader = m_vertex_shaders_cache.get(context, raw_program_.vertex_shader, raw_program_.state); result.vertex_shader = m_vertex_shaders_cache.get(context, raw_program_.vertex_shader, raw_program_.state);
result.fragment_shader = m_vertex_shaders_cache.get(context, raw_program_.fragment_shader, raw_program_.state); result.fragment_shader = m_fragment_shader_cache.get(context, raw_program_.fragment_shader, raw_program_.state);
result.program = context.make_program(result.vertex_shader.complete->user_data, result.fragment_shader.complete->user_data); result.program = context.make_program(result.vertex_shader.complete->user_data, result.fragment_shader.complete->user_data);
m_program_cache.insert({ raw_program_, result }); m_program_cache.insert({ raw_program_, result });

@ -1 +1 @@
Subproject commit 9f8814af57264c82b7e063c1df5d71dc32c7a951 Subproject commit 9f2d4c3c61b38d24c166398bd4f9c6d2b2e6fcb9