diff --git a/rpcs3/Emu/RSX/Common/TextureUtils.h b/rpcs3/Emu/RSX/Common/TextureUtils.h index f8d899a6ca..1cc9c21248 100644 --- a/rpcs3/Emu/RSX/Common/TextureUtils.h +++ b/rpcs3/Emu/RSX/Common/TextureUtils.h @@ -135,6 +135,12 @@ namespace rsx RSX_FORMAT_FEATURE_16BIT_CHANNELS = (1 << 3), // Complements RSX_FORMAT_FEATURE_SIGNED_COMPONENTS }; + enum host_format_features : u8 + { + RSX_HOST_FORMAT_FEATURE_SNORM = (1 << 0), + RSX_HOST_FORMAT_FEATURE_SRGB = (1 << 1), + }; + using enum format_features; struct texture_format_ex @@ -150,10 +156,14 @@ namespace rsx bool hw_SNORM_possible() const; bool hw_SRGB_possible() const; + bool host_snorm_format_active() const { return host_features & RSX_HOST_FORMAT_FEATURE_SNORM; } + bool host_srgb_format_active() const { return host_features & RSX_HOST_FORMAT_FEATURE_SRGB; } + //private: u32 format_bits = 0; u32 features = 0; u32 texel_remap_control = 0; + u32 host_features = 0; }; // Sampled image descriptor diff --git a/rpcs3/Emu/RSX/GL/GLDraw.cpp b/rpcs3/Emu/RSX/GL/GLDraw.cpp index bdf5a53d01..10e5f6da31 100644 --- a/rpcs3/Emu/RSX/GL/GLDraw.cpp +++ b/rpcs3/Emu/RSX/GL/GLDraw.cpp @@ -361,22 +361,26 @@ void GLGSRender::load_texture_env() const auto gl_format = sampler_state->image_handle->view_format(); GLenum format_override = gl_format; rsx::flags32_t flags_to_erase = 0u; + rsx::flags32_t host_flags_to_set = 0u; if (sampler_state->format_ex.hw_SNORM_possible()) { format_override = gl::get_compatible_snorm_format(gl_format); flags_to_erase = rsx::texture_control_bits::SEXT_MASK; + host_flags_to_set = rsx::RSX_HOST_FORMAT_FEATURE_SNORM; } else if (sampler_state->format_ex.hw_SRGB_possible()) { format_override = gl::get_compatible_srgb_format(gl_format); flags_to_erase = rsx::texture_control_bits::GAMMA_CTRL_MASK; + host_flags_to_set = rsx::RSX_HOST_FORMAT_FEATURE_SRGB; } if (format_override != GL_NONE && format_override != gl_format) { sampler_state->image_handle = sampler_state->image_handle->as(format_override); sampler_state->format_ex.texel_remap_control &= (~flags_to_erase); + sampler_state->format_ex.host_features |= host_flags_to_set; } } diff --git a/rpcs3/Emu/RSX/GL/glutils/sampler.cpp b/rpcs3/Emu/RSX/GL/glutils/sampler.cpp index 0d37dc3524..387228983c 100644 --- a/rpcs3/Emu/RSX/GL/glutils/sampler.cpp +++ b/rpcs3/Emu/RSX/GL/glutils/sampler.cpp @@ -84,23 +84,25 @@ namespace gl // Therefore, we pass the raw value here, and the texture view will handle the rest for us. const bool sext_conv_required = (sampled_image->format_ex.texel_remap_control & rsx::SEXT_MASK) != 0; const auto encoded_color = tex.border_color(sext_conv_required); - if (get_parameteri(GL_TEXTURE_BORDER_COLOR) != encoded_color) + const auto host_features = sampled_image->format_ex.host_features; + + if (get_parameteri(GL_TEXTURE_BORDER_COLOR) != encoded_color || + get_parameteri(GL_TEXTURE_BORDER_VALUES_NV) != host_features) { m_propertiesi[GL_TEXTURE_BORDER_COLOR] = encoded_color; - auto border_color = rsx::decode_border_color(encoded_color); + m_propertiesi[GL_TEXTURE_BORDER_VALUES_NV] = host_features; - if (const auto snorm_mask = tex.argb_signed(); - !sext_conv_required && tex.argb_signed()) [[ unlikely ]] + auto border_color = rsx::decode_border_color(encoded_color); + if (sampled_image->format_ex.host_snorm_format_active()) [[ unlikely ]] { // Hardware SNORM is active - ensure(sampled_image->format_ex.hw_SNORM_possible()); - // Convert the border color in host space (2N - 1) // HW does the conversion in integer space as (x - 128) / 127 which introduces a biasing error. const float bias_v = 128.f / 255.f; const float scale_v = 255.f / 127.f; color4f scale{ 1.f }, bias{ 0.f }; + const auto snorm_mask = tex.argb_signed(); if (snorm_mask & 1) { scale.a = scale_v; bias.a = -bias_v; } if (snorm_mask & 2) { scale.r = scale_v; bias.r = -bias_v; } if (snorm_mask & 4) { scale.g = scale_v; bias.g = -bias_v; } diff --git a/rpcs3/Emu/RSX/VK/VKDraw.cpp b/rpcs3/Emu/RSX/VK/VKDraw.cpp index e13cc9aa94..2e62edd331 100644 --- a/rpcs3/Emu/RSX/VK/VKDraw.cpp +++ b/rpcs3/Emu/RSX/VK/VKDraw.cpp @@ -353,22 +353,26 @@ void VKGSRender::load_texture_env() const auto vk_format = sampler_state->image_handle->format(); VkFormat format_override = vk_format;; rsx::flags32_t flags_to_erase = 0u; + rsx::flags32_t host_flags_to_set = 0u; if (sampler_state->format_ex.hw_SNORM_possible()) { format_override = vk::get_compatible_snorm_format(vk_format); flags_to_erase = rsx::texture_control_bits::SEXT_MASK; + host_flags_to_set = rsx::RSX_HOST_FORMAT_FEATURE_SNORM; } else if (sampler_state->format_ex.hw_SRGB_possible()) { format_override = vk::get_compatible_srgb_format(vk_format); flags_to_erase = rsx::texture_control_bits::GAMMA_CTRL_MASK; + host_flags_to_set = rsx::RSX_HOST_FORMAT_FEATURE_SRGB; } if (format_override != VK_FORMAT_UNDEFINED && format_override != vk_format) { sampler_state->image_handle = sampler_state->image_handle->as(format_override); sampler_state->format_ex.texel_remap_control &= (~flags_to_erase); + sampler_state->format_ex.host_features |= host_flags_to_set; } } @@ -400,8 +404,7 @@ void VKGSRender::load_texture_env() if (rsx::is_border_clamped_texture(tex)) { auto color_value = get_border_color(tex, sext_conv_required); - if (const auto snorm_mask = tex.argb_signed(); - !sext_conv_required && snorm_mask) + if (sampler_state->format_ex.host_snorm_format_active()) { // Convert the border color in host space (2N - 1) // HW does the conversion in integer space as (x - 128) / 127 which introduces a biasing error. @@ -409,6 +412,7 @@ void VKGSRender::load_texture_env() const float scale_v = 255.f / 127.f; color4f scale{ 1.f }, bias{ 0.f }; + const auto snorm_mask = tex.argb_signed(); if (snorm_mask & 1) { scale.a = scale_v; bias.a = -bias_v; } if (snorm_mask & 2) { scale.r = scale_v; bias.r = -bias_v; } if (snorm_mask & 4) { scale.g = scale_v; bias.g = -bias_v; }