diff --git a/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp b/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp index 4590e7715d..94340a7306 100644 --- a/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp +++ b/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp @@ -35,6 +35,8 @@ void GLFragmentDecompilerThread::insertHeader(std::stringstream & OS) OS << " mat4 scaleOffsetMat;\n"; OS << " float fog_param0;\n"; OS << " float fog_param1;\n"; + OS << " uint alpha_test;\n"; + OS << " float alpha_ref;\n"; OS << "};\n"; } @@ -205,10 +207,14 @@ void GLFragmentDecompilerThread::insertMainEnd(std::stringstream & OS) { "ocol3", m_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS ? "r4" : "h8" }, }; + std::string first_output_name; for (int i = 0; i < sizeof(table) / sizeof(*table); ++i) { if (m_parr.HasParam(PF_PARAM_NONE, "vec4", table[i].second)) + { OS << " " << table[i].first << " = " << table[i].second << ";" << std::endl; + if (first_output_name.empty()) first_output_name = table[i].first; + } } if (m_ctrl & CELL_GCM_SHADER_CONTROL_DEPTH_EXPORT) @@ -223,6 +229,30 @@ void GLFragmentDecompilerThread::insertMainEnd(std::stringstream & OS) } } + if (!first_output_name.empty()) + { + switch (m_prog.alpha_func) + { + case rsx::comparaison_function::equal: + OS << " if (bool(alpha_test) && " << first_output_name << ".a != alpha_ref) discard;\n"; + break; + case rsx::comparaison_function::not_equal: + OS << " if (bool(alpha_test) && " << first_output_name << ".a == alpha_ref) discard;\n"; + break; + case rsx::comparaison_function::less_or_equal: + OS << " if (bool(alpha_test) && " << first_output_name << ".a > alpha_ref) discard;\n"; + break; + case rsx::comparaison_function::less: + OS << " if (bool(alpha_test) && " << first_output_name << ".a >= alpha_ref) discard;\n"; + break; + case rsx::comparaison_function::greater: + OS << " if (bool(alpha_test) && " << first_output_name << ".a <= alpha_ref) discard;\n"; + break; + case rsx::comparaison_function::greater_or_equal: + OS << " if (bool(alpha_test) && " << first_output_name << ".a < alpha_ref) discard;\n"; + break; + } + } OS << "}" << std::endl; } diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index 72dea64d18..3fd6cc6336 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -377,7 +377,7 @@ void GLGSRender::on_init_thread() m_vao.create(); m_vbo.create(); m_ebo.create(); - m_scale_offset_buffer.create(18 * sizeof(float)); + m_scale_offset_buffer.create(32 * sizeof(float)); m_vertex_constants_buffer.create(512 * 4 * sizeof(float)); m_fragment_constants_buffer.create(); @@ -585,11 +585,17 @@ bool GLGSRender::load_program() if (fragment_constants_sz > max_buffer_sz) max_buffer_sz = fragment_constants_sz; + u32 is_alpha_tested = !!(rsx::method_registers[NV4097_SET_ALPHA_TEST_ENABLE]); + u8 alpha_ref_raw = (u8)(rsx::method_registers[NV4097_SET_ALPHA_REF] & 0xFF); + float alpha_ref = alpha_ref_raw / 255.f; + std::vector client_side_buf(max_buffer_sz); fill_scale_offset_data(client_side_buf.data(), false); memcpy(client_side_buf.data() + 16 * sizeof(float), &rsx::method_registers[NV4097_SET_FOG_PARAMS], sizeof(float)); memcpy(client_side_buf.data() + 17 * sizeof(float), &rsx::method_registers[NV4097_SET_FOG_PARAMS + 1], sizeof(float)); + memcpy(client_side_buf.data() + 18 * sizeof(float), &is_alpha_tested, sizeof(u32)); + memcpy(client_side_buf.data() + 19 * sizeof(float), &alpha_ref, sizeof(float)); m_scale_offset_buffer.data(m_scale_offset_buffer.size(), nullptr); m_scale_offset_buffer.sub_data(0, m_scale_offset_buffer.size(), client_side_buf.data()); diff --git a/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp b/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp index ccf1c35880..f24f3e5771 100644 --- a/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp +++ b/rpcs3/Emu/RSX/GL/GLVertexProgram.cpp @@ -35,6 +35,8 @@ void GLVertexDecompilerThread::insertHeader(std::stringstream &OS) OS << " mat4 scaleOffsetMat;" << std::endl; OS << " float fog_param0;\n"; OS << " float fog_param1;\n"; + OS << " uint alpha_test;\n"; + OS << " float alpha_ref;\n"; OS << "};" << std::endl; } diff --git a/rpcs3/Emu/RSX/VK/VKFragmentProgram.cpp b/rpcs3/Emu/RSX/VK/VKFragmentProgram.cpp index b1ad178adc..a08d702857 100644 --- a/rpcs3/Emu/RSX/VK/VKFragmentProgram.cpp +++ b/rpcs3/Emu/RSX/VK/VKFragmentProgram.cpp @@ -37,6 +37,8 @@ void VKFragmentDecompilerThread::insertHeader(std::stringstream & OS) OS << " mat4 scaleOffsetMat;" << std::endl; OS << " float fog_param0;" << std::endl; OS << " float fog_param1;" << std::endl; + OS << " uint alpha_test;" << std::endl; + OS << " float alpha_ref;" << std::endl; OS << "};" << std::endl << std::endl; vk::glsl::program_input in; @@ -219,10 +221,14 @@ void VKFragmentDecompilerThread::insertMainEnd(std::stringstream & OS) { "ocol3", m_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS ? "r4" : "h8" }, }; + std::string first_output_name; for (int i = 0; i < sizeof(table) / sizeof(*table); ++i) { if (m_parr.HasParam(PF_PARAM_NONE, "vec4", table[i].second)) + { OS << " " << table[i].first << " = " << table[i].second << ";" << std::endl; + if (first_output_name.empty()) first_output_name = table[i].first; + } } if (m_ctrl & CELL_GCM_SHADER_CONTROL_DEPTH_EXPORT) @@ -237,6 +243,30 @@ void VKFragmentDecompilerThread::insertMainEnd(std::stringstream & OS) } } + if (!first_output_name.empty()) + { + switch (m_prog.alpha_func) + { + case rsx::comparaison_function::equal: + OS << " if (bool(alpha_test) && " << first_output_name << ".a != alpha_ref) discard;\n"; + break; + case rsx::comparaison_function::not_equal: + OS << " if (bool(alpha_test) && " << first_output_name << ".a == alpha_ref) discard;\n"; + break; + case rsx::comparaison_function::less_or_equal: + OS << " if (bool(alpha_test) && " << first_output_name << ".a > alpha_ref) discard;\n"; + break; + case rsx::comparaison_function::less: + OS << " if (bool(alpha_test) && " << first_output_name << ".a >= alpha_ref) discard;\n"; + break; + case rsx::comparaison_function::greater: + OS << " if (bool(alpha_test) && " << first_output_name << ".a <= alpha_ref) discard;\n"; + break; + case rsx::comparaison_function::greater_or_equal: + OS << " if (bool(alpha_test) && " << first_output_name << ".a < alpha_ref) discard;\n"; + break; + } + } OS << "}" << std::endl; } diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index d416c178ee..006df8757f 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -934,9 +934,14 @@ bool VKGSRender::load_program() stream_vector((char*)buf + 48, 0, 0, 0, (u32&)one); } - memset((char*)buf+64, 0, 8); + u32 is_alpha_tested = !!(rsx::method_registers[NV4097_SET_ALPHA_TEST_ENABLE]); + u8 alpha_ref_raw = (u8)(rsx::method_registers[NV4097_SET_ALPHA_REF] & 0xFF); + float alpha_ref = alpha_ref_raw / 255.f; + memcpy((char*)buf + 64, &rsx::method_registers[NV4097_SET_FOG_PARAMS], sizeof(float)); memcpy((char*)buf + 68, &rsx::method_registers[NV4097_SET_FOG_PARAMS + 1], sizeof(float)); + memcpy((char*)buf + 72, &is_alpha_tested, sizeof(u32)); + memcpy((char*)buf + 76, &alpha_ref, sizeof(float)); m_uniform_buffer_ring_info.unmap(); const size_t vertex_constants_offset = m_uniform_buffer_ring_info.alloc<256>(512 * 4 * sizeof(float)); diff --git a/rpcs3/Emu/RSX/VK/VKVertexProgram.cpp b/rpcs3/Emu/RSX/VK/VKVertexProgram.cpp index 32c84527e4..8f1523b7df 100644 --- a/rpcs3/Emu/RSX/VK/VKVertexProgram.cpp +++ b/rpcs3/Emu/RSX/VK/VKVertexProgram.cpp @@ -35,6 +35,8 @@ void VKVertexDecompilerThread::insertHeader(std::stringstream &OS) OS << " mat4 scaleOffsetMat;" << std::endl; OS << " float fog_param0;\n"; OS << " float fog_param1;\n"; + OS << " uint alpha_test;\n"; + OS << " float alpha_ref;\n"; OS << "};" << std::endl; vk::glsl::program_input in;