diff --git a/rpcs3/Emu/RSX/GCM.h b/rpcs3/Emu/RSX/GCM.h index f42f07fa04..82c583c876 100644 --- a/rpcs3/Emu/RSX/GCM.h +++ b/rpcs3/Emu/RSX/GCM.h @@ -515,28 +515,51 @@ enum CELL_GCM_SCULL_SFUNC_GEQUAL = 6, CELL_GCM_SCULL_SFUNC_ALWAYS = 7, - CELL_GCM_ATTRIB_OUTPUT_MASK_FRONTDIFFUSE = 1 << 0, - CELL_GCM_ATTRIB_OUTPUT_MASK_FRONTSPECULAR = 1 << 1, - CELL_GCM_ATTRIB_OUTPUT_MASK_BACKDIFFUSE = 1 << 2, - CELL_GCM_ATTRIB_OUTPUT_MASK_BACKSPECULAR = 1 << 3, - CELL_GCM_ATTRIB_OUTPUT_MASK_FOG = 1 << 4, - CELL_GCM_ATTRIB_OUTPUT_MASK_POINTSIZE = 1 << 5, - CELL_GCM_ATTRIB_OUTPUT_MASK_UC0 = 1 << 6, - CELL_GCM_ATTRIB_OUTPUT_MASK_UC1 = 1 << 7, - CELL_GCM_ATTRIB_OUTPUT_MASK_UC2 = 1 << 8, - CELL_GCM_ATTRIB_OUTPUT_MASK_UC3 = 1 << 9, - CELL_GCM_ATTRIB_OUTPUT_MASK_UC4 = 1 << 10, - CELL_GCM_ATTRIB_OUTPUT_MASK_UC5 = 1 << 11, - CELL_GCM_ATTRIB_OUTPUT_MASK_TEX8 = 1 << 12, - CELL_GCM_ATTRIB_OUTPUT_MASK_TEX9 = 1 << 13, - CELL_GCM_ATTRIB_OUTPUT_MASK_TEX0 = 1 << 14, - CELL_GCM_ATTRIB_OUTPUT_MASK_TEX1 = 1 << 15, - CELL_GCM_ATTRIB_OUTPUT_MASK_TEX2 = 1 << 16, - CELL_GCM_ATTRIB_OUTPUT_MASK_TEX3 = 1 << 17, - CELL_GCM_ATTRIB_OUTPUT_MASK_TEX4 = 1 << 18, - CELL_GCM_ATTRIB_OUTPUT_MASK_TEX5 = 1 << 19, - CELL_GCM_ATTRIB_OUTPUT_MASK_TEX6 = 1 << 20, - CELL_GCM_ATTRIB_OUTPUT_MASK_TEX7 = 1 << 21, + CELL_GCM_ATTRIB_OUTPUT_FRONTDIFFUSE = 0, + CELL_GCM_ATTRIB_OUTPUT_FRONTSPECULAR = 1, + CELL_GCM_ATTRIB_OUTPUT_BACKDIFFUSE = 2, + CELL_GCM_ATTRIB_OUTPUT_BACKSPECULAR = 3, + CELL_GCM_ATTRIB_OUTPUT_FOG = 4, + CELL_GCM_ATTRIB_OUTPUT_POINTSIZE = 5, + CELL_GCM_ATTRIB_OUTPUT_UC0 = 6, + CELL_GCM_ATTRIB_OUTPUT_UC1 = 7, + CELL_GCM_ATTRIB_OUTPUT_UC2 = 8, + CELL_GCM_ATTRIB_OUTPUT_UC3 = 9, + CELL_GCM_ATTRIB_OUTPUT_UC4 = 10, + CELL_GCM_ATTRIB_OUTPUT_UC5 = 11, + CELL_GCM_ATTRIB_OUTPUT_TEX8 = 12, + CELL_GCM_ATTRIB_OUTPUT_TEX9 = 13, + CELL_GCM_ATTRIB_OUTPUT_TEX0 = 14, + CELL_GCM_ATTRIB_OUTPUT_TEX1 = 15, + CELL_GCM_ATTRIB_OUTPUT_TEX2 = 16, + CELL_GCM_ATTRIB_OUTPUT_TEX3 = 17, + CELL_GCM_ATTRIB_OUTPUT_TEX4 = 18, + CELL_GCM_ATTRIB_OUTPUT_TEX5 = 19, + CELL_GCM_ATTRIB_OUTPUT_TEX6 = 20, + CELL_GCM_ATTRIB_OUTPUT_TEX7 = 21, + + CELL_GCM_ATTRIB_OUTPUT_MASK_FRONTDIFFUSE = 1 << CELL_GCM_ATTRIB_OUTPUT_FRONTDIFFUSE, + CELL_GCM_ATTRIB_OUTPUT_MASK_FRONTSPECULAR = 1 << CELL_GCM_ATTRIB_OUTPUT_FRONTSPECULAR, + CELL_GCM_ATTRIB_OUTPUT_MASK_BACKDIFFUSE = 1 << CELL_GCM_ATTRIB_OUTPUT_BACKDIFFUSE, + CELL_GCM_ATTRIB_OUTPUT_MASK_BACKSPECULAR = 1 << CELL_GCM_ATTRIB_OUTPUT_BACKSPECULAR, + CELL_GCM_ATTRIB_OUTPUT_MASK_FOG = 1 << CELL_GCM_ATTRIB_OUTPUT_FOG, + CELL_GCM_ATTRIB_OUTPUT_MASK_POINTSIZE = 1 << CELL_GCM_ATTRIB_OUTPUT_POINTSIZE, + CELL_GCM_ATTRIB_OUTPUT_MASK_UC0 = 1 << CELL_GCM_ATTRIB_OUTPUT_UC0, + CELL_GCM_ATTRIB_OUTPUT_MASK_UC1 = 1 << CELL_GCM_ATTRIB_OUTPUT_UC1, + CELL_GCM_ATTRIB_OUTPUT_MASK_UC2 = 1 << CELL_GCM_ATTRIB_OUTPUT_UC2, + CELL_GCM_ATTRIB_OUTPUT_MASK_UC3 = 1 << CELL_GCM_ATTRIB_OUTPUT_UC3, + CELL_GCM_ATTRIB_OUTPUT_MASK_UC4 = 1 << CELL_GCM_ATTRIB_OUTPUT_UC4, + CELL_GCM_ATTRIB_OUTPUT_MASK_UC5 = 1 << CELL_GCM_ATTRIB_OUTPUT_UC5, + CELL_GCM_ATTRIB_OUTPUT_MASK_TEX8 = 1 << CELL_GCM_ATTRIB_OUTPUT_TEX8, + CELL_GCM_ATTRIB_OUTPUT_MASK_TEX9 = 1 << CELL_GCM_ATTRIB_OUTPUT_TEX9, + CELL_GCM_ATTRIB_OUTPUT_MASK_TEX0 = 1 << CELL_GCM_ATTRIB_OUTPUT_TEX0, + CELL_GCM_ATTRIB_OUTPUT_MASK_TEX1 = 1 << CELL_GCM_ATTRIB_OUTPUT_TEX1, + CELL_GCM_ATTRIB_OUTPUT_MASK_TEX2 = 1 << CELL_GCM_ATTRIB_OUTPUT_TEX2, + CELL_GCM_ATTRIB_OUTPUT_MASK_TEX3 = 1 << CELL_GCM_ATTRIB_OUTPUT_TEX3, + CELL_GCM_ATTRIB_OUTPUT_MASK_TEX4 = 1 << CELL_GCM_ATTRIB_OUTPUT_TEX4, + CELL_GCM_ATTRIB_OUTPUT_MASK_TEX5 = 1 << CELL_GCM_ATTRIB_OUTPUT_TEX5, + CELL_GCM_ATTRIB_OUTPUT_MASK_TEX6 = 1 << CELL_GCM_ATTRIB_OUTPUT_TEX6, + CELL_GCM_ATTRIB_OUTPUT_MASK_TEX7 = 1 << CELL_GCM_ATTRIB_OUTPUT_TEX7, CELL_GCM_POLYGON_MODE_POINT = 0x1B00, CELL_GCM_POLYGON_MODE_LINE = 0x1B01, diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index 8ee4141f78..56c4b4d9eb 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -92,12 +92,6 @@ void GLGSRender::begin() __glcheck glDepthRange((f32&)rsx::method_registers[NV4097_SET_CLIP_MIN], (f32&)rsx::method_registers[NV4097_SET_CLIP_MAX]); __glcheck enable(rsx::method_registers[NV4097_SET_DITHER_ENABLE], GL_DITHER); - if (!!rsx::method_registers[NV4097_SET_ALPHA_TEST_ENABLE]) - { - //TODO: NV4097_SET_ALPHA_REF must be converted to f32 - //glcheck(glAlphaFunc(rsx::method_registers[NV4097_SET_ALPHA_FUNC], rsx::method_registers[NV4097_SET_ALPHA_REF])); - } - if (__glcheck enable(rsx::method_registers[NV4097_SET_BLEND_ENABLE], GL_BLEND)) { u32 sfactor = rsx::method_registers[NV4097_SET_BLEND_FUNC_SFACTOR]; @@ -609,6 +603,15 @@ struct alignas(4) glsl_fragment_constants_buffer float fc[2048][4]; }; +//binding 3 +struct alignas(4) glsl_fragment_state_buffer +{ + float fog_param0; + float fog_param1; + uint alpha_test; + float alpha_ref; +}; + static void fill_matrix_buffer(glsl_matrix_buffer *buffer) { rsx::fill_viewport_matrix(buffer->viewport_matrix, true); @@ -657,6 +660,14 @@ static void fill_matrix_buffer(glsl_matrix_buffer *buffer) rsx::fill_scale_offset_matrix(buffer->normalize_matrix, true, offset_x, offset_y, offset_z, scale_x, scale_y, scale_z); } +static void fill_fragment_state_buffer(glsl_fragment_state_buffer *buffer) +{ + std::memcpy(&buffer->fog_param0, rsx::method_registers + NV4097_SET_FOG_PARAMS, sizeof(float) * 2); + + buffer->alpha_test = rsx::method_registers[NV4097_SET_ALPHA_TEST_ENABLE]; + buffer->alpha_ref = rsx::method_registers[NV4097_SET_ALPHA_REF] / 255.f; +} + bool GLGSRender::load_program() { if (0) @@ -678,6 +689,7 @@ bool GLGSRender::load_program() u32 max_buffer_sz = align(sizeof(glsl_matrix_buffer), m_uniform_buffer_offset_align) + align(sizeof(glsl_vertex_constants_buffer), m_uniform_buffer_offset_align) + + align(sizeof(glsl_fragment_state_buffer), m_uniform_buffer_offset_align) + align(fragment_constants_size, m_uniform_buffer_offset_align); m_uniform_ring_buffer.reserve_and_map(max_buffer_sz); @@ -685,6 +697,7 @@ bool GLGSRender::load_program() u32 scale_offset_offset; u32 vertex_constants_offset; u32 fragment_constants_offset; + u32 fragment_state_offset; { auto mapping = m_uniform_ring_buffer.alloc_from_reserve(sizeof(glsl_matrix_buffer), m_uniform_buffer_offset_align); @@ -698,6 +711,12 @@ bool GLGSRender::load_program() vertex_constants_offset = mapping.second; } + { + auto mapping = m_uniform_ring_buffer.alloc_from_reserve(sizeof(glsl_fragment_state_buffer), m_uniform_buffer_offset_align); + fill_fragment_state_buffer((glsl_fragment_state_buffer *)mapping.first); + fragment_state_offset = mapping.second; + } + if (fragment_constants_size) { auto mapping = m_uniform_ring_buffer.alloc_from_reserve(fragment_constants_size, m_uniform_buffer_offset_align); @@ -745,6 +764,8 @@ bool GLGSRender::load_program() m_uniform_ring_buffer.bind_range(2, fragment_constants_offset, fragment_constants_size); } + m_uniform_ring_buffer.bind_range(3, fragment_state_offset, sizeof(glsl_fragment_state_buffer)); + return true; } diff --git a/rpcs3/Emu/RSX/GL/rsx_gl_cache.cpp b/rpcs3/Emu/RSX/GL/rsx_gl_cache.cpp index 391ffcd808..bced7df7fc 100644 --- a/rpcs3/Emu/RSX/GL/rsx_gl_cache.cpp +++ b/rpcs3/Emu/RSX/GL/rsx_gl_cache.cpp @@ -173,6 +173,15 @@ rsx::complete_shader glsl_complete_shader(const rsx::decompiled_shader &shader, "\tmat4 normalize_matrix;\n" "};\n"; } + else if (shader.raw->type == rsx::program_type::fragment) + { + result.code += "layout(std140, binding = 3) uniform StateParameters\n{\n" + "\tfloat fog_param0;\n" + "\tfloat fog_param1;\n" + "\tuint alpha_test;\n" + "\tfloat alpha_ref;\n" + "};\n"; + } if (!shader.constants.empty()) { @@ -330,6 +339,43 @@ rsx::complete_shader glsl_complete_shader(const rsx::decompiled_shader &shader, } } + { + if (~state.output_attributes & CELL_GCM_ATTRIB_OUTPUT_MASK_FOG) + { + result.code += "vec4 fog = vec4(0.0);\n"; + } + + result.code += "vec4 fogc;\n"; + + std::string body; + switch ((rsx::fog_mode)state.fog_mode) + { + case rsx::fog_mode::linear: + body = "fog_param1 * fog.x + (fog_param0 - 1.0), fog_param1 * fog.x + (fog_param0 - 1.0)"; + break; + case rsx::fog_mode::exponential: + body = "11.084 * (fog_param1 * fog.x + fog_param0 - 1.5), exp(11.084 * (fog_param1 * fog.x + fog_param0 - 1.5))"; + break; + case rsx::fog_mode::exponential2: + body = "4.709 * (fog_param1 * fog.x + fog_param0 - 1.5), exp(-pow(4.709 * (fog_param1 * fog.x + fog_param0 - 1.5), 2.0))"; + break; + case rsx::fog_mode::linear_abs: + body = "fog_param1 * abs(fog.x) + (fog_param0 - 1.0), fog_param1 * abs(fog.x) + (fog_param0 - 1.0)"; + break; + case rsx::fog_mode::exponential_abs: + body = "11.084 * (fog_param1 * abs(fog.x) + fog_param0 - 1.5), exp(11.084 * (fog_param1 * abs(fog.x) + fog_param0 - 1.5))"; + break; + case rsx::fog_mode::exponential2_abs: + body = "4.709 * (fog_param1 * abs(fog.x) + fog_param0 - 1.5), exp(-pow(4.709 * (fog_param1 * abs(fog.x) + fog_param0 - 1.5), 2.0))"; + break; + + default: + body = "0.0, 0.0"; + } + + prepare += "\tfogc = clamp(vec4(" + body + ", 0.0, 0.0), 0.0, 1.0);\n"; + } + { u32 diffuse_color = state.output_attributes & (CELL_GCM_ATTRIB_OUTPUT_MASK_FRONTDIFFUSE | CELL_GCM_ATTRIB_OUTPUT_MASK_BACKDIFFUSE); u32 specular_color = state.output_attributes & (CELL_GCM_ATTRIB_OUTPUT_MASK_FRONTSPECULAR | CELL_GCM_ATTRIB_OUTPUT_MASK_BACKSPECULAR); @@ -417,6 +463,64 @@ rsx::complete_shader glsl_complete_shader(const rsx::decompiled_shader &shader, result.code += "in vec4 " + rsx::vertex_program::output_attrib_names[index] + ";\n"; } } + + { + auto make_comparsion_test = [](rsx::comparaison_function compare_func, const std::string &test, const std::string &a, const std::string &b) -> std::string + { + if (compare_func == rsx::comparaison_function::always) + { + return{}; + } + + if (compare_func == rsx::comparaison_function::never) + { + return "\tdiscard;\n"; + } + + std::string compare; + + switch (compare_func) + { + case rsx::comparaison_function::equal: + compare = "=="; + break; + + case rsx::comparaison_function::not_equal: + compare = "!="; + break; + + case rsx::comparaison_function::less_or_equal: + compare = "<="; + break; + + case rsx::comparaison_function::less: + compare = "<"; + break; + + case rsx::comparaison_function::greater: + compare = ">"; + break; + + case rsx::comparaison_function::greater_or_equal: + compare = ">="; + break; + } + + return "\tif (" + test + "!(" + a + " " + compare + " " + b + ")) discard;\n"; + }; + + for (u8 index = 0; index < 16; ++index) + { + if (state.textures_alpha_kill[index]) + { + std::string index_string = std::to_string(index); + std::string fetch_texture = "texture_fetch(" + index_string + ", tex" + index_string + " * ftexture" + index_string + "_cm).a"; + finalize += make_comparsion_test((rsx::comparaison_function)state.textures_zfunc[index], "", "0", fetch_texture); + } + } + + finalize += make_comparsion_test((rsx::comparaison_function)state.alpha_func, "alpha_test != 0 && ", "ocol.a", "alpha_ref"); + } break; case rsx::program_type::vertex: @@ -501,6 +605,12 @@ rsx::complete_shader glsl_complete_shader(const rsx::decompiled_shader &shader, } { + if (state.output_attributes & CELL_GCM_ATTRIB_OUTPUT_MASK_FOG) + { + result.code += "out vec4 fog;\n"; + finalize += "\tfog = o5.xxxx;\n"; + } + auto map_register = [&](int to, int from) { if (shader.output_attributes & (1 << from)) @@ -512,11 +622,11 @@ rsx::complete_shader glsl_complete_shader(const rsx::decompiled_shader &shader, { result.code += "out vec4 " + rsx::vertex_program::output_attrib_names[to] + ";\n"; - if ((1 << to) == CELL_GCM_ATTRIB_OUTPUT_MASK_BACKDIFFUSE && shader.output_attributes & (1 << 1)) + if (to == CELL_GCM_ATTRIB_OUTPUT_BACKDIFFUSE && shader.output_attributes & (1 << 1)) { finalize += "\t" + rsx::vertex_program::output_attrib_names[to] + " = o1;\n"; } - else if ((1 << to) == CELL_GCM_ATTRIB_OUTPUT_MASK_BACKSPECULAR && shader.output_attributes & (1 << 2)) + else if (to == CELL_GCM_ATTRIB_OUTPUT_BACKSPECULAR && shader.output_attributes & (1 << 2)) { finalize += "\t" + rsx::vertex_program::output_attrib_names[to] + " = o2;\n"; } @@ -527,19 +637,19 @@ rsx::complete_shader glsl_complete_shader(const rsx::decompiled_shader &shader, } }; - map_register(0, 1); - map_register(1, 2); - map_register(2, 3); - map_register(3, 4); - map_register(14, 7); - map_register(15, 8); - map_register(16, 9); - map_register(17, 10); - map_register(18, 11); - map_register(19, 12); - map_register(20, 13); - map_register(21, 14); - map_register(12, 15); + map_register(CELL_GCM_ATTRIB_OUTPUT_FRONTDIFFUSE, 1); + map_register(CELL_GCM_ATTRIB_OUTPUT_FRONTSPECULAR, 2); + map_register(CELL_GCM_ATTRIB_OUTPUT_BACKDIFFUSE, 3); + map_register(CELL_GCM_ATTRIB_OUTPUT_BACKSPECULAR, 4); + map_register(CELL_GCM_ATTRIB_OUTPUT_TEX0, 7); + map_register(CELL_GCM_ATTRIB_OUTPUT_TEX1, 8); + map_register(CELL_GCM_ATTRIB_OUTPUT_TEX2, 9); + map_register(CELL_GCM_ATTRIB_OUTPUT_TEX3, 10); + map_register(CELL_GCM_ATTRIB_OUTPUT_TEX4, 11); + map_register(CELL_GCM_ATTRIB_OUTPUT_TEX5, 12); + map_register(CELL_GCM_ATTRIB_OUTPUT_TEX6, 13); + map_register(CELL_GCM_ATTRIB_OUTPUT_TEX7, 14); + map_register(CELL_GCM_ATTRIB_OUTPUT_TEX8, 15); if (shader.output_attributes & (1 << 5)) { @@ -587,11 +697,6 @@ rsx::complete_shader glsl_complete_shader(const rsx::decompiled_shader &shader, finalize += "\tgl_ClipDistance[5] = uc_m5 * o6.w;\n"; } } - - if (state.output_attributes & CELL_GCM_ATTRIB_OUTPUT_MASK_FOG) - { - //TODO - } } break; @@ -602,7 +707,7 @@ rsx::complete_shader glsl_complete_shader(const rsx::decompiled_shader &shader, result.code += "\n"; result.code += shader.code; - result.code += "void main()\n{\n" + prepare + "\t" + shader.entry_function + "();\n" + finalize + "}"; + result.code += "void main()\n{\n" + prepare + "\n\t" + shader.entry_function + "();\n\n" + finalize + "}"; return result; } diff --git a/rpcs3/Emu/RSX/GL/rsx_gl_texture.cpp b/rpcs3/Emu/RSX/GL/rsx_gl_texture.cpp index 141dca7bf7..ad2814693e 100644 --- a/rpcs3/Emu/RSX/GL/rsx_gl_texture.cpp +++ b/rpcs3/Emu/RSX/GL/rsx_gl_texture.cpp @@ -516,8 +516,6 @@ namespace rsx __glcheck glTexParameteri(m_target, GL_TEXTURE_WRAP_T, gl_wrap(tex.wrap_t())); __glcheck glTexParameteri(m_target, GL_TEXTURE_WRAP_R, gl_wrap(tex.wrap_r())); - __glcheck glTexParameteri(m_target, GL_TEXTURE_COMPARE_FUNC, gl_tex_zfunc[tex.zfunc()]); - __glcheck glTexParameterf(m_target, GL_TEXTURE_LOD_BIAS, tex.bias()); __glcheck glTexParameteri(m_target, GL_TEXTURE_MIN_LOD, (tex.min_lod() >> 8)); __glcheck glTexParameteri(m_target, GL_TEXTURE_MAX_LOD, (tex.max_lod() >> 8)); diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 067c96c08c..bb080f3818 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -767,6 +767,8 @@ namespace rsx result.state.output_attributes = rsx::method_registers[NV4097_SET_VERTEX_ATTRIB_OUTPUT_MASK]; result.state.ctrl = rsx::method_registers[NV4097_SET_SHADER_CONTROL]; result.state.divider_op = rsx::method_registers[NV4097_SET_FREQUENCY_DIVIDER_OPERATION]; + result.state.alpha_func = rsx::method_registers[NV4097_SET_ALPHA_FUNC]; + result.state.fog_mode = (u32)rsx::to_fog_mode(rsx::method_registers[NV4097_SET_FOG_MODE]); result.state.is_int = 0; for (u8 index = 0; index < rsx::limits::vertex_count; ++index) @@ -798,10 +800,15 @@ namespace rsx { if (!textures[index].enabled()) { + result.state.textures_alpha_kill[index] = 0; + result.state.textures_zfunc[index] = 0; result.state.textures[index] = rsx::texture_target::none; continue; } + result.state.textures_alpha_kill[index] = textures[index].alpha_kill_enabled() ? 1 : 0; + result.state.textures_zfunc[index] = textures[index].zfunc(); + switch (textures[index].get_extended_texture_dimension()) { case rsx::texture_dimension_extended::texture_dimension_1d: result.state.textures[index] = rsx::texture_target::_1; break; diff --git a/rsx_program_decompiler b/rsx_program_decompiler index a9e8d5ac4b..6db9567440 160000 --- a/rsx_program_decompiler +++ b/rsx_program_decompiler @@ -1 +1 @@ -Subproject commit a9e8d5ac4b718e247759f97615dde8759b1f0419 +Subproject commit 6db95674404f407fc50b3c96695e6098d25146d3