gl: Implement SNORM and SRGB format overrides

This commit is contained in:
kd-11 2026-02-22 20:57:16 +03:00 committed by kd-11
parent 0f1735d0df
commit e29cd4cc93
3 changed files with 81 additions and 6 deletions

View file

@ -334,17 +334,52 @@ void GLGSRender::load_texture_env()
continue;
}
if (!is_sampler_dirty)
{
if (sampler_state->format_class != previous_format_class)
{
// Host details changed but RSX is not aware
m_graphics_state |= rsx::fragment_program_state_dirty;
}
if (m_fs_sampler_states[i])
{
// Nothing to change, use cached sampler
continue;
}
}
sampler_state->format_ex = tex.format_ex();
if (is_sampler_dirty)
if (sampler_state->format_ex.texel_remap_control &&
sampler_state->image_handle &&
sampler_state->upload_context == rsx::texture_upload_context::shader_read) [[ unlikely ]]
{
m_fs_sampler_states[i].apply(tex, fs_sampler_state[i].get());
}
else if (sampler_state->format_class != previous_format_class)
{
m_graphics_state |= rsx::fragment_program_state_dirty;
// Check if we need to override the view format
const auto gl_format = sampler_state->image_handle->view_format();
GLenum format_override = gl_format;
rsx::flags32_t flags_to_erase = 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;
}
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;
}
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);
}
}
m_fs_sampler_states[i].apply(tex, fs_sampler_state[i].get());
const auto texture_format = sampler_state->format_ex.format();
// Depth format redirected to BGRA8 resample stage. Do not filter to avoid bits leaking.
// If accurate graphics are desired, force a bitcast to COLOR as a workaround.

View file

@ -266,6 +266,44 @@ namespace gl
fmt::throw_exception("Unknown format 0x%x", texture_format);
}
GLenum get_compatible_snorm_format(GLenum base_format)
{
switch (base_format)
{
case GL_R8:
return GL_R8_SNORM;
case GL_RG8:
return GL_RG8_SNORM;
case GL_RGBA8:
return GL_RGBA8_SNORM;
case GL_R16:
return GL_R16_SNORM;
case GL_RG16:
return GL_RG16_SNORM;
case GL_RGBA16:
return GL_RGBA16_SNORM;
default:
return GL_NONE;
}
}
GLenum get_compatible_srgb_format(GLenum base_format)
{
switch (base_format)
{
case GL_RGBA8:
return GL_SRGB8_ALPHA8_EXT;
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT;
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT;
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT;
default:
return GL_NONE;
}
}
cs_shuffle_base* get_trivial_transform_job(const pixel_buffer_layout& pack_info)
{
if (!pack_info.swap_bytes)

View file

@ -62,6 +62,8 @@ namespace gl
std::tuple<GLenum, GLenum> get_format_type(u32 texture_format);
pixel_buffer_layout get_format_type(texture::internal_format format);
std::array<GLenum, 4> get_swizzle_remap(u32 texture_format);
GLenum get_compatible_snorm_format(GLenum base_format);
GLenum get_compatible_srgb_format(GLenum base_format);
viewable_image* create_texture(u32 gcm_format, u16 width, u16 height, u16 depth, u16 mipmaps, rsx::texture_dimension_extended type);