mirror of
https://github.com/RPCS3/rpcs3.git
synced 2026-03-09 23:14:46 +01:00
rsx: Add border color correction for hardware SNORM formats
This commit is contained in:
parent
585305f434
commit
759ef0f5b0
|
|
@ -821,6 +821,14 @@ struct color4_base
|
|||
a *= rhs;
|
||||
}
|
||||
|
||||
void operator += (const color4_base<T>& rhs)
|
||||
{
|
||||
r += rhs.r;
|
||||
g += rhs.g;
|
||||
b += rhs.b;
|
||||
a += rhs.a;
|
||||
}
|
||||
|
||||
constexpr color4_base<T> operator * (const color4_base<T>& rhs) const
|
||||
{
|
||||
return { r * rhs.r, g * rhs.g, b * rhs.b, a * rhs.a };
|
||||
|
|
|
|||
|
|
@ -82,11 +82,32 @@ namespace gl
|
|||
{
|
||||
// NOTE: In OpenGL, the border texels are processed by the pipeline and will be swizzled by the texture view.
|
||||
// Therefore, we pass the raw value here, and the texture view will handle the rest for us.
|
||||
const auto encoded_color = tex.border_color();
|
||||
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)
|
||||
{
|
||||
m_propertiesi[GL_TEXTURE_BORDER_COLOR] = encoded_color;
|
||||
const auto border_color = rsx::decode_border_color(encoded_color);
|
||||
auto border_color = rsx::decode_border_color(encoded_color);
|
||||
|
||||
if (const auto snorm_mask = tex.argb_signed();
|
||||
!sext_conv_required && tex.argb_signed()) [[ 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 };
|
||||
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; }
|
||||
if (snorm_mask & 8) { scale.b = scale_v; bias.b = -bias_v; }
|
||||
border_color = (border_color + bias) * scale;
|
||||
}
|
||||
|
||||
glSamplerParameterfv(sampler_handle, GL_TEXTURE_BORDER_COLOR, border_color.rgba);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -364,11 +364,15 @@ namespace rsx
|
|||
return dimension() != rsx::texture_dimension::dimension1d ? ((registers[NV4097_SET_TEXTURE_IMAGE_RECT + (m_index * 8)]) & 0xffff) : 1;
|
||||
}
|
||||
|
||||
u32 fragment_texture::border_color() const
|
||||
u32 fragment_texture::border_color(bool apply_colorspace_remapping) const
|
||||
{
|
||||
const u32 raw = registers[NV4097_SET_TEXTURE_BORDER_COLOR + (m_index * 8)];
|
||||
const u32 sext = argb_signed();
|
||||
if (!apply_colorspace_remapping) [[ likely ]]
|
||||
{
|
||||
return raw;
|
||||
}
|
||||
|
||||
const u32 sext = argb_signed();
|
||||
if (!sext) [[ likely ]]
|
||||
{
|
||||
return raw;
|
||||
|
|
@ -430,9 +434,9 @@ namespace rsx
|
|||
return (conv & mask) | (raw & ~mask);
|
||||
}
|
||||
|
||||
color4f fragment_texture::remapped_border_color() const
|
||||
color4f fragment_texture::remapped_border_color(bool apply_colorspace_remapping) const
|
||||
{
|
||||
color4f base_color = rsx::decode_border_color(border_color());
|
||||
color4f base_color = rsx::decode_border_color(border_color(apply_colorspace_remapping));
|
||||
if (remap() == RSX_TEXTURE_REMAP_IDENTITY)
|
||||
{
|
||||
return base_color;
|
||||
|
|
@ -571,14 +575,14 @@ namespace rsx
|
|||
return dimension() != rsx::texture_dimension::dimension1d ? ((registers[NV4097_SET_VERTEX_TEXTURE_IMAGE_RECT + (m_index * 8)]) & 0xffff) : 1;
|
||||
}
|
||||
|
||||
u32 vertex_texture::border_color() const
|
||||
u32 vertex_texture::border_color(bool) const
|
||||
{
|
||||
return registers[NV4097_SET_VERTEX_TEXTURE_BORDER_COLOR + (m_index * 8)];
|
||||
}
|
||||
|
||||
color4f vertex_texture::remapped_border_color() const
|
||||
color4f vertex_texture::remapped_border_color(bool) const
|
||||
{
|
||||
return rsx::decode_border_color(border_color());
|
||||
return rsx::decode_border_color(border_color(false));
|
||||
}
|
||||
|
||||
u16 vertex_texture::depth() const
|
||||
|
|
|
|||
|
|
@ -80,8 +80,8 @@ namespace rsx
|
|||
u16 height() const;
|
||||
|
||||
// Border Color
|
||||
u32 border_color() const;
|
||||
color4f remapped_border_color() const;
|
||||
u32 border_color(bool apply_colorspace_remapping = false) const;
|
||||
color4f remapped_border_color(bool apply_colorspace_remapping = false) const;
|
||||
|
||||
u16 depth() const;
|
||||
u32 pitch() const;
|
||||
|
|
@ -136,8 +136,8 @@ namespace rsx
|
|||
u16 height() const;
|
||||
|
||||
// Border Color
|
||||
u32 border_color() const;
|
||||
color4f remapped_border_color() const;
|
||||
u32 border_color(bool = false) const;
|
||||
color4f remapped_border_color(bool = false) const;
|
||||
|
||||
u16 depth() const;
|
||||
u32 pitch() const;
|
||||
|
|
|
|||
|
|
@ -274,11 +274,11 @@ void VKGSRender::load_texture_env()
|
|||
return false;
|
||||
};
|
||||
|
||||
auto get_border_color = [&](const rsx::Texture auto& tex)
|
||||
auto get_border_color = [&](const rsx::Texture auto& tex, bool remap_colorspace)
|
||||
{
|
||||
return m_device->get_custom_border_color_support().require_border_color_remap
|
||||
? tex.remapped_border_color()
|
||||
: rsx::decode_border_color(tex.border_color());
|
||||
? tex.remapped_border_color(remap_colorspace)
|
||||
: rsx::decode_border_color(tex.border_color(remap_colorspace));
|
||||
};
|
||||
|
||||
std::lock_guard lock(m_sampler_mutex);
|
||||
|
|
@ -394,9 +394,30 @@ void VKGSRender::load_texture_env()
|
|||
|
||||
// NOTE: In vulkan, the border color can bypass the sample swizzle stage.
|
||||
// Check the device properties to determine whether to pre-swizzle the colors or not.
|
||||
const auto border_color = rsx::is_border_clamped_texture(tex)
|
||||
? vk::border_color_t(get_border_color(tex))
|
||||
: vk::border_color_t(VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK);
|
||||
const bool sext_conv_required = (sampler_state->format_ex.texel_remap_control & rsx::texture_control_bits::SEXT_MASK) != 0;
|
||||
vk::border_color_t border_color(VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK);
|
||||
|
||||
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)
|
||||
{
|
||||
// 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 };
|
||||
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; }
|
||||
if (snorm_mask & 8) { scale.b = scale_v; bias.b = -bias_v; }
|
||||
color_value = (color_value + bias) * scale;
|
||||
}
|
||||
|
||||
border_color = color_value;
|
||||
}
|
||||
|
||||
// Check if non-point filtering can even be used on this format
|
||||
bool can_sample_linear;
|
||||
|
|
@ -404,7 +425,7 @@ void VKGSRender::load_texture_env()
|
|||
{
|
||||
// Most PS3-like formats can be linearly filtered without problem
|
||||
// Exclude textures that require SNORM conversion however
|
||||
can_sample_linear = (sampler_state->format_ex.texel_remap_control & rsx::texture_control_bits::SEXT_MASK) == 0;
|
||||
can_sample_linear = !sext_conv_required;
|
||||
}
|
||||
else if (sampler_state->format_class != rsx::classify_format(texture_format) &&
|
||||
(texture_format == CELL_GCM_TEXTURE_A8R8G8B8 || texture_format == CELL_GCM_TEXTURE_D8R8G8B8))
|
||||
|
|
@ -554,7 +575,7 @@ void VKGSRender::load_texture_env()
|
|||
// NOTE: In vulkan, the border color can bypass the sample swizzle stage.
|
||||
// Check the device properties to determine whether to pre-swizzle the colors or not.
|
||||
const auto border_color = is_border_clamped_texture(tex)
|
||||
? vk::border_color_t(get_border_color(tex))
|
||||
? vk::border_color_t(get_border_color(tex, false))
|
||||
: vk::border_color_t(VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK);
|
||||
|
||||
if (vs_sampler_handles[i] &&
|
||||
|
|
|
|||
Loading…
Reference in a new issue