From de5a4fe083807f9dcccc6a4bb45fe10d21fe2aea Mon Sep 17 00:00:00 2001 From: kd-11 Date: Sat, 18 Nov 2017 16:10:54 +0300 Subject: [PATCH] rsx: Reimplement depth <-> RGBA reinterpretation code - Implements proper channel order for fp24-ARGB8 conversion - Takes swizzle remap into account when reconstructing source bytes --- rpcs3/Emu/RSX/Common/GLSLCommon.h | 35 +++++++++++++++---- rpcs3/Emu/RSX/D3D12/D3D12CommonDecompiler.cpp | 32 +++++++++++++---- rpcs3/Emu/RSX/GL/GLOverlays.h | 4 +-- rpcs3/Emu/RSX/RSXFragmentProgram.h | 2 +- rpcs3/Emu/RSX/RSXThread.cpp | 13 ++++++- rpcs3/Emu/RSX/VK/VKOverlays.h | 4 +-- 6 files changed, 70 insertions(+), 20 deletions(-) diff --git a/rpcs3/Emu/RSX/Common/GLSLCommon.h b/rpcs3/Emu/RSX/Common/GLSLCommon.h index 604a4c2300..b4128f64d2 100644 --- a/rpcs3/Emu/RSX/Common/GLSLCommon.h +++ b/rpcs3/Emu/RSX/Common/GLSLCommon.h @@ -320,20 +320,43 @@ namespace glsl program_common::insert_compare_op(OS); - //NOTE: After testing with GOW, the w component is either the original depth or wraps around to the x component - //Since component.r == depth_value with some precision loss, just use the precise depth value for now (further testing needed) + //NOTE: Memory layout is fetched as byteswapped BGRA [GBAR] (GOW collection, DS2, DeS) + //The A component (Z) is useless (should contain stencil8 or just 1) OS << "vec4 decodeLinearDepth(float depth_value)\n"; OS << "{\n"; OS << " uint value = uint(depth_value * 16777215);\n"; OS << " uint b = (value & 0xff);\n"; OS << " uint g = (value >> 8) & 0xff;\n"; OS << " uint r = (value >> 16) & 0xff;\n"; - OS << " return vec4(float(r)/255., float(g)/255., float(b)/255., depth_value);\n"; + OS << " return vec4(float(g)/255., float(b)/255., 1., float(r)/255.);\n"; OS << "}\n\n"; - OS << "vec4 texture2DReconstruct(sampler2D tex, vec2 coord)\n"; + OS << "float read_value(vec4 src, uint remap_index)\n"; OS << "{\n"; - OS << " return decodeLinearDepth(texture(tex, coord.xy).r);\n"; + OS << " switch (remap_index)\n"; + OS << " {\n"; + OS << " case 0: return src.a;\n"; + OS << " case 1: return src.r;\n"; + OS << " case 2: return src.g;\n"; + OS << " case 3: return src.b;\n"; + OS << " }\n"; + OS << "}\n\n"; + + OS << "vec4 texture2DReconstruct(sampler2D tex, vec2 coord, float remap)\n"; + OS << "{\n"; + OS << " vec4 result = decodeLinearDepth(texture(tex, coord.xy).r);\n"; + OS << " uint remap_vector = floatBitsToUint(remap) & 0xFF;\n"; + OS << " if (remap_vector == 0xE4) return result;\n\n"; + OS << " vec4 tmp;\n"; + OS << " uint remap_a = remap_vector & 0x3;\n"; + OS << " uint remap_r = (remap_vector >> 2) & 0x3;\n"; + OS << " uint remap_g = (remap_vector >> 4) & 0x3;\n"; + OS << " uint remap_b = (remap_vector >> 6) & 0x3;\n"; + OS << " tmp.a = read_value(result, remap_a);\n"; + OS << " tmp.r = read_value(result, remap_r);\n"; + OS << " tmp.g = read_value(result, remap_g);\n"; + OS << " tmp.b = read_value(result, remap_b);\n"; + OS << " return tmp;\n"; OS << "}\n\n"; OS << "vec4 get_wpos()\n"; @@ -415,7 +438,7 @@ namespace glsl case FUNCTION::FUNCTION_VERTEX_TEXTURE_FETCH2D: return "textureLod($t, $0.xy, 0)"; case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_DEPTH_RGBA: - return "texture2DReconstruct($t, $0.xy * texture_parameters[$_i].xy)"; + return "texture2DReconstruct($t, $0.xy * texture_parameters[$_i].xy, texture_parameters[$_i].z)"; } } } \ No newline at end of file diff --git a/rpcs3/Emu/RSX/D3D12/D3D12CommonDecompiler.cpp b/rpcs3/Emu/RSX/D3D12/D3D12CommonDecompiler.cpp index 4743039b05..c59fdac051 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12CommonDecompiler.cpp +++ b/rpcs3/Emu/RSX/D3D12/D3D12CommonDecompiler.cpp @@ -83,7 +83,7 @@ std::string getFunctionImp(FUNCTION f) case FUNCTION::FUNCTION_DFDY: return "ddy($0)"; case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_DEPTH_RGBA: - return "texture2DReconstruct($t.Sample($tsampler, $0.xy * $t_scale))"; + return "texture2DReconstruct($t.Sample($tsampler, $0.xy * $t_scale, texture_parameters[$_i].z))"; } } @@ -192,16 +192,36 @@ void insert_d3d12_legacy_function(std::ostream& OS, bool is_fragment_program) OS << " return unpackSnorm2x16(val) * 6.1E+5;\n"; OS << "}\n\n"; - //NOTE: After testing with GOW, the w component is either the original depth or wraps around to the x component - //Since component.r == depth_value with some precision loss, just use the precise depth value for now (further testing needed) - //TODO: This function does not work as intended on DX12 - OS << "float4 texture2DReconstruct(float depth_value)\n"; + OS << "float read_value(float4 src, uint remap_index)\n"; + OS << "{\n"; + OS << " switch (remap_index)\n"; + OS << " {\n"; + OS << " case 0: return src.a;\n"; + OS << " case 1: return src.r;\n"; + OS << " case 2: return src.g;\n"; + OS << " case 3: return src.b;\n"; + OS << " }\n"; + OS << "}\n\n"; + + OS << "float4 texture2DReconstruct(float depth_value, float remap)\n"; OS << "{\n"; OS << " uint value = round(depth_value * 16777215);\n"; OS << " uint b = (value & 0xff);\n"; OS << " uint g = (value >> 8) & 0xff;\n"; OS << " uint r = (value >> 16) & 0xff;\n"; - OS << " return float4(r/255., g/255., b/255., depth_value);\n"; + OS << " float4 result = float4(g/255., b/255., 1., r/255.);\n\n"; + OS << " uint remap_vector = asuint(remap) & 0xFF;\n"; + OS << " if (remap_vector == 0xE4) return result;\n\n"; + OS << " float4 tmp;\n"; + OS << " uint remap_a = remap_vector & 0x3;\n"; + OS << " uint remap_r = (remap_vector >> 2) & 0x3;\n"; + OS << " uint remap_g = (remap_vector >> 4) & 0x3;\n"; + OS << " uint remap_b = (remap_vector >> 6) & 0x3;\n"; + OS << " tmp.a = read_value(result, remap_a);\n"; + OS << " tmp.r = read_value(result, remap_r);\n"; + OS << " tmp.g = read_value(result, remap_g);\n"; + OS << " tmp.b = read_value(result, remap_b);\n"; + OS << " return tmp;\n"; OS << "}\n\n"; } #endif diff --git a/rpcs3/Emu/RSX/GL/GLOverlays.h b/rpcs3/Emu/RSX/GL/GLOverlays.h index a50a0f6f7f..68a83c8d86 100644 --- a/rpcs3/Emu/RSX/GL/GLOverlays.h +++ b/rpcs3/Emu/RSX/GL/GLOverlays.h @@ -185,9 +185,7 @@ namespace gl "void main()\n" "{\n" " vec4 rgba_in = texture(fs0, tc0);\n" - " uint raw_value = uint(rgba_in.b * 255.) | (uint(rgba_in.g * 255.) << 8) | (uint(rgba_in.r * 255.) << 16);\n" - " gl_FragDepth = float(raw_value) / 16777215.;\n" - " //gl_FragDepth = rgba_in.r * 0.99609 + rgba_in.g * 0.00389 + rgba_in.b * 0.00002;\n" + " gl_FragDepth = rgba_in.w * 0.99609 + rgba_in.x * 0.00389 + rgba_in.y * 0.00002;\n" "}\n" }; } diff --git a/rpcs3/Emu/RSX/RSXFragmentProgram.h b/rpcs3/Emu/RSX/RSXFragmentProgram.h index 29941c6744..a8d1a00943 100644 --- a/rpcs3/Emu/RSX/RSXFragmentProgram.h +++ b/rpcs3/Emu/RSX/RSXFragmentProgram.h @@ -230,7 +230,7 @@ struct RSXFragmentProgram bool front_color_specular_output : 1; u32 texture_dimensions; - std::array texture_scale[16]; + std::array texture_scale[16]; u8 textures_alpha_kill[16]; u8 textures_zfunc[16]; diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index de88e7dbe2..922e99203b 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -854,7 +854,10 @@ namespace rsx size_t offset = 8; for (int index = 0; index < 16; ++index) { - stream_vector(&dst[offset], (u32&)fragment_program.texture_scale[index][0], (u32&)fragment_program.texture_scale[index][1], 0U, 0U); + stream_vector(&dst[offset], + (u32&)fragment_program.texture_scale[index][0], (u32&)fragment_program.texture_scale[index][1], + (u32&)fragment_program.texture_scale[index][2], (u32&)fragment_program.texture_scale[index][3]); + offset += 4; } } @@ -1396,8 +1399,12 @@ namespace rsx case CELL_GCM_TEXTURE_D8R8G8B8: case CELL_GCM_TEXTURE_A4R4G4B4: case CELL_GCM_TEXTURE_R5G6B5: + { + u32 remap = tex.remap(); result.redirected_textures |= (1 << i); + result.texture_scale[i][2] = (f32&)remap; break; + } case CELL_GCM_TEXTURE_DEPTH16: case CELL_GCM_TEXTURE_DEPTH24_D8: case CELL_GCM_TEXTURE_DEPTH16_FLOAT: @@ -1520,8 +1527,12 @@ namespace rsx case CELL_GCM_TEXTURE_D8R8G8B8: case CELL_GCM_TEXTURE_A4R4G4B4: case CELL_GCM_TEXTURE_R5G6B5: + { + u32 remap = tex.remap(); result.redirected_textures |= (1 << i); + result.texture_scale[i][2] = (f32&)remap; break; + } case CELL_GCM_TEXTURE_DEPTH16: case CELL_GCM_TEXTURE_DEPTH24_D8: case CELL_GCM_TEXTURE_DEPTH16_FLOAT: diff --git a/rpcs3/Emu/RSX/VK/VKOverlays.h b/rpcs3/Emu/RSX/VK/VKOverlays.h index 537f9f2119..bd321b8ae8 100644 --- a/rpcs3/Emu/RSX/VK/VKOverlays.h +++ b/rpcs3/Emu/RSX/VK/VKOverlays.h @@ -334,9 +334,7 @@ namespace vk "void main()\n" "{\n" " vec4 rgba_in = texture(fs0, tc0);\n" - " uint raw_value = uint(rgba_in.b * 255.) | (uint(rgba_in.g * 255.) << 8) | (uint(rgba_in.r * 255.) << 16);\n" - " gl_FragDepth = float(raw_value) / 16777215.;\n" - " //gl_FragDepth = rgba_in.r * 0.99609 + rgba_in.g * 0.00389 + rgba_in.b * 0.00002;\n" + " gl_FragDepth = rgba_in.w * 0.99609 + rgba_in.x * 0.00389 + rgba_in.y * 0.00002;\n" "}\n" };