From 6a9eef038273907e73297679583ba02ec51ba0ce Mon Sep 17 00:00:00 2001 From: kd-11 Date: Mon, 12 Jun 2017 12:42:30 +0300 Subject: [PATCH] rsx/gl/vk: Enable use of native PCF shadows --- rpcs3/Emu/RSX/Common/ProgramStateCache.cpp | 3 ++- rpcs3/Emu/RSX/GL/GLCommonDecompiler.cpp | 4 ++-- rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp | 3 +++ rpcs3/Emu/RSX/GL/GLTexture.cpp | 20 ++++++++++++++++++++ rpcs3/Emu/RSX/RSXFragmentProgram.h | 1 + rpcs3/Emu/RSX/RSXThread.cpp | 8 +++++--- rpcs3/Emu/RSX/VK/VKFragmentProgram.cpp | 2 ++ rpcs3/Emu/RSX/VK/VKGSRender.cpp | 19 ++++++++++++------- rpcs3/Emu/RSX/VK/VKHelpers.h | 7 ++++--- 9 files changed, 51 insertions(+), 16 deletions(-) diff --git a/rpcs3/Emu/RSX/Common/ProgramStateCache.cpp b/rpcs3/Emu/RSX/Common/ProgramStateCache.cpp index 9f4130ef64..2b3a0f8308 100644 --- a/rpcs3/Emu/RSX/Common/ProgramStateCache.cpp +++ b/rpcs3/Emu/RSX/Common/ProgramStateCache.cpp @@ -106,7 +106,8 @@ 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.alpha_func != binary2.alpha_func || binary1.redirected_textures != binary2.redirected_textures) + binary1.front_back_color_enabled != binary2.front_back_color_enabled || binary1.alpha_func != binary2.alpha_func || + binary1.shadow_textures != binary2.shadow_textures || binary1.redirected_textures != binary2.redirected_textures) return false; const qword *instBuffer1 = (const qword*)binary1.addr; const qword *instBuffer2 = (const qword*)binary2.addr; diff --git a/rpcs3/Emu/RSX/GL/GLCommonDecompiler.cpp b/rpcs3/Emu/RSX/GL/GLCommonDecompiler.cpp index da099c5414..ab8c4872e3 100644 --- a/rpcs3/Emu/RSX/GL/GLCommonDecompiler.cpp +++ b/rpcs3/Emu/RSX/GL/GLCommonDecompiler.cpp @@ -123,9 +123,9 @@ void insert_glsl_legacy_function(std::ostream& OS) //NOTE: We lose precision if we just store depth value into 8-bit textures i.e (depth, 0, 0) //NOTE2: 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) - OS << "vec4 texture2DReconstruct(sampler2D tex, vec2 coord)\n"; + OS << "highp vec4 texture2DReconstruct(sampler2D tex, vec2 coord)\n"; OS << "{\n"; - OS << " float depth_value = texture(tex, coord.xy).r;\n"; + OS << " highp float depth_value = texture(tex, coord.xy).r;\n"; OS << " uint value = uint(depth_value * 16777215);\n"; OS << " uint b = (value & 0xff);\n"; OS << " uint g = (value >> 8) & 0xff;\n"; diff --git a/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp b/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp index a187c2b4d3..2a7cfa2c7d 100644 --- a/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp +++ b/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp @@ -107,6 +107,9 @@ void GLFragmentDecompilerThread::insertConstants(std::stringstream & OS) std::string samplerType = PT.type; int index = atoi(&PI.name.data()[3]); + if ((m_prog.shadow_textures & (1 << index)) > 0) + samplerType = "sampler2DShadow"; + OS << "uniform " << samplerType << " " << PI.name << ";" << std::endl; } } diff --git a/rpcs3/Emu/RSX/GL/GLTexture.cpp b/rpcs3/Emu/RSX/GL/GLTexture.cpp index 968e1f0721..9306bf54b8 100644 --- a/rpcs3/Emu/RSX/GL/GLTexture.cpp +++ b/rpcs3/Emu/RSX/GL/GLTexture.cpp @@ -176,6 +176,26 @@ namespace gl glSamplerParameteri(samplerHandle, GL_TEXTURE_MAG_FILTER, tex_mag_filter(tex.mag_filter())); glSamplerParameteri(samplerHandle, GL_TEXTURE_MAX_ANISOTROPY_EXT, ::gl::max_aniso(tex.max_aniso())); + + const u32 texture_format = tex.format() & ~(CELL_GCM_TEXTURE_UN | CELL_GCM_TEXTURE_LN); + if (texture_format == CELL_GCM_TEXTURE_DEPTH16 || texture_format == CELL_GCM_TEXTURE_DEPTH24_D8) + { + //NOTE: The stored texture function is reversed wrt the textureProj compare function + GLenum compare_mode = (GLenum)tex.zfunc() | GL_NEVER; + + switch (compare_mode) + { + case GL_GREATER: compare_mode = GL_LESS; break; + case GL_GEQUAL: compare_mode = GL_LEQUAL; break; + case GL_LESS: compare_mode = GL_GREATER; break; + case GL_LEQUAL: compare_mode = GL_GEQUAL; break; + } + + glSamplerParameteri(samplerHandle, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); + glSamplerParameteri(samplerHandle, GL_TEXTURE_COMPARE_FUNC, compare_mode); + } + else + glSamplerParameteri(samplerHandle, GL_TEXTURE_COMPARE_MODE, GL_NONE); } } diff --git a/rpcs3/Emu/RSX/RSXFragmentProgram.h b/rpcs3/Emu/RSX/RSXFragmentProgram.h index da8b59fac6..8cc967bc46 100644 --- a/rpcs3/Emu/RSX/RSXFragmentProgram.h +++ b/rpcs3/Emu/RSX/RSXFragmentProgram.h @@ -222,6 +222,7 @@ struct RSXFragmentProgram u32 ctrl; u16 unnormalized_coords; u16 redirected_textures; + u16 shadow_textures; rsx::comparison_function alpha_func; bool front_back_color_enabled : 1; bool back_color_diffuse_output : 1; diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index ab07d57760..9e2e30d4e8 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -946,7 +946,7 @@ namespace rsx result.pixel_center_mode = rsx::method_registers.shader_window_pixel(); result.height = rsx::method_registers.shader_window_height(); result.redirected_textures = 0; - + result.shadow_textures = 0; std::array texture_dimensions; for (u32 i = 0; i < rsx::limits::fragment_textures_count; ++i) @@ -989,9 +989,11 @@ namespace rsx { u32 format = raw_format & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN); if (format == CELL_GCM_TEXTURE_A8R8G8B8 || format == CELL_GCM_TEXTURE_D8R8G8B8) - { result.redirected_textures |= (1 << i); - } + else if (format == CELL_GCM_TEXTURE_DEPTH16 || format == CELL_GCM_TEXTURE_DEPTH24_D8) + result.shadow_textures |= (1 << i); + else + LOG_ERROR(RSX, "Depth texture bound to pipeline with unexpected format 0x%X", format); } } } diff --git a/rpcs3/Emu/RSX/VK/VKFragmentProgram.cpp b/rpcs3/Emu/RSX/VK/VKFragmentProgram.cpp index 354761436e..bda40c7bcd 100644 --- a/rpcs3/Emu/RSX/VK/VKFragmentProgram.cpp +++ b/rpcs3/Emu/RSX/VK/VKFragmentProgram.cpp @@ -125,6 +125,8 @@ void VKFragmentDecompilerThread::insertConstants(std::stringstream & OS) if (m_prog.unnormalized_coords & (1 << index)) samplerType = "sampler2DRect"; + else if (m_prog.shadow_textures & (1 << index)) + samplerType = "sampler2DShadow"; vk::glsl::program_input in; in.location = location; diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index 7c04eaabca..c4fd5029a8 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -32,15 +32,15 @@ namespace namespace vk { - VkCompareOp get_compare_func(rsx::comparison_function op) + VkCompareOp get_compare_func(rsx::comparison_function op, bool reverse_direction = false) { switch (op) { case rsx::comparison_function::never: return VK_COMPARE_OP_NEVER; - case rsx::comparison_function::greater: return VK_COMPARE_OP_GREATER; - case rsx::comparison_function::less: return VK_COMPARE_OP_LESS; - case rsx::comparison_function::less_or_equal: return VK_COMPARE_OP_LESS_OR_EQUAL; - case rsx::comparison_function::greater_or_equal: return VK_COMPARE_OP_GREATER_OR_EQUAL; + case rsx::comparison_function::greater: return reverse_direction ? VK_COMPARE_OP_LESS: VK_COMPARE_OP_GREATER; + case rsx::comparison_function::less: return reverse_direction ? VK_COMPARE_OP_GREATER: VK_COMPARE_OP_LESS; + case rsx::comparison_function::less_or_equal: return reverse_direction ? VK_COMPARE_OP_GREATER_OR_EQUAL: VK_COMPARE_OP_LESS_OR_EQUAL; + case rsx::comparison_function::greater_or_equal: return reverse_direction ? VK_COMPARE_OP_LESS_OR_EQUAL: VK_COMPARE_OP_GREATER_OR_EQUAL; case rsx::comparison_function::equal: return VK_COMPARE_OP_EQUAL; case rsx::comparison_function::not_equal: return VK_COMPARE_OP_NOT_EQUAL; case rsx::comparison_function::always: return VK_COMPARE_OP_ALWAYS; @@ -863,6 +863,11 @@ void VKGSRender::end() continue; } + const u32 texture_format = rsx::method_registers.fragment_textures[i].format() & ~(CELL_GCM_TEXTURE_UN | CELL_GCM_TEXTURE_LN); + + VkBool32 is_depth_texture = (texture_format == CELL_GCM_TEXTURE_DEPTH16 || texture_format == CELL_GCM_TEXTURE_DEPTH24_D8); + VkCompareOp depth_compare = is_depth_texture? vk::get_compare_func((rsx::comparison_function)rsx::method_registers.fragment_textures[i].zfunc(), true): VK_COMPARE_OP_NEVER; + VkFilter min_filter; VkSamplerMipmapMode mip_mode; float min_lod = 0.f, max_lod = 0.f; @@ -886,8 +891,8 @@ void VKGSRender::end() vk::vk_wrap_mode(rsx::method_registers.fragment_textures[i].wrap_s()), vk::vk_wrap_mode(rsx::method_registers.fragment_textures[i].wrap_t()), vk::vk_wrap_mode(rsx::method_registers.fragment_textures[i].wrap_r()), !!(rsx::method_registers.fragment_textures[i].format() & CELL_GCM_TEXTURE_UN), lod_bias, vk::max_aniso(rsx::method_registers.fragment_textures[i].max_aniso()), min_lod, max_lod, - min_filter, vk::get_mag_filter(rsx::method_registers.fragment_textures[i].mag_filter()), mip_mode, vk::get_border_color(rsx::method_registers.fragment_textures[i].border_color()) - )); + min_filter, vk::get_mag_filter(rsx::method_registers.fragment_textures[i].mag_filter()), mip_mode, vk::get_border_color(rsx::method_registers.fragment_textures[i].border_color()), + is_depth_texture, depth_compare)); m_program->bind_uniform({ m_sampler_to_clean.back()->value, texture0->value, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }, "tex" + std::to_string(i), descriptor_sets); } diff --git a/rpcs3/Emu/RSX/VK/VKHelpers.h b/rpcs3/Emu/RSX/VK/VKHelpers.h index fcd59272eb..c002043b60 100644 --- a/rpcs3/Emu/RSX/VK/VKHelpers.h +++ b/rpcs3/Emu/RSX/VK/VKHelpers.h @@ -592,7 +592,8 @@ namespace vk sampler(VkDevice dev, VkSamplerAddressMode clamp_u, VkSamplerAddressMode clamp_v, VkSamplerAddressMode clamp_w, bool unnormalized_coordinates, float mipLodBias, float max_anisotropy, float min_lod, float max_lod, - VkFilter min_filter, VkFilter mag_filter, VkSamplerMipmapMode mipmap_mode, VkBorderColor border_color) + VkFilter min_filter, VkFilter mag_filter, VkSamplerMipmapMode mipmap_mode, VkBorderColor border_color, + VkBool32 depth_compare = false, VkCompareOp depth_compare_mode = VK_COMPARE_OP_NEVER) : m_device(dev) { VkSamplerCreateInfo info = {}; @@ -601,7 +602,7 @@ namespace vk info.addressModeV = clamp_v; info.addressModeW = clamp_w; info.anisotropyEnable = VK_TRUE; - info.compareEnable = VK_FALSE; + info.compareEnable = depth_compare; info.unnormalizedCoordinates = unnormalized_coordinates; info.mipLodBias = mipLodBias; info.maxAnisotropy = max_anisotropy; @@ -610,7 +611,7 @@ namespace vk info.magFilter = mag_filter; info.minFilter = min_filter; info.mipmapMode = mipmap_mode; - info.compareOp = VK_COMPARE_OP_NEVER; + info.compareOp = depth_compare_mode; info.borderColor = border_color; CHECK_RESULT(vkCreateSampler(m_device, &info, nullptr, &value));