diff --git a/rpcs3/Emu/RSX/Common/ProgramStateCache.cpp b/rpcs3/Emu/RSX/Common/ProgramStateCache.cpp index 02d510b36..4179abecf 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 bfb47c14b..9884fffe7 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 b8950bd8b..1884a2a59 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 bb1b7d08f..68ffa167e 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 b34e80173..b8ff87718 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++)