rsx/decompiler: Restructure program register behavior

- Fix reading of varying registers in FP
  Different registers have different behavior
- Always write to varying registers. If a register is not written to, it is initialized to (0, 0, 0, 1)
- Reimplements two-sided lighting correctly without hacks
- Also bumps shader cache version
This commit is contained in:
kd-11 2019-08-23 19:36:01 +03:00 committed by kd-11
parent fe6ff8622a
commit 3e28e4b1e0
17 changed files with 318 additions and 426 deletions

View File

@ -1,6 +1,7 @@
#include "stdafx.h"
#include "Emu/Memory/vm.h"
#include "Emu/System.h"
#include "../rsx_methods.h"
#include "FragmentProgramDecompiler.h"
@ -520,27 +521,81 @@ template<typename T> std::string FragmentProgramDecompiler::GetSRC(T src)
"ssa"
};
//TODO: Investigate effect of input modifier on this type
// NOTE: Hw testing showed the following:
// 1. Reading from registers 1 and 2 (COL0 and COL1) is clamped to (0, 1)
// 2. Reading from registers 4-12 (inclusive) is not clamped, but..
// 3. If the texcoord control mask is enabled, the last 2 values are always 0 and 1!
const std::string reg_var = (dst.src_attr_reg_num < std::size(reg_table))? reg_table[dst.src_attr_reg_num] : "unk";
bool insert = true;
switch (dst.src_attr_reg_num)
{
case 0x00:
{
// WPOS
ret += reg_table[0];
properties.has_wpos_input = true;
insert = false;
break;
default:
if (dst.src_attr_reg_num < std::size(reg_table))
}
case 0x01:
case 0x02:
{
// COL0, COL1
ret += "_saturate(" + reg_var + ")";
apply_precision_modifier = false;
break;
}
case 0x03:
{
// FOGC
// TODO: Confirm if precision modifiers affect this one
ret += reg_var;
break;
}
case 0x4:
case 0x5:
case 0x6:
case 0x7:
case 0x8:
case 0x9:
case 0xA:
case 0xB:
case 0xC:
case 0xD:
{
// TEX0 - TEX9
// Texcoord mask seems to reset the last 2 arguments to 0 and 1 if set
if (m_prog.texcoord_is_2d(dst.src_attr_reg_num - 4))
{
ret += m_parr.AddParam(PF_PARAM_IN, getFloatTypeName(4), reg_table[dst.src_attr_reg_num]);
ret += getFloatTypeName(4) + "(" + reg_var + ".x, " + reg_var + ".y, 0., 1.)";
}
else
{
LOG_ERROR(RSX, "Bad src reg num: %d", u32{ dst.src_attr_reg_num });
ret += m_parr.AddParam(PF_PARAM_IN, getFloatTypeName(4), "unk");
Emu.Pause();
ret += reg_var;
}
break;
}
default:
{
// SSA (winding direction register)
// UNK
if (reg_var == "unk")
{
LOG_ERROR(RSX, "Bad src reg num: %d", u32{ dst.src_attr_reg_num });
}
ret += reg_var;
apply_precision_modifier = false;
break;
}
}
if (insert)
{
m_parr.AddParam(PF_PARAM_IN, getFloatTypeName(4), reg_var);
}
properties.in_register_mask |= (1 << dst.src_attr_reg_num);
}
break;

View File

