diff --git a/rpcs3/Emu/RSX/Common/ProgramStateCache.cpp b/rpcs3/Emu/RSX/Common/ProgramStateCache.cpp index 02d510b361..4179abecf6 100644 --- a/rpcs3/Emu/RSX/Common/ProgramStateCache.cpp +++ b/rpcs3/Emu/RSX/Common/ProgramStateCache.cpp @@ -104,7 +104,9 @@ size_t fragment_program_hash::operator()(const RSXFragmentProgram& program) cons bool fragment_program_compare::operator()(const RSXFragmentProgram& binary1, const RSXFragmentProgram& binary2) const { 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.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) return false; const qword *instBuffer1 = (const qword*)binary1.addr; const qword *instBuffer2 = (const qword*)binary2.addr; diff --git a/rpcs3/Emu/RSX/D3D12/D3D12FragmentProgramDecompiler.cpp b/rpcs3/Emu/RSX/D3D12/D3D12FragmentProgramDecompiler.cpp index bfb47c14bf..9884fffe74 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12FragmentProgramDecompiler.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12FragmentProgramDecompiler.cpp @@ -150,12 +150,27 @@ void D3D12FragmentDecompiler::insertMainStart(std::stringstream & OS) "r0", "r1", "r2", "r3", "r4", "h0", "h2", "h4", "h6", "h8" }; - OS << "void ps_impl(PixelInput In, inout float4 r0, inout float4 h0, inout float4 r1, inout float4 h2, inout float4 r2, inout float4 h4, inout float4 r3, inout float4 h6, inout float4 r4, inout float4 h8)" << std::endl; + OS << "void ps_impl(bool is_front_face, PixelInput In, inout float4 r0, inout float4 h0, inout float4 r1, inout float4 h2, inout float4 r2, inout float4 h4, inout float4 r3, inout float4 h6, inout float4 r4, inout float4 h8)" << std::endl; OS << "{" << std::endl; for (const ParamType &PT : m_parr.params[PF_PARAM_IN]) { 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; + } + } OS << " " << PT.type << " " << PI.name << " = In." << PI.name << ";" << std::endl; + } } // A bit unclean, but works. OS << " " << "float4 gl_Position = In.Position;" << std::endl; @@ -194,7 +209,7 @@ void D3D12FragmentDecompiler::insertMainEnd(std::stringstream & OS) { OS << "}" << std::endl; OS << std::endl; - OS << "PixelOutput main(PixelInput In)" << std::endl; + OS << "PixelOutput main(PixelInput In, bool is_front_face : SV_IsFrontFace)" << std::endl; OS << "{" << std::endl; OS << " float4 r0 = float4(0., 0., 0., 0.);" << std::endl; OS << " float4 r1 = float4(0., 0., 0., 0.);" << std::endl; @@ -206,7 +221,7 @@ void D3D12FragmentDecompiler::insertMainEnd(std::stringstream & OS) OS << " float4 h4 = float4(0., 0., 0., 0.);" << std::endl; OS << " float4 h6 = float4(0., 0., 0., 0.);" << std::endl; OS << " float4 h8 = float4(0., 0., 0., 0.);" << std::endl; - OS << " ps_impl(In, r0, h0, r1, h2, r2, h4, r3, h6, r4, h8);" << std::endl; + OS << " ps_impl(is_front_face, In, r0, h0, r1, h2, r2, h4, r3, h6, r4, h8);" << std::endl; const std::pair table[] = { diff --git a/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.cpp b/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.cpp index b8950bd8b5..1884a2a59a 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12PipelineState.cpp @@ -195,7 +195,7 @@ void D3D12GSRender::load_program() D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF, }; prop.Rasterization = CD3D12_RASTERIZER_DESC; - if (rsx::method_registers[NV4097_SET_CULL_FACE_ENABLE]) + if (!!rsx::method_registers[NV4097_SET_CULL_FACE_ENABLE]) { switch (rsx::method_registers[NV4097_SET_CULL_FACE]) { diff --git a/rpcs3/Emu/RSX/RSXFragmentProgram.h b/rpcs3/Emu/RSX/RSXFragmentProgram.h index bb1b7d08f8..68ffa167e3 100644 --- a/rpcs3/Emu/RSX/RSXFragmentProgram.h +++ b/rpcs3/Emu/RSX/RSXFragmentProgram.h @@ -220,6 +220,9 @@ struct RSXFragmentProgram u32 offset; u32 ctrl; u16 unnormalized_coords; + bool front_back_color_enabled : 1; + bool back_color_diffuse_output : 1; + bool back_color_specular_output : 1; u32 texture_dimensions; rsx::window_origin origin_mode; rsx::window_pixel_center pixel_center_mode; diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index b34e80173c..b8ff877180 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -667,6 +667,9 @@ namespace rsx result.addr = vm::base(rsx::get_address(result.offset, (shader_program & 0x3) - 1)); result.ctrl = rsx::method_registers[NV4097_SET_SHADER_CONTROL]; result.unnormalized_coords = 0; + 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); 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); @@ -762,6 +765,7 @@ namespace rsx method_registers[NV4097_SET_ZSTENCIL_CLEAR_VALUE] = 0xffffffff; 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; // Reset vertex attrib array for (int i = 0; i < limits::vertex_count; i++)