diff --git a/rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.cpp b/rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.cpp index 017044dc6d..c9ff52bc08 100644 --- a/rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.cpp +++ b/rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.cpp @@ -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 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; diff --git a/rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.h b/rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.h index 7233c8ef92..3a87cf3add 100644 --- a/rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.h +++ b/rpcs3/Emu/RSX/Common/FragmentProgramDecompiler.h @@ -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; diff --git a/rpcs3/Emu/RSX/Common/ProgramStateCache.cpp b/rpcs3/Emu/RSX/Common/ProgramStateCache.cpp index b791333758..2bb221c968 100644 --- a/rpcs3/Emu/RSX/Common/ProgramStateCache.cpp +++ b/rpcs3/Emu/RSX/Common/ProgramStateCache.cpp @@ -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; diff --git a/rpcs3/Emu/RSX/Common/ShaderParam.h b/rpcs3/Emu/RSX/Common/ShaderParam.h index eec54c2913..3f27c4ef27 100644 --- a/rpcs3/Emu/RSX/Common/ShaderParam.h +++ b/rpcs3/Emu/RSX/Common/ShaderParam.h @@ -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); + } }; diff --git a/rpcs3/Emu/RSX/D3D12/D3D12FragmentProgramDecompiler.cpp b/rpcs3/Emu/RSX/D3D12/D3D12FragmentProgramDecompiler.cpp index 795469023e..87940d67aa 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12FragmentProgramDecompiler.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12FragmentProgramDecompiler.cpp @@ -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"; diff --git a/rpcs3/Emu/RSX/GL/GLCommonDecompiler.cpp b/rpcs3/Emu/RSX/GL/GLCommonDecompiler.cpp index bb67c0249a..625e6b6dc6 100644 --- a/rpcs3/Emu/RSX/GL/GLCommonDecompiler.cpp +++ b/rpcs3/Emu/RSX/GL/GLCommonDecompiler.cpp @@ -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}, diff --git a/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp b/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp index 7a2a70bebd..5beca7413b 100644 --- a/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp +++ b/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp @@ -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 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 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"; } } diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index 38b95c5388..4a9492042c 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -29,7 +29,7 @@ u64 GLGSRender::get_cycles() GLGSRender::GLGSRender() : GSRender() { - m_shaders_cache = std::make_unique(m_prog_buffer, "opengl", "v1.6"); + m_shaders_cache = std::make_unique(m_prog_buffer, "opengl", "v1.91"); if (g_cfg.video.disable_vertex_cache || g_cfg.video.multithreaded_rsx) m_vertex_cache = std::make_unique(); diff --git a/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp b/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp index 7c40ad3435..1d841b084d 100644 --- a/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp +++ b/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp @@ -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 & 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 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"; diff --git a/rpcs3/Emu/RSX/RSXFragmentProgram.h b/rpcs3/Emu/RSX/RSXFragmentProgram.h index 5a35eefe71..ff1ac3260f 100644 --- a/rpcs3/Emu/RSX/RSXFragmentProgram.h +++ b/rpcs3/Emu/RSX/RSXFragmentProgram.h @@ -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)); diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 1012df95ba..81498eab95 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -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; diff --git a/rpcs3/Emu/RSX/VK/VKCommonDecompiler.cpp b/rpcs3/Emu/RSX/VK/VKCommonDecompiler.cpp index c05f816fd3..e6a67e6418 100644 --- a/rpcs3/Emu/RSX/VK/VKCommonDecompiler.cpp +++ b/rpcs3/Emu/RSX/VK/VKCommonDecompiler.cpp @@ -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 } }}; diff --git a/rpcs3/Emu/RSX/VK/VKFragmentProgram.cpp b/rpcs3/Emu/RSX/VK/VKFragmentProgram.cpp index b8e1f07890..c320c8e734 100644 --- a/rpcs3/Emu/RSX/VK/VKFragmentProgram.cpp +++ b/rpcs3/Emu/RSX/VK/VKFragmentProgram.cpp @@ -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 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"; } } diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index 29402b7554..531d6ec518 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -503,7 +503,7 @@ VKGSRender::VKGSRender() : GSRender() else m_vertex_cache = std::make_unique(); - m_shaders_cache = std::make_unique(*m_prog_buffer, "vulkan", "v1.8"); + m_shaders_cache = std::make_unique(*m_prog_buffer, "vulkan", "v1.91"); open_command_buffer(); diff --git a/rpcs3/Emu/RSX/VK/VKVertexProgram.cpp b/rpcs3/Emu/RSX/VK/VKVertexProgram.cpp index 297713f8e4..c7bd2427b1 100644 --- a/rpcs3/Emu/RSX/VK/VKVertexProgram.cpp +++ b/rpcs3/Emu/RSX/VK/VKVertexProgram.cpp @@ -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 & 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"; diff --git a/rpcs3/Emu/RSX/rsx_cache.h b/rpcs3/Emu/RSX/rsx_cache.h index c0aa15be77..ebcd3951bc 100644 --- a/rpcs3/Emu/RSX/rsx_cache.h +++ b/rpcs3/Emu/RSX/rsx_cache.h @@ -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(data.fp_ctrl); state_hash ^= rpcs3::hash_base(data.vp_texture_dimensions); state_hash ^= rpcs3::hash_base(data.fp_texture_dimensions); + state_hash ^= rpcs3::hash_base(data.fp_texcoord_control); state_hash ^= rpcs3::hash_base(data.fp_unnormalized_coords); state_hash ^= rpcs3::hash_base(data.fp_height); state_hash ^= rpcs3::hash_base(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; diff --git a/rpcs3/Emu/RSX/rsx_methods.h b/rpcs3/Emu/RSX/rsx_methods.h index ebe36a228e..640efd8a75 100644 --- a/rpcs3/Emu/RSX/rsx_methods.h +++ b/rpcs3/Emu/RSX/rsx_methods.h @@ -1624,6 +1624,18 @@ namespace rsx { return decode().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;