@ -252,11 +252,30 @@ protected:
virtual void insertMainEnd(std::stringstream &OS) = 0;
public:
enum : u16
{
in_wpos = (1 << 0),
in_diff_color = (1 << 1),
in_spec_color = (1 << 2),
in_fogc = (1 << 3),
in_tc0 = (1 << 4),
in_tc1 = (1 << 5),
in_tc2 = (1 << 6),
in_tc3 = (1 << 7),
in_tc4 = (1 << 8),
in_tc5 = (1 << 9),
in_tc6 = (1 << 10),
in_tc7 = (1 << 11),
in_tc8 = (1 << 12),
in_tc9 = (1 << 13),
in_ssa = (1 << 14)
};
struct
{
u16 in_register_mask = 0;
bool has_lit_op = false;
bool has_gather_op = false;
bool has_wpos_input = false;
bool has_no_output = false;
bool has_discard_op = false;
bool has_tex_op = false;

View File

@ -1,4 +1,4 @@
#include "stdafx.h"
#include "stdafx.h"
#include "ProgramStateCache.h"
#include "Emu/System.h"
@ -424,9 +424,7 @@ size_t fragment_program_storage_hash::operator()(const RSXFragmentProgram& progr
hash ^= program.ctrl;
hash ^= program.texture_dimensions;
hash ^= program.unnormalized_coords;
hash ^= program.back_color_diffuse_output;
hash ^= program.back_color_specular_output;
hash ^= program.front_back_color_enabled;
hash ^= program.two_sided_lighting;
hash ^= program.shadow_textures;
hash ^= program.redirected_textures;
@ -436,8 +434,7 @@ size_t fragment_program_storage_hash::operator()(const RSXFragmentProgram& progr
bool fragment_program_compare::operator()(const RSXFragmentProgram& binary1, const RSXFragmentProgram& binary2) const
{
if (binary1.ctrl != binary2.ctrl || binary1.texture_dimensions != binary2.texture_dimensions || binary1.unnormalized_coords != binary2.unnormalized_coords ||
binary1.back_color_diffuse_output != binary2.back_color_diffuse_output || binary1.back_color_specular_output != binary2.back_color_specular_output ||
binary1.front_back_color_enabled != binary2.front_back_color_enabled ||
binary1.two_sided_lighting != binary2.two_sided_lighting ||
binary1.shadow_textures != binary2.shadow_textures || binary1.redirected_textures != binary2.redirected_textures)
return false;

View File

@ -325,14 +325,50 @@ public:
struct vertex_reg_info
{
std::string name; //output name
bool need_declare; //needs explicit declaration as output (not language in-built)
std::string src_reg; //reg to get data from
std::string src_reg_mask; //input swizzle mask
bool need_cast; //needs casting
std::string cond; //update on condition
std::string default_val; //fallback value on cond fail
std::string dst_alias; //output name override
bool check_mask; //check program output control mask for this output
u32 check_mask_value; //program output control mask for testing
enum mask_test_type : u8
{
any = 0, // Any bit set
none = 1, // No bits set
all = 2, // All bits set
xall = 3 // Some bits set
};
std::string name; // output name
bool need_declare; // needs explicit declaration as output (not language in-built)
std::string src_reg; // reg to get data from
std::string src_reg_mask; // input swizzle mask
bool need_cast; // needs casting
std::string cond; // update on condition
std::string default_val; // fallback value on cond fail
std::string dst_alias; // output name override
bool check_mask; // check program output control mask for this output
u32 check_mask_value; // program output control mask for testing
mask_test_type check_flags; // whole mask must match
bool test(u32 mask) const
{
if (!check_mask)
return true;
const u32 val = (mask & check_mask_value);
switch (check_flags)
{
case none:
return (val == 0);
case any:
return (val != 0);
case all:
return (val == check_mask_value);
case xall:
return (val && val != check_mask_value);
default:
fmt::throw_exception("Unreachable" HERE);
}
}
bool declare(u32 mask) const
{
return test(mask);
}
};

View File

@ -1,4 +1,4 @@
#ifdef _MSC_VER
#ifdef _MSC_VER
#include "stdafx.h"
#include "stdafx_d3d12.h"
#include "D3D12FragmentProgramDecompiler.h"
@ -206,19 +206,6 @@ void D3D12FragmentDecompiler::insertMainStart(std::stringstream & OS)
{
for (const ParamItem &PI : PT.items)
{
if (m_prog.front_back_color_enabled)
{
if (PI.name == "spec_color" && m_prog.back_color_specular_output)
{
OS << " float4 spec_color = is_front_face ? In.dst_reg4 : In.spec_color;\n";
continue;
}
if (PI.name == "diff_color" && m_prog.back_color_diffuse_output)
{
OS << " float4 diff_color = is_front_face ? In.dst_reg3 : In.diff_color;\n";
continue;
}
}
if (PI.name == "fogc")
{
OS << " float4 fogc = fetch_fog_value(fog_mode, In.fogc);\n";

View File

@ -1,4 +1,4 @@
#include "stdafx.h"
#include "stdafx.h"
#include "GLCommonDecompiler.h"
namespace gl
@ -7,10 +7,9 @@ namespace gl
{{
{"diff_color", 1},
{"spec_color", 2},
{"back_diff_color", 1},
{"back_spec_color", 2},
{"front_diff_color", 3},
{"front_spec_color", 4},
{"diff_color1", 3},
{"spec_color1", 4},
{"fogc", 5},
{"fog_c", 5},
{"tc0", 6},
{"tc1", 7},

View File

@ -48,7 +48,6 @@ void GLFragmentDecompilerThread::insertHeader(std::stringstream & OS)
void GLFragmentDecompilerThread::insertInputs(std::stringstream & OS)
{
bool two_sided_enabled = m_prog.front_back_color_enabled && (m_prog.back_color_diffuse_output || m_prog.back_color_specular_output);
std::vector<std::string> inputs_to_declare;
for (const ParamType& PT : m_parr.params[PF_PARAM_IN])
@ -58,41 +57,28 @@ void GLFragmentDecompilerThread::insertInputs(std::stringstream & OS)
//ssa is defined in the program body and is not a varying type
if (PI.name == "ssa") continue;
const auto reg_location = gl::get_varying_register_location(PI.name);
std::string var_name = PI.name;
if (two_sided_enabled)
if (var_name == "fogc")
{
if (m_prog.back_color_diffuse_output && var_name == "diff_color")
var_name = "back_diff_color";
if (m_prog.back_color_specular_output && var_name == "spec_color")
var_name = "back_spec_color";
var_name = "fog_c";
}
else if (m_prog.two_sided_lighting)
{
if (var_name == "diff_color")
{
var_name = "diff_color0";
}
else if (var_name == "spec_color")
{
var_name = "spec_color0";
}
}
if (var_name == "fogc")
var_name = "fog_c";
inputs_to_declare.push_back(var_name);
OS << "layout(location=" << reg_location << ") in vec4 " << var_name << ";\n";
}
}
if (two_sided_enabled)
{
if (m_prog.front_color_diffuse_output && m_prog.back_color_diffuse_output)
{
inputs_to_declare.emplace_back("front_diff_color");
}
if (m_prog.front_color_specular_output && m_prog.back_color_specular_output)
{
inputs_to_declare.emplace_back("front_spec_color");
}
}
for (auto &name: inputs_to_declare)
{
OS << "layout(location=" << gl::get_varying_register_location(name) << ") in vec4 " << name << ";\n";
}
}
void GLFragmentDecompilerThread::insertOutputs(std::stringstream & OS)
@ -201,7 +187,7 @@ void GLFragmentDecompilerThread::insertGlobalFunctions(std::stringstream &OS)
properties2.require_lit_emulation = properties.has_lit_op;
properties2.fp32_outputs = !!(m_prog.ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS);
properties2.require_depth_conversion = m_prog.redirected_textures != 0;
properties2.require_wpos = properties.has_wpos_input;
properties2.require_wpos = !!(properties.in_register_mask & in_wpos);
properties2.require_texture_ops = properties.has_tex_op;
properties2.require_shadow_ops = m_prog.shadow_textures != 0;
properties2.emulate_coverage_tests = g_cfg.video.antialiasing_level == msaa_level::none;
@ -213,18 +199,8 @@ void GLFragmentDecompilerThread::insertGlobalFunctions(std::stringstream &OS)
void GLFragmentDecompilerThread::insertMainStart(std::stringstream & OS)
{
//TODO: Generate input mask during parse stage to avoid this
for (const ParamType& PT : m_parr.params[PF_PARAM_IN])
{
for (const ParamItem& PI : PT.items)
{
if (PI.name == "fogc")
{
glsl::insert_fog_declaration(OS);
break;
}
}
}
if (properties.in_register_mask & in_fogc)
glsl::insert_fog_declaration(OS);
const std::set<std::string> output_values =
{
@ -267,58 +243,25 @@ void GLFragmentDecompilerThread::insertMainStart(std::stringstream & OS)
if (m_parr.HasParam(PF_PARAM_IN, "vec4", "ssa"))
OS << " vec4 ssa = gl_FrontFacing ? vec4(1.) : vec4(-1.);\n";
if (properties.has_wpos_input)
if (properties.in_register_mask & in_wpos)
OS << " vec4 wpos = get_wpos();\n";
bool two_sided_enabled = m_prog.front_back_color_enabled && (m_prog.back_color_diffuse_output || m_prog.back_color_specular_output);
if (properties.in_register_mask & in_ssa)
OS << " vec4 ssa = gl_FrontFacing ? vec4(1.) : vec4(-1.);\n";
for (const ParamType& PT : m_parr.params[PF_PARAM_IN])
if (properties.in_register_mask & in_wpos)
OS << " vec4 wpos = get_wpos();\n";
if (properties.in_register_mask & in_fogc)
OS << " vec4 fogc = fetch_fog_value(fog_mode);\n";
if (m_prog.two_sided_lighting)
{
for (const ParamItem& PI : PT.items)
{
if (two_sided_enabled)
{
if (PI.name == "spec_color")
{
if (m_prog.back_color_specular_output)
{
if (m_prog.back_color_specular_output && m_prog.front_color_specular_output)
{
OS << " vec4 spec_color = gl_FrontFacing ? front_spec_color : back_spec_color;\n";
}
else
{
OS << " vec4 spec_color = back_spec_color;\n";
}
}
if (properties.in_register_mask & in_diff_color)
OS << " vec4 diff_color = gl_FrontFacing ? diff_color1 : diff_color0;\n";
continue;
}
else if (PI.name == "diff_color")
{
if (m_prog.back_color_diffuse_output)
{
if (m_prog.back_color_diffuse_output && m_prog.front_color_diffuse_output)
{
OS << " vec4 diff_color = gl_FrontFacing ? front_diff_color : back_diff_color;\n";
}
else
{
OS << " vec4 diff_color = back_diff_color;\n";
}
}
continue;
}
}
if (PI.name == "fogc")
{
OS << " vec4 fogc = fetch_fog_value(fog_mode);\n";
continue;
}
}
if (properties.in_register_mask & in_spec_color)
OS << " vec4 spec_color = gl_FrontFacing ? spec_color1 : spec_color0;\n";
}
}

View File

@ -29,7 +29,7 @@ u64 GLGSRender::get_cycles()
GLGSRender::GLGSRender() : GSRender()
{
m_shaders_cache = std::make_unique<gl::shader_cache>(m_prog_buffer, "opengl", "v1.6");
m_shaders_cache = std::make_unique<gl::shader_cache>(m_prog_buffer, "opengl", "v1.91");
if (g_cfg.video.disable_vertex_cache || g_cfg.video.multithreaded_rsx)
m_vertex_cache = std::make_unique<gl::null_vertex_cache>();

View File

@ -79,78 +79,43 @@ void GLVertexDecompilerThread::insertConstants(std::stringstream & OS, const std
static const vertex_reg_info reg_table[] =
{
{ "gl_Position", false, "dst_reg0", "", false },
{ "diff_color", true, "dst_reg1", "", false, "", "", "", false, CELL_GCM_ATTRIB_OUTPUT_MASK_FRONTDIFFUSE },
{ "spec_color", true, "dst_reg2", "", false, "", "", "", false, CELL_GCM_ATTRIB_OUTPUT_MASK_FRONTSPECULAR },
{ "diff_color", true, "dst_reg1", "", false, "", "", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_FRONTDIFFUSE | CELL_GCM_ATTRIB_OUTPUT_MASK_BACKDIFFUSE },
{ "spec_color", true, "dst_reg2", "", false, "", "", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_FRONTSPECULAR | CELL_GCM_ATTRIB_OUTPUT_MASK_BACKSPECULAR },
//These are only present when back variants are specified, otherwise the default diff/spec color vars are for both front and back
{ "front_diff_color", true, "dst_reg3", "", false },
{ "front_spec_color", true, "dst_reg4", "", false },
{ "diff_color1", true, "dst_reg3", "", false, "", "", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_FRONTDIFFUSE | CELL_GCM_ATTRIB_OUTPUT_MASK_BACKDIFFUSE },
{ "spec_color1", true, "dst_reg4", "", false, "", "", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_FRONTSPECULAR | CELL_GCM_ATTRIB_OUTPUT_MASK_BACKSPECULAR },
//Fog output shares a data source register with clip planes 0-2 so only declare when specified
{ "fog_c", true, "dst_reg5", ".xxxx", true, "", "", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_FOG },
//Warning: Always define all 3 clip plane groups together to avoid flickering with openGL
{ "gl_ClipDistance[0]", false, "dst_reg5", ".y * user_clip_factor[0].x", false, "user_clip_enabled[0].x > 0", "0.5", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_UC0 | CELL_GCM_ATTRIB_OUTPUT_MASK_UC1 | CELL_GCM_ATTRIB_OUTPUT_MASK_UC2 },
{ "gl_ClipDistance[1]", false, "dst_reg5", ".z * user_clip_factor[0].y", false, "user_clip_enabled[0].y > 0", "0.5", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_UC0 | CELL_GCM_ATTRIB_OUTPUT_MASK_UC1 | CELL_GCM_ATTRIB_OUTPUT_MASK_UC2 },
{ "gl_ClipDistance[2]", false, "dst_reg5", ".w * user_clip_factor[0].z", false, "user_clip_enabled[0].z > 0", "0.5", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_UC0 | CELL_GCM_ATTRIB_OUTPUT_MASK_UC1 | CELL_GCM_ATTRIB_OUTPUT_MASK_UC2 },
{ "gl_PointSize", false, "dst_reg6", ".x", false },
{ "gl_PointSize", false, "dst_reg6", ".x", false, "", "", "", true, CELL_GCM_ATTRIB_OUTPUT_POINTSIZE },
{ "gl_ClipDistance[3]", false, "dst_reg6", ".y * user_clip_factor[0].w", false, "user_clip_enabled[0].w > 0", "0.5", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_UC3 | CELL_GCM_ATTRIB_OUTPUT_MASK_UC4 | CELL_GCM_ATTRIB_OUTPUT_MASK_UC5 },
{ "gl_ClipDistance[4]", false, "dst_reg6", ".z * user_clip_factor[1].x", false, "user_clip_enabled[1].x > 0", "0.5", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_UC3 | CELL_GCM_ATTRIB_OUTPUT_MASK_UC4 | CELL_GCM_ATTRIB_OUTPUT_MASK_UC5 },
{ "gl_ClipDistance[5]", false, "dst_reg6", ".w * user_clip_factor[1].y", false, "user_clip_enabled[1].y > 0", "0.5", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_UC3 | CELL_GCM_ATTRIB_OUTPUT_MASK_UC4 | CELL_GCM_ATTRIB_OUTPUT_MASK_UC5 },
{ "tc0", true, "dst_reg7", "", false, "", "", "", false, CELL_GCM_ATTRIB_OUTPUT_MASK_TEX0 },
{ "tc1", true, "dst_reg8", "", false, "", "", "", false, CELL_GCM_ATTRIB_OUTPUT_MASK_TEX1 },
{ "tc2", true, "dst_reg9", "", false, "", "", "", false, CELL_GCM_ATTRIB_OUTPUT_MASK_TEX2 },
{ "tc3", true, "dst_reg10", "", false, "", "", "", false, CELL_GCM_ATTRIB_OUTPUT_MASK_TEX3 },
{ "tc4", true, "dst_reg11", "", false, "", "", "", false, CELL_GCM_ATTRIB_OUTPUT_MASK_TEX4 },
{ "tc5", true, "dst_reg12", "", false, "", "", "", false, CELL_GCM_ATTRIB_OUTPUT_MASK_TEX5 },
{ "tc6", true, "dst_reg13", "", false, "", "", "", false, CELL_GCM_ATTRIB_OUTPUT_MASK_TEX6 },
{ "tc7", true, "dst_reg14", "", false, "", "", "", false, CELL_GCM_ATTRIB_OUTPUT_MASK_TEX7 },
{ "tc8", true, "dst_reg15", "", false, "", "", "", false, CELL_GCM_ATTRIB_OUTPUT_MASK_TEX8 },
{ "tc0", true, "dst_reg7", "", false, "", "", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_TEX0 },
{ "tc1", true, "dst_reg8", "", false, "", "", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_TEX1 },
{ "tc2", true, "dst_reg9", "", false, "", "", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_TEX2 },
{ "tc3", true, "dst_reg10", "", false, "", "", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_TEX3 },
{ "tc4", true, "dst_reg11", "", false, "", "", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_TEX4 },
{ "tc5", true, "dst_reg12", "", false, "", "", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_TEX5 },
{ "tc6", true, "dst_reg13", "", false, "", "", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_TEX6 },
{ "tc7", true, "dst_reg14", "", false, "", "", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_TEX7 },
{ "tc8", true, "dst_reg15", "", false, "", "", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_TEX8 },
{ "tc9", true, "dst_reg6", "", false, "", "", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_TEX9 } // In this line, dst_reg6 is correct since dst_reg goes from 0 to 15.
};
void GLVertexDecompilerThread::insertOutputs(std::stringstream & OS, const std::vector<ParamType> & outputs)
{
bool insert_front_diffuse = (rsx_vertex_program.output_mask & CELL_GCM_ATTRIB_OUTPUT_MASK_FRONTDIFFUSE) != 0;
bool insert_back_diffuse = (rsx_vertex_program.output_mask & CELL_GCM_ATTRIB_OUTPUT_MASK_BACKDIFFUSE) != 0;
bool insert_front_specular = (rsx_vertex_program.output_mask & CELL_GCM_ATTRIB_OUTPUT_MASK_FRONTSPECULAR) != 0;
bool insert_back_specular = (rsx_vertex_program.output_mask & CELL_GCM_ATTRIB_OUTPUT_MASK_BACKSPECULAR) != 0;
bool front_back_diffuse = (insert_back_diffuse && insert_front_diffuse);
bool front_back_specular = (insert_back_specular && insert_front_specular);
std::vector<std::string> outputs_to_declare;
for (auto &i : reg_table)
{
if (i.need_declare)
{
if (i.name == "front_diff_color")
insert_front_diffuse = false;
if (i.name == "front_spec_color")
insert_front_specular = false;
std::string name = i.name;
if (front_back_diffuse && name == "diff_color")
name = "back_diff_color";
if (front_back_specular && name == "spec_color")
name = "back_spec_color";
outputs_to_declare.push_back(name);
// All outputs must be declared always to allow setting default values
OS << "layout(location=" << gl::get_varying_register_location(i.name) << ") out vec4 " << i.name << ";\n";
}
}
if (insert_back_diffuse && insert_front_diffuse)
outputs_to_declare.emplace_back("front_diff_color");
if (insert_back_specular && insert_front_specular)
outputs_to_declare.emplace_back("front_spec_color");
for (auto &name: outputs_to_declare)
{
OS << "layout(location=" << gl::get_varying_register_location(name) << ") out vec4 " << name << ";\n";
}
}
void GLVertexDecompilerThread::insertMainStart(std::stringstream & OS)
@ -240,65 +205,43 @@ void GLVertexDecompilerThread::insertMainEnd(std::stringstream & OS)
OS << "\n" << " vs_main(" << parameters << ");\n\n";
bool insert_front_diffuse = (rsx_vertex_program.output_mask & CELL_GCM_ATTRIB_OUTPUT_MASK_FRONTDIFFUSE) != 0;
bool insert_front_specular = (rsx_vertex_program.output_mask & CELL_GCM_ATTRIB_OUTPUT_MASK_FRONTSPECULAR) != 0;
bool insert_back_diffuse = (rsx_vertex_program.output_mask & CELL_GCM_ATTRIB_OUTPUT_MASK_BACKDIFFUSE) != 0;
bool insert_back_specular = (rsx_vertex_program.output_mask & CELL_GCM_ATTRIB_OUTPUT_MASK_BACKSPECULAR) != 0;
bool front_back_diffuse = (insert_back_diffuse && insert_front_diffuse);
bool front_back_specular = (insert_back_specular && insert_front_specular);
for (auto &i : reg_table)
{
std::string name = i.name;
if (front_back_diffuse && name == "diff_color")
name = "back_diff_color";
if (front_back_specular && name == "spec_color")
name = "back_spec_color";
if (m_parr.HasParam(PF_PARAM_OUT, "vec4", i.src_reg))
if (!i.check_mask || i.test(rsx_vertex_program.output_mask))
{
if (i.check_mask && (rsx_vertex_program.output_mask & i.check_mask_value) == 0)
if (m_parr.HasParam(PF_PARAM_OUT, "vec4", i.src_reg))
{
std::string condition = (!i.cond.empty()) ? "(" + i.cond + ") " : "";
if (condition.empty() || i.default_val.empty())
{
if (!condition.empty()) condition = "if " + condition;
OS << " " << condition << i.name << " = " << i.src_reg << i.src_reg_mask << ";\n";
}
else
{
//Insert if-else condition
OS << " " << i.name << " = " << condition << "? " << i.src_reg << i.src_reg_mask << ": " << i.default_val << ";\n";
}
// Register was marked for output and a properly initialized source register exists
// Nothing more to do
continue;
if (i.name == "front_diff_color")
insert_front_diffuse = false;
if (i.name == "front_spec_color")
insert_front_specular = false;
std::string condition = (!i.cond.empty()) ? "(" + i.cond + ") " : "";
if (condition.empty() || i.default_val.empty())
{
if (!condition.empty()) condition = "if " + condition;
OS << " " << condition << name << " = " << i.src_reg << i.src_reg_mask << ";\n";
}
else
{
//Insert if-else condition
OS << " " << name << " = " << condition << "? " << i.src_reg << i.src_reg_mask << ": " << i.default_val << ";\n";
}
}
else if (i.need_declare && (rsx_vertex_program.output_mask & i.check_mask_value) > 0)
if (i.need_declare)
{
//An output was declared but nothing was written to it
//Set it to all ones (Atelier Escha)
OS << " " << name << " = vec4(1.);\n";
OS << " " << i.name << " = vec4(0., 0., 0., 1.);\n";
}
}
if (insert_back_diffuse && insert_front_diffuse)
if (m_parr.HasParam(PF_PARAM_OUT, "vec4", "dst_reg1"))
OS << " front_diff_color = dst_reg1;\n";
// Default point size if none was generated by the program
if ((rsx_vertex_program.output_mask & CELL_GCM_ATTRIB_OUTPUT_MASK_POINTSIZE) == 0)
{
OS << " gl_PointSize = point_size;\n";
}
if (insert_back_specular && insert_front_specular)
if (m_parr.HasParam(PF_PARAM_OUT, "vec4", "dst_reg2"))
OS << " front_spec_color = dst_reg2;\n";
OS << " gl_PointSize = point_size;\n";
OS << " gl_Position = gl_Position * scale_offset_mat;\n";
OS << " gl_Position = apply_zclip_xform(gl_Position, z_near, z_far);\n";

View File

@ -234,12 +234,9 @@ struct RSXFragmentProgram
u16 unnormalized_coords;
u16 redirected_textures;
u16 shadow_textures;
bool front_back_color_enabled : 1;
bool back_color_diffuse_output : 1;
bool back_color_specular_output : 1;
bool front_color_diffuse_output : 1;
bool front_color_specular_output : 1;
bool two_sided_lighting;
u32 texture_dimensions;
u32 texcoord_control_mask;
float texture_scale[16][4];
u8 textures_alpha_kill[16];
@ -252,6 +249,11 @@ struct RSXFragmentProgram
return (rsx::texture_dimension_extended)((texture_dimensions >> (id * 2)) & 0x3);
}
bool texcoord_is_2d(u8 index) const
{
return !!(texcoord_control_mask & (1u << index));
}
RSXFragmentProgram()
{
memset(this, 0, sizeof(RSXFragmentProgram));

View File

@ -1618,12 +1618,9 @@ namespace rsx
result.ucode_length = current_fp_metadata.program_ucode_length;
result.valid = true;
result.ctrl = rsx::method_registers.shader_control() & (CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS | CELL_GCM_SHADER_CONTROL_DEPTH_EXPORT);
result.texcoord_control_mask = rsx::method_registers.texcoord_control_mask();
result.unnormalized_coords = 0;
result.front_back_color_enabled = !rsx::method_registers.two_side_light_en();
result.back_color_diffuse_output = !!(rsx::method_registers.vertex_attrib_output_mask() & CELL_GCM_ATTRIB_OUTPUT_MASK_BACKDIFFUSE);
result.back_color_specular_output = !!(rsx::method_registers.vertex_attrib_output_mask() & CELL_GCM_ATTRIB_OUTPUT_MASK_BACKSPECULAR);
result.front_color_diffuse_output = !!(rsx::method_registers.vertex_attrib_output_mask() & CELL_GCM_ATTRIB_OUTPUT_MASK_FRONTDIFFUSE);
result.front_color_specular_output = !!(rsx::method_registers.vertex_attrib_output_mask() & CELL_GCM_ATTRIB_OUTPUT_MASK_FRONTSPECULAR);
result.two_sided_lighting = rsx::method_registers.two_side_light_en();
result.redirected_textures = 0;
result.shadow_textures = 0;
@ -1754,11 +1751,7 @@ namespace rsx
result.valid = true;
result.ctrl = rsx::method_registers.shader_control() & (CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS | CELL_GCM_SHADER_CONTROL_DEPTH_EXPORT);
result.unnormalized_coords = 0;
result.front_back_color_enabled = !rsx::method_registers.two_side_light_en();
result.back_color_diffuse_output = !!(rsx::method_registers.vertex_attrib_output_mask() & CELL_GCM_ATTRIB_OUTPUT_MASK_BACKDIFFUSE);
result.back_color_specular_output = !!(rsx::method_registers.vertex_attrib_output_mask() & CELL_GCM_ATTRIB_OUTPUT_MASK_BACKSPECULAR);
result.front_color_diffuse_output = !!(rsx::method_registers.vertex_attrib_output_mask() & CELL_GCM_ATTRIB_OUTPUT_MASK_FRONTDIFFUSE);
result.front_color_specular_output = !!(rsx::method_registers.vertex_attrib_output_mask() & CELL_GCM_ATTRIB_OUTPUT_MASK_FRONTSPECULAR);
result.two_sided_lighting = rsx::method_registers.two_side_light_en();
result.redirected_textures = 0;
result.shadow_textures = 0;

View File

@ -1,4 +1,4 @@
#include "stdafx.h"
#include "stdafx.h"
#include "VKCommonDecompiler.h"
#include "restore_new.h"
#include "SPIRV/GlslangToSpv.h"
@ -118,11 +118,9 @@ namespace vk
{ "tc8", 8 },
{ "tc9", 9 },
{ "diff_color", 10 },
{ "back_diff_color", 10 },
{ "front_diff_color", 11 },
{ "diff_color1", 11 },
{ "spec_color", 12 },
{ "back_spec_color", 12 },
{ "front_spec_color", 13 },
{ "spec_color1", 13 },
{ "fog_c", 14 },
{ "fogc", 14 }
}};

View File

@ -44,9 +44,6 @@ void VKFragmentDecompilerThread::insertHeader(std::stringstream & OS)
void VKFragmentDecompilerThread::insertInputs(std::stringstream & OS)
{
//It is possible for the two_sided_enabled flag to be set without actual 2-sided outputs
bool two_sided_enabled = m_prog.front_back_color_enabled && (m_prog.back_color_diffuse_output || m_prog.back_color_specular_output);
for (const ParamType& PT : m_parr.params[PF_PARAM_IN])
{
for (const ParamItem& PI : PT.items)
@ -57,33 +54,36 @@ void VKFragmentDecompilerThread::insertInputs(std::stringstream & OS)
const auto reg_location = vk::get_varying_register_location(PI.name);
std::string var_name = PI.name;
if (two_sided_enabled)
{
if (m_prog.back_color_diffuse_output && var_name == "diff_color")
var_name = "back_diff_color";
if (m_prog.back_color_specular_output && var_name == "spec_color")
var_name = "back_spec_color";
}
if (var_name == "fogc")
{
var_name = "fog_c";
}
else if (m_prog.two_sided_lighting)
{
if (var_name == "diff_color")
{
var_name = "diff_color0";
}
else if (var_name == "spec_color")
{
var_name = "spec_color0";
}
}
OS << "layout(location=" << reg_location << ") in " << PT.type << " " << var_name << ";\n";
}
}
if (two_sided_enabled)
if (m_prog.two_sided_lighting)
{
//Only include the front counterparts if the default output is for back only and exists.
if (m_prog.front_color_diffuse_output && m_prog.back_color_diffuse_output)
if (properties.in_register_mask & in_diff_color)
{
OS << "layout(location=" << vk::get_varying_register_location("front_diff_color") << ") in vec4 front_diff_color;\n";
OS << "layout(location=" << vk::get_varying_register_location("diff_color1") << ") in vec4 diff_color1;\n";
}
if (m_prog.front_color_specular_output && m_prog.back_color_specular_output)
if (properties.in_register_mask & in_spec_color)
{
OS << "layout(location=" << vk::get_varying_register_location("front_spec_color") << ") in vec4 front_spec_color;\n";
OS << "layout(location=" << vk::get_varying_register_location("spec_color1") << ") in vec4 spec_color1;\n";
}
}
}
@ -231,7 +231,7 @@ void VKFragmentDecompilerThread::insertGlobalFunctions(std::stringstream &OS)
properties2.require_lit_emulation = properties.has_lit_op;
properties2.fp32_outputs = !!(m_prog.ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS);
properties2.require_depth_conversion = m_prog.redirected_textures != 0;
properties2.require_wpos = properties.has_wpos_input;
properties2.require_wpos = !!(properties.in_register_mask & in_wpos);
properties2.require_texture_ops = properties.has_tex_op;
properties2.require_shadow_ops = m_prog.shadow_textures != 0;
properties2.emulate_coverage_tests = g_cfg.video.antialiasing_level == msaa_level::none;
@ -243,18 +243,8 @@ void VKFragmentDecompilerThread::insertGlobalFunctions(std::stringstream &OS)
void VKFragmentDecompilerThread::insertMainStart(std::stringstream & OS)
{
//TODO: Generate input mask during parse stage to avoid this
for (const ParamType& PT : m_parr.params[PF_PARAM_IN])
{
for (const ParamItem& PI : PT.items)
{
if (PI.name == "fogc")
{
glsl::insert_fog_declaration(OS);
break;
}
}
}
if (properties.in_register_mask & in_fogc)
glsl::insert_fog_declaration(OS);
const std::set<std::string> output_values =
{
@ -294,64 +284,22 @@ void VKFragmentDecompilerThread::insertMainStart(std::stringstream & OS)
}
}
if (m_parr.HasParam(PF_PARAM_IN, "vec4", "ssa"))
if (properties.in_register_mask & in_ssa)
OS << " vec4 ssa = gl_FrontFacing ? vec4(1.) : vec4(-1.);\n";
if (properties.has_wpos_input)
if (properties.in_register_mask & in_wpos)
OS << " vec4 wpos = get_wpos();\n";
bool two_sided_enabled = m_prog.front_back_color_enabled && (m_prog.back_color_diffuse_output || m_prog.back_color_specular_output);
if (properties.in_register_mask & in_fogc)
OS << " vec4 fogc = fetch_fog_value(fog_mode);\n";
//Some registers require redirection
for (const ParamType& PT : m_parr.params[PF_PARAM_IN])
if (m_prog.two_sided_lighting)
{
for (const ParamItem& PI : PT.items)
{
if (two_sided_enabled)
{
if (PI.name == "spec_color")
{
//Only redirect/rename variables if the back_color exists
if (m_prog.back_color_specular_output)
{
if (m_prog.back_color_specular_output && m_prog.front_color_specular_output)
{
OS << " vec4 spec_color = gl_FrontFacing ? front_spec_color : back_spec_color;\n";
}
else
{
OS << " vec4 spec_color = back_spec_color;\n";
}
}
if (properties.in_register_mask & in_diff_color)
OS << " vec4 diff_color = gl_FrontFacing ? diff_color1 : diff_color0;\n";
continue;
}
else if (PI.name == "diff_color")
{
//Only redirect/rename variables if the back_color exists
if (m_prog.back_color_diffuse_output)
{
if (m_prog.back_color_diffuse_output && m_prog.front_color_diffuse_output)
{
OS << " vec4 diff_color = gl_FrontFacing ? front_diff_color : back_diff_color;\n";
}
else
{
OS << " vec4 diff_color = back_diff_color;\n";
}
}
continue;
}
}
if (PI.name == "fogc")
{
OS << " vec4 fogc = fetch_fog_value(fog_mode);\n";
continue;
}
}
if (properties.in_register_mask & in_spec_color)
OS << " vec4 spec_color = gl_FrontFacing ? spec_color1 : spec_color0;\n";
}
}

View File

@ -503,7 +503,7 @@ VKGSRender::VKGSRender() : GSRender()
else
m_vertex_cache = std::make_unique<vk::weak_vertex_cache>();
m_shaders_cache = std::make_unique<vk::shader_cache>(*m_prog_buffer, "vulkan", "v1.8");
m_shaders_cache = std::make_unique<vk::shader_cache>(*m_prog_buffer, "vulkan", "v1.91");
open_command_buffer();

View File

@ -6,6 +6,8 @@
#include "VKHelpers.h"
#include "../Common/GLSLCommon.h"
#pragma optimize("", off)
std::string VKVertexDecompilerThread::getFloatTypeName(size_t elementCount)
{
return glsl::getFloatTypeNameImpl(elementCount);
@ -129,70 +131,41 @@ static const vertex_reg_info reg_table[] =
{
{ "gl_Position", false, "dst_reg0", "", false },
//Technically these two are for both back and front
{ "back_diff_color", true, "dst_reg1", "", false, "", "", "", false, CELL_GCM_ATTRIB_OUTPUT_MASK_FRONTDIFFUSE },
{ "back_spec_color", true, "dst_reg2", "", false, "", "", "", false, CELL_GCM_ATTRIB_OUTPUT_MASK_FRONTSPECULAR },
{ "front_diff_color", true, "dst_reg3", "", false },
{ "front_spec_color", true, "dst_reg4", "", false },
{ "diff_color", true, "dst_reg1", "", false, "", "", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_FRONTDIFFUSE | CELL_GCM_ATTRIB_OUTPUT_MASK_BACKDIFFUSE },
{ "spec_color", true, "dst_reg2", "", false, "", "", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_FRONTSPECULAR | CELL_GCM_ATTRIB_OUTPUT_MASK_BACKSPECULAR },
{ "diff_color1", true, "dst_reg3", "", false, "", "", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_FRONTDIFFUSE | CELL_GCM_ATTRIB_OUTPUT_MASK_BACKDIFFUSE },
{ "spec_color1", true, "dst_reg4", "", false, "", "", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_FRONTSPECULAR | CELL_GCM_ATTRIB_OUTPUT_MASK_BACKSPECULAR },
{ "fog_c", true, "dst_reg5", ".xxxx", true, "", "", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_FOG },
//Warning: With spir-v if you declare clip distance var, you must assign a value even when its disabled! Runtime does not assign a default value
{ "gl_ClipDistance[0]", false, "dst_reg5", ".y * user_clip_factor[0].x", false, "user_clip_enabled[0].x > 0", "0.5", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_UC0 },
{ "gl_ClipDistance[1]", false, "dst_reg5", ".z * user_clip_factor[0].y", false, "user_clip_enabled[0].y > 0", "0.5", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_UC1 },
{ "gl_ClipDistance[2]", false, "dst_reg5", ".w * user_clip_factor[0].z", false, "user_clip_enabled[0].z > 0", "0.5", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_UC2 },
{ "gl_PointSize", false, "dst_reg6", ".x", false },
{ "gl_PointSize", false, "dst_reg6", ".x", false, "", "", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_POINTSIZE },
{ "gl_ClipDistance[3]", false, "dst_reg6", ".y * user_clip_factor[0].w", false, "user_clip_enabled[0].w > 0", "0.5", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_UC3 },
{ "gl_ClipDistance[4]", false, "dst_reg6", ".z * user_clip_factor[1].x", false, "user_clip_enabled[1].x > 0", "0.5", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_UC4 },
{ "gl_ClipDistance[5]", false, "dst_reg6", ".w * user_clip_factor[1].y", false, "user_clip_enabled[1].y > 0", "0.5", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_UC5 },
{ "tc0", true, "dst_reg7", "", false, "", "", "", false, CELL_GCM_ATTRIB_OUTPUT_MASK_TEX0 },
{ "tc1", true, "dst_reg8", "", false, "", "", "", false, CELL_GCM_ATTRIB_OUTPUT_MASK_TEX1 },
{ "tc2", true, "dst_reg9", "", false, "", "", "", false, CELL_GCM_ATTRIB_OUTPUT_MASK_TEX2 },
{ "tc3", true, "dst_reg10", "", false, "", "", "", false, CELL_GCM_ATTRIB_OUTPUT_MASK_TEX3 },
{ "tc4", true, "dst_reg11", "", false, "", "", "", false, CELL_GCM_ATTRIB_OUTPUT_MASK_TEX4 },
{ "tc5", true, "dst_reg12", "", false, "", "", "", false, CELL_GCM_ATTRIB_OUTPUT_MASK_TEX5 },
{ "tc6", true, "dst_reg13", "", false, "", "", "", false, CELL_GCM_ATTRIB_OUTPUT_MASK_TEX6 },
{ "tc7", true, "dst_reg14", "", false, "", "", "", false, CELL_GCM_ATTRIB_OUTPUT_MASK_TEX7 },
{ "tc8", true, "dst_reg15", "", false, "", "", "", false, CELL_GCM_ATTRIB_OUTPUT_MASK_TEX8 },
{ "tc0", true, "dst_reg7", "", false, "", "", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_TEX0 },
{ "tc1", true, "dst_reg8", "", false, "", "", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_TEX1 },
{ "tc2", true, "dst_reg9", "", false, "", "", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_TEX2 },
{ "tc3", true, "dst_reg10", "", false, "", "", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_TEX3 },
{ "tc4", true, "dst_reg11", "", false, "", "", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_TEX4 },
{ "tc5", true, "dst_reg12", "", false, "", "", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_TEX5 },
{ "tc6", true, "dst_reg13", "", false, "", "", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_TEX6 },
{ "tc7", true, "dst_reg14", "", false, "", "", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_TEX7 },
{ "tc8", true, "dst_reg15", "", false, "", "", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_TEX8 },
{ "tc9", true, "dst_reg6", "", false, "", "", "", true, CELL_GCM_ATTRIB_OUTPUT_MASK_TEX9 } // In this line, dst_reg6 is correct since dst_reg goes from 0 to 15.
};
void VKVertexDecompilerThread::insertOutputs(std::stringstream & OS, const std::vector<ParamType> & outputs)
{
bool insert_front_diffuse = (rsx_vertex_program.output_mask & CELL_GCM_ATTRIB_OUTPUT_MASK_FRONTDIFFUSE) != 0;
bool insert_back_diffuse = (rsx_vertex_program.output_mask & CELL_GCM_ATTRIB_OUTPUT_MASK_BACKDIFFUSE) != 0;
bool insert_front_specular = (rsx_vertex_program.output_mask & CELL_GCM_ATTRIB_OUTPUT_MASK_FRONTSPECULAR) != 0;
bool insert_back_specular = (rsx_vertex_program.output_mask & CELL_GCM_ATTRIB_OUTPUT_MASK_BACKSPECULAR) != 0;
for (auto &i : reg_table)
{
if (m_parr.HasParam(PF_PARAM_OUT, "vec4", i.src_reg) && i.need_declare)
if (i.need_declare)
{
if (i.check_mask && (rsx_vertex_program.output_mask & i.check_mask_value) == 0)
continue;
if (i.name == "front_diff_color")
insert_front_diffuse = false;
if (i.name == "front_spec_color")
insert_front_specular = false;
// All outputs must be declared always to allow setting default values
OS << "layout(location=" << vk::get_varying_register_location(i.name) << ") out vec4 " << i.name << ";\n";
}
else
{
//Force some outputs to be declared even if unused so we can set default values
//NOTE: Registers that can be skept will not have their check_mask_value set
if (i.need_declare && (rsx_vertex_program.output_mask & i.check_mask_value) > 0)
{
OS << "layout(location=" << vk::get_varying_register_location(i.name) << ") out vec4 " << i.name << ";\n";
}
}
}
if (insert_back_diffuse && insert_front_diffuse)
OS << "layout(location=" << vk::get_varying_register_location("front_diff_color") << ") out vec4 front_diff_color;\n";
if (insert_back_specular && insert_front_specular)
OS << "layout(location=" << vk::get_varying_register_location("front_spec_color") << ") out vec4 front_spec_color;\n";
}
void VKVertexDecompilerThread::insertMainStart(std::stringstream & OS)
@ -280,55 +253,43 @@ void VKVertexDecompilerThread::insertMainEnd(std::stringstream & OS)
OS << "\n" << " vs_main(" << parameters << ");\n\n";
bool insert_front_diffuse = (rsx_vertex_program.output_mask & CELL_GCM_ATTRIB_OUTPUT_MASK_FRONTDIFFUSE) != 0;
bool insert_front_specular = (rsx_vertex_program.output_mask & CELL_GCM_ATTRIB_OUTPUT_MASK_FRONTSPECULAR) != 0;
bool insert_back_diffuse = (rsx_vertex_program.output_mask & CELL_GCM_ATTRIB_OUTPUT_MASK_BACKDIFFUSE) != 0;
bool insert_back_specular = (rsx_vertex_program.output_mask & CELL_GCM_ATTRIB_OUTPUT_MASK_BACKSPECULAR) != 0;
for (auto &i : reg_table)
{
if (m_parr.HasParam(PF_PARAM_OUT, "vec4", i.src_reg))
if (!i.check_mask || i.test(rsx_vertex_program.output_mask))
{
if (i.check_mask && (rsx_vertex_program.output_mask & i.check_mask_value) == 0)
if (m_parr.HasParam(PF_PARAM_OUT, "vec4", i.src_reg))
{
std::string condition = (!i.cond.empty()) ? "(" + i.cond + ") " : "";
if (condition.empty() || i.default_val.empty())
{
if (!condition.empty()) condition = "if " + condition;
OS << " " << condition << i.name << " = " << i.src_reg << i.src_reg_mask << ";\n";
}
else
{
//Insert if-else condition
OS << " " << i.name << " = " << condition << "? " << i.src_reg << i.src_reg_mask << ": " << i.default_val << ";\n";
}
// Register was marked for output and a properly initialized source register exists
// Nothing more to do
continue;
if (i.name == "front_diff_color")
insert_front_diffuse = false;
if (i.name == "front_spec_color")
insert_front_specular = false;
std::string condition = (!i.cond.empty()) ? "(" + i.cond + ") " : "";
if (condition.empty() || i.default_val.empty())
{
if (!condition.empty()) condition = "if " + condition;
OS << " " << condition << i.name << " = " << i.src_reg << i.src_reg_mask << ";\n";
}
else
{
//Insert if-else condition
OS << " " << i.name << " = " << condition << "? " << i.src_reg << i.src_reg_mask << ": " << i.default_val << ";\n";
}
}
else if (i.need_declare && (rsx_vertex_program.output_mask & i.check_mask_value) > 0)
if (i.need_declare)
{
//An output was declared but nothing was written to it
//Set it to all ones (Atelier Escha)
OS << " " << i.name << " = vec4(1.);\n";
OS << " " << i.name << " = vec4(0., 0., 0., 1.);\n";
}
}
if (insert_back_diffuse && insert_front_diffuse)
if (m_parr.HasParam(PF_PARAM_OUT, "vec4", "dst_reg1"))
OS << " front_diff_color = dst_reg1;\n";
// Default point size if none was generated by the program
if ((rsx_vertex_program.output_mask & CELL_GCM_ATTRIB_OUTPUT_MASK_POINTSIZE) == 0)
{
OS << " gl_PointSize = point_size;\n";
}
if (insert_back_specular && insert_front_specular)
if (m_parr.HasParam(PF_PARAM_OUT, "vec4", "dst_reg2"))
OS << " front_spec_color = dst_reg2;\n";
OS << " gl_PointSize = point_size;\n";
OS << " gl_Position = gl_Position * scale_offset_mat;\n";
OS << " gl_Position = apply_zclip_xform(gl_Position, z_near, z_far);\n";
OS << "}\n";

View File

@ -401,6 +401,7 @@ namespace rsx
u32 fp_ctrl;
u32 fp_texture_dimensions;
u32 fp_texcoord_control;
u16 fp_unnormalized_coords;
u16 fp_height;
u16 fp_pixel_layout;
@ -738,6 +739,7 @@ namespace rsx
state_hash ^= rpcs3::hash_base<u32>(data.fp_ctrl);
state_hash ^= rpcs3::hash_base<u32>(data.vp_texture_dimensions);
state_hash ^= rpcs3::hash_base<u32>(data.fp_texture_dimensions);
state_hash ^= rpcs3::hash_base<u32>(data.fp_texcoord_control);
state_hash ^= rpcs3::hash_base<u16>(data.fp_unnormalized_coords);
state_hash ^= rpcs3::hash_base<u16>(data.fp_height);
state_hash ^= rpcs3::hash_base<u16>(data.fp_pixel_layout);
@ -810,12 +812,9 @@ namespace rsx
fp.ctrl = data.fp_ctrl;
fp.texture_dimensions = data.fp_texture_dimensions;
fp.texcoord_control_mask = data.fp_texcoord_control;
fp.unnormalized_coords = data.fp_unnormalized_coords;
fp.front_back_color_enabled = (data.fp_lighting_flags & 0x1) != 0;
fp.back_color_diffuse_output = ((data.fp_lighting_flags >> 1) & 0x1) != 0;
fp.back_color_specular_output = ((data.fp_lighting_flags >> 2) & 0x1) != 0;
fp.front_color_diffuse_output = ((data.fp_lighting_flags >> 3) & 0x1) != 0;
fp.front_color_specular_output = ((data.fp_lighting_flags >> 4) & 0x1) != 0;
fp.two_sided_lighting = !!(data.fp_lighting_flags & 0x1);
fp.shadow_textures = data.fp_shadow_textures;
fp.redirected_textures = data.fp_redirected_textures;
@ -863,9 +862,9 @@ namespace rsx
data_block.fp_ctrl = fp.ctrl;
data_block.fp_texture_dimensions = fp.texture_dimensions;
data_block.fp_texcoord_control = fp.texcoord_control_mask;
data_block.fp_unnormalized_coords = fp.unnormalized_coords;
data_block.fp_lighting_flags = (u16)fp.front_back_color_enabled | (u16)fp.back_color_diffuse_output << 1 |
(u16)fp.back_color_specular_output << 2 | (u16)fp.front_color_diffuse_output << 3 | (u16)fp.front_color_specular_output << 4;
data_block.fp_lighting_flags = u16(fp.two_sided_lighting);
data_block.fp_shadow_textures = fp.shadow_textures;
data_block.fp_redirected_textures = fp.redirected_textures;

View File

@ -1624,6 +1624,18 @@ namespace rsx
{
return decode<NV4097_SET_CONTROL0>().depth_float();
}
u32 texcoord_control_mask()
{
// Only 10 texture coords exist [0-9]
u32 control_mask = 0;
for (u8 index = 0; index < 10; ++index)
{
control_mask |= ((registers[NV4097_SET_TEX_COORD_CONTROL + index] & 1) << index);
}
return control_mask;
}
};
extern rsx_state method_registers;