rsx: Get rid of some guessing when handling special hardware formats

This commit is contained in:
kd-11 2026-02-23 01:42:49 +03:00 committed by kd-11
parent cb7c3488ab
commit 34f0e865ac
4 changed files with 28 additions and 8 deletions

View file

@ -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

View file

@ -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;
}
}

View file

@ -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; }

View file

@ -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; }