From 837e06e85ba71432d15bcab1efa477a0d0874f7b Mon Sep 17 00:00:00 2001 From: Vincent Lejeune Date: Sat, 6 Feb 2016 19:54:12 +0100 Subject: [PATCH] rsx/common/d3d12: Support non default alpha function Fix After burner climax cloud effects. --- rpcs3/Emu/RSX/Common/ProgramStateCache.cpp | 2 +- rpcs3/Emu/RSX/D3D12/D3D12Buffer.cpp | 3 ++- .../D3D12/D3D12FragmentProgramDecompiler.cpp | 25 ++++++++++++++++++- rpcs3/Emu/RSX/GCM.cpp | 16 ++++++++++++ rpcs3/Emu/RSX/GCM.h | 14 +++++++++++ rpcs3/Emu/RSX/RSXFragmentProgram.h | 1 + rpcs3/Emu/RSX/RSXThread.cpp | 2 ++ 7 files changed, 60 insertions(+), 3 deletions(-) diff --git a/rpcs3/Emu/RSX/Common/ProgramStateCache.cpp b/rpcs3/Emu/RSX/Common/ProgramStateCache.cpp index 4179abecf6..b9704b2802 100644 --- a/rpcs3/Emu/RSX/Common/ProgramStateCache.cpp +++ b/rpcs3/Emu/RSX/Common/ProgramStateCache.cpp @@ -106,7 +106,7 @@ bool fragment_program_compare::operator()(const RSXFragmentProgram& binary1, con if (binary1.texture_dimensions != binary2.texture_dimensions || binary1.unnormalized_coords != binary2.unnormalized_coords || binary1.height != binary2.height || binary1.origin_mode != binary2.origin_mode || binary1.pixel_center_mode != binary2.pixel_center_mode || 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.front_back_color_enabled != binary2.front_back_color_enabled || binary1.alpha_func != binary2.alpha_func) return false; const qword *instBuffer1 = (const qword*)binary1.addr; const qword *instBuffer2 = (const qword*)binary2.addr; diff --git a/rpcs3/Emu/RSX/D3D12/D3D12Buffer.cpp b/rpcs3/Emu/RSX/D3D12/D3D12Buffer.cpp index 4be3fa5fbd..6d9eabb8f8 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12Buffer.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12Buffer.cpp @@ -209,7 +209,8 @@ void D3D12GSRender::upload_and_bind_scale_offset_matrix(size_t descriptorIndex) void *mapped_buffer = m_buffer_data.map(CD3DX12_RANGE(heap_offset, heap_offset + 256)); fill_scale_offset_data(mapped_buffer); int is_alpha_tested = !!(rsx::method_registers[NV4097_SET_ALPHA_TEST_ENABLE]); - float alpha_ref = (float&)rsx::method_registers[NV4097_SET_ALPHA_REF]; + u8 alpha_ref_raw = (u8)(rsx::method_registers[NV4097_SET_ALPHA_REF] & 0xFF); + float alpha_ref = alpha_ref_raw / 255.f; memcpy((char*)mapped_buffer + 16 * sizeof(float), &is_alpha_tested, sizeof(int)); memcpy((char*)mapped_buffer + 17 * sizeof(float), &alpha_ref, sizeof(float)); m_buffer_data.unmap(CD3DX12_RANGE(heap_offset, heap_offset + 256)); diff --git a/rpcs3/Emu/RSX/D3D12/D3D12FragmentProgramDecompiler.cpp b/rpcs3/Emu/RSX/D3D12/D3D12FragmentProgramDecompiler.cpp index 55e9de688f..fcada5457b 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12FragmentProgramDecompiler.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12FragmentProgramDecompiler.cpp @@ -253,7 +253,30 @@ void D3D12FragmentDecompiler::insertMainEnd(std::stringstream & OS) } // Shaders don't always output colors (for instance if they write to depth only) if (!first_output_name.empty()) - OS << " if (isAlphaTested && Out." << first_output_name << ".a <= alphaRef) discard;\n"; + { + switch (m_prog.alpha_func) + { + case rsx::comparaison_function::equal: + OS << " if (isAlphaTested && Out." << first_output_name << ".a != alphaRef) discard;\n"; + break; + case rsx::comparaison_function::not_equal: + OS << " if (isAlphaTested && Out." << first_output_name << ".a == alphaRef) discard;\n"; + break; + case rsx::comparaison_function::less_or_equal: + OS << " if (isAlphaTested && Out." << first_output_name << ".a > alphaRef) discard;\n"; + break; + case rsx::comparaison_function::less: + OS << " if (isAlphaTested && Out." << first_output_name << ".a >= alphaRef) discard;\n"; + break; + case rsx::comparaison_function::greater: + OS << " if (isAlphaTested && Out." << first_output_name << ".a <= alphaRef) discard;\n"; + break; + case rsx::comparaison_function::greater_or_equal: + OS << " if (isAlphaTested && Out." << first_output_name << ".a < alphaRef) discard;\n"; + break; + } + + } OS << " return Out;" << std::endl; OS << "}" << std::endl; } diff --git a/rpcs3/Emu/RSX/GCM.cpp b/rpcs3/Emu/RSX/GCM.cpp index e463a3208f..8e724eea5b 100644 --- a/rpcs3/Emu/RSX/GCM.cpp +++ b/rpcs3/Emu/RSX/GCM.cpp @@ -790,6 +790,22 @@ rsx::window_pixel_center rsx::to_window_pixel_center(u8 in) throw EXCEPTION("Unknow window pixel center %x", in); } +rsx::comparaison_function rsx::to_comparaison_function(u16 in) +{ + switch (in) + { + case CELL_GCM_NEVER: return rsx::comparaison_function::never; + case CELL_GCM_LESS: return rsx::comparaison_function::less; + case CELL_GCM_EQUAL: return rsx::comparaison_function::equal; + case CELL_GCM_LEQUAL: return rsx::comparaison_function::less_or_equal; + case CELL_GCM_GREATER: return rsx::comparaison_function::greater; + case CELL_GCM_NOTEQUAL: return rsx::comparaison_function::not_equal; + case CELL_GCM_GEQUAL: return rsx::comparaison_function::greater_or_equal; + case CELL_GCM_ALWAYS: return rsx::comparaison_function::always; + } + throw EXCEPTION("Wrong comparaison function %x", in); +} + enum { diff --git a/rpcs3/Emu/RSX/GCM.h b/rpcs3/Emu/RSX/GCM.h index f9a2b0f80e..5d894e5ffa 100644 --- a/rpcs3/Emu/RSX/GCM.h +++ b/rpcs3/Emu/RSX/GCM.h @@ -127,6 +127,20 @@ namespace rsx }; window_pixel_center to_window_pixel_center(u8 in); + + enum class comparaison_function : u8 + { + never, + less, + equal, + less_or_equal, + greater, + not_equal, + greater_or_equal, + always + }; + + comparaison_function to_comparaison_function(u16 in); } enum diff --git a/rpcs3/Emu/RSX/RSXFragmentProgram.h b/rpcs3/Emu/RSX/RSXFragmentProgram.h index 68ffa167e3..5fe8429533 100644 --- a/rpcs3/Emu/RSX/RSXFragmentProgram.h +++ b/rpcs3/Emu/RSX/RSXFragmentProgram.h @@ -220,6 +220,7 @@ struct RSXFragmentProgram u32 offset; u32 ctrl; u16 unnormalized_coords; + rsx::comparaison_function alpha_func; bool front_back_color_enabled : 1; bool back_color_diffuse_output : 1; bool back_color_specular_output : 1; diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index b8ff877180..8b98ea23bb 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -670,6 +670,7 @@ namespace rsx result.front_back_color_enabled = !rsx::method_registers[NV4097_SET_TWO_SIDE_LIGHT_EN]; result.back_color_diffuse_output = !!(rsx::method_registers[NV4097_SET_VERTEX_ATTRIB_OUTPUT_MASK] & CELL_GCM_ATTRIB_OUTPUT_MASK_BACKDIFFUSE); result.back_color_specular_output = !!(rsx::method_registers[NV4097_SET_VERTEX_ATTRIB_OUTPUT_MASK] & CELL_GCM_ATTRIB_OUTPUT_MASK_BACKSPECULAR); + result.alpha_func = to_comparaison_function(rsx::method_registers[NV4097_SET_ALPHA_FUNC]); u32 shader_window = rsx::method_registers[NV4097_SET_SHADER_WINDOW]; result.origin_mode = rsx::to_window_origin((shader_window >> 12) & 0xF); result.pixel_center_mode = rsx::to_window_pixel_center((shader_window >> 16) & 0xF); @@ -766,6 +767,7 @@ namespace rsx method_registers[NV4097_SET_CONTEXT_DMA_REPORT] = CELL_GCM_CONTEXT_DMA_TO_MEMORY_GET_REPORT; rsx::method_registers[NV4097_SET_TWO_SIDE_LIGHT_EN] = true; + rsx::method_registers[NV4097_SET_ALPHA_FUNC] = CELL_GCM_ALWAYS; // Reset vertex attrib array for (int i = 0; i < limits::vertex_count; i++)