mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-16 11:48:36 +12:00
gl: Use the GPU to scale textures; use ARB_sampler_object
Improve scaling and separate sampler state from texture state gl: Unify all texture cache objects under one structure separate by use case gl: Texture cache fixes - Acquire lock when finding matching textures - Account for swizzled surfaces when deciding whether to cpu memcpy - Handle swizzled images on the GPU
This commit is contained in:
parent
d94986ff0d
commit
6d6d0e4e36
11 changed files with 880 additions and 370 deletions
|
@ -67,6 +67,116 @@ namespace gl
|
|||
}
|
||||
fmt::throw_exception("Compressed or unknown texture format 0x%x" HERE, texture_format);
|
||||
}
|
||||
|
||||
GLenum wrap_mode(rsx::texture_wrap_mode wrap)
|
||||
{
|
||||
switch (wrap)
|
||||
{
|
||||
case rsx::texture_wrap_mode::wrap: return GL_REPEAT;
|
||||
case rsx::texture_wrap_mode::mirror: return GL_MIRRORED_REPEAT;
|
||||
case rsx::texture_wrap_mode::clamp_to_edge: return GL_CLAMP_TO_EDGE;
|
||||
case rsx::texture_wrap_mode::border: return GL_CLAMP_TO_BORDER;
|
||||
case rsx::texture_wrap_mode::clamp: return GL_CLAMP_TO_EDGE;
|
||||
case rsx::texture_wrap_mode::mirror_once_clamp_to_edge: return GL_MIRROR_CLAMP_TO_EDGE_EXT;
|
||||
case rsx::texture_wrap_mode::mirror_once_border: return GL_MIRROR_CLAMP_TO_BORDER_EXT;
|
||||
case rsx::texture_wrap_mode::mirror_once_clamp: return GL_MIRROR_CLAMP_EXT;
|
||||
}
|
||||
|
||||
LOG_ERROR(RSX, "Texture wrap error: bad wrap (%d)", (u32)wrap);
|
||||
return GL_REPEAT;
|
||||
}
|
||||
|
||||
float max_aniso(rsx::texture_max_anisotropy aniso)
|
||||
{
|
||||
switch (aniso)
|
||||
{
|
||||
case rsx::texture_max_anisotropy::x1: return 1.0f;
|
||||
case rsx::texture_max_anisotropy::x2: return 2.0f;
|
||||
case rsx::texture_max_anisotropy::x4: return 4.0f;
|
||||
case rsx::texture_max_anisotropy::x6: return 6.0f;
|
||||
case rsx::texture_max_anisotropy::x8: return 8.0f;
|
||||
case rsx::texture_max_anisotropy::x10: return 10.0f;
|
||||
case rsx::texture_max_anisotropy::x12: return 12.0f;
|
||||
case rsx::texture_max_anisotropy::x16: return 16.0f;
|
||||
}
|
||||
|
||||
LOG_ERROR(RSX, "Texture anisotropy error: bad max aniso (%d)", (u32)aniso);
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
int tex_min_filter(rsx::texture_minify_filter min_filter)
|
||||
{
|
||||
switch (min_filter)
|
||||
{
|
||||
case rsx::texture_minify_filter::nearest: return GL_NEAREST;
|
||||
case rsx::texture_minify_filter::linear: return GL_LINEAR;
|
||||
case rsx::texture_minify_filter::nearest_nearest: return GL_NEAREST_MIPMAP_NEAREST;
|
||||
case rsx::texture_minify_filter::linear_nearest: return GL_LINEAR_MIPMAP_NEAREST;
|
||||
case rsx::texture_minify_filter::nearest_linear: return GL_NEAREST_MIPMAP_LINEAR;
|
||||
case rsx::texture_minify_filter::linear_linear: return GL_LINEAR_MIPMAP_LINEAR;
|
||||
case rsx::texture_minify_filter::convolution_min: return GL_LINEAR_MIPMAP_LINEAR;
|
||||
}
|
||||
fmt::throw_exception("Unknow min filter" HERE);
|
||||
}
|
||||
|
||||
int tex_mag_filter(rsx::texture_magnify_filter mag_filter)
|
||||
{
|
||||
switch (mag_filter)
|
||||
{
|
||||
case rsx::texture_magnify_filter::nearest: return GL_NEAREST;
|
||||
case rsx::texture_magnify_filter::linear: return GL_LINEAR;
|
||||
case rsx::texture_magnify_filter::convolution_mag: return GL_LINEAR;
|
||||
}
|
||||
fmt::throw_exception("Unknow mag filter" HERE);
|
||||
}
|
||||
|
||||
//Apply sampler state settings
|
||||
void sampler_state::apply(rsx::fragment_texture& tex)
|
||||
{
|
||||
const f32 border_color = (f32)tex.border_color() / 255;
|
||||
const f32 border_color_array[] = { border_color, border_color, border_color, border_color };
|
||||
|
||||
glSamplerParameteri(samplerHandle, GL_TEXTURE_WRAP_S, wrap_mode(tex.wrap_s()));
|
||||
glSamplerParameteri(samplerHandle, GL_TEXTURE_WRAP_T, wrap_mode(tex.wrap_t()));
|
||||
glSamplerParameteri(samplerHandle, GL_TEXTURE_WRAP_R, wrap_mode(tex.wrap_r()));
|
||||
glSamplerParameterfv(samplerHandle, GL_TEXTURE_BORDER_COLOR, border_color_array);
|
||||
|
||||
if (tex.get_exact_mipmap_count() <= 1)
|
||||
{
|
||||
GLint min_filter = tex_min_filter(tex.min_filter());
|
||||
|
||||
if (min_filter != GL_LINEAR && min_filter != GL_NEAREST)
|
||||
{
|
||||
switch (min_filter)
|
||||
{
|
||||
case GL_NEAREST_MIPMAP_NEAREST:
|
||||
case GL_NEAREST_MIPMAP_LINEAR:
|
||||
min_filter = GL_NEAREST; break;
|
||||
case GL_LINEAR_MIPMAP_NEAREST:
|
||||
case GL_LINEAR_MIPMAP_LINEAR:
|
||||
min_filter = GL_LINEAR; break;
|
||||
default:
|
||||
LOG_ERROR(RSX, "No mipmap fallback defined for rsx_min_filter = 0x%X", (u32)tex.min_filter());
|
||||
min_filter = GL_NEAREST;
|
||||
}
|
||||
}
|
||||
|
||||
glSamplerParameteri(samplerHandle, GL_TEXTURE_MIN_FILTER, min_filter);
|
||||
glSamplerParameteri(samplerHandle, GL_TEXTURE_LOD_BIAS, 0.);
|
||||
glSamplerParameteri(samplerHandle, GL_TEXTURE_MIN_LOD, 0);
|
||||
glSamplerParameteri(samplerHandle, GL_TEXTURE_MAX_LOD, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
glSamplerParameteri(samplerHandle, GL_TEXTURE_MIN_FILTER, tex_min_filter(tex.min_filter()));
|
||||
glSamplerParameteri(samplerHandle, GL_TEXTURE_LOD_BIAS, tex.bias());
|
||||
glSamplerParameteri(samplerHandle, GL_TEXTURE_MIN_LOD, (tex.min_lod() >> 8));
|
||||
glSamplerParameteri(samplerHandle, GL_TEXTURE_MAX_LOD, (tex.max_lod() >> 8));
|
||||
}
|
||||
|
||||
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()));
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
|
@ -182,32 +292,6 @@ namespace rsx
|
|||
{
|
||||
namespace gl
|
||||
{
|
||||
int gl_tex_min_filter(rsx::texture_minify_filter min_filter)
|
||||
{
|
||||
switch (min_filter)
|
||||
{
|
||||
case rsx::texture_minify_filter::nearest: return GL_NEAREST;
|
||||
case rsx::texture_minify_filter::linear: return GL_LINEAR;
|
||||
case rsx::texture_minify_filter::nearest_nearest: return GL_NEAREST_MIPMAP_NEAREST;
|
||||
case rsx::texture_minify_filter::linear_nearest: return GL_LINEAR_MIPMAP_NEAREST;
|
||||
case rsx::texture_minify_filter::nearest_linear: return GL_NEAREST_MIPMAP_LINEAR;
|
||||
case rsx::texture_minify_filter::linear_linear: return GL_LINEAR_MIPMAP_LINEAR;
|
||||
case rsx::texture_minify_filter::convolution_min: return GL_LINEAR_MIPMAP_LINEAR;
|
||||
}
|
||||
fmt::throw_exception("Unknow min filter" HERE);
|
||||
}
|
||||
|
||||
int gl_tex_mag_filter(rsx::texture_magnify_filter mag_filter)
|
||||
{
|
||||
switch (mag_filter)
|
||||
{
|
||||
case rsx::texture_magnify_filter::nearest: return GL_NEAREST;
|
||||
case rsx::texture_magnify_filter::linear: return GL_LINEAR;
|
||||
case rsx::texture_magnify_filter::convolution_mag: return GL_LINEAR;
|
||||
}
|
||||
fmt::throw_exception("Unknow mag filter" HERE);
|
||||
}
|
||||
|
||||
static const int gl_tex_zfunc[] =
|
||||
{
|
||||
GL_NEVER,
|
||||
|
@ -230,42 +314,6 @@ namespace rsx
|
|||
glGenTextures(1, &m_id);
|
||||
}
|
||||
|
||||
int texture::gl_wrap(rsx::texture_wrap_mode wrap)
|
||||
{
|
||||
switch (wrap)
|
||||
{
|
||||
case rsx::texture_wrap_mode::wrap: return GL_REPEAT;
|
||||
case rsx::texture_wrap_mode::mirror: return GL_MIRRORED_REPEAT;
|
||||
case rsx::texture_wrap_mode::clamp_to_edge: return GL_CLAMP_TO_EDGE;
|
||||
case rsx::texture_wrap_mode::border: return GL_CLAMP_TO_BORDER;
|
||||
case rsx::texture_wrap_mode::clamp: return GL_CLAMP_TO_EDGE;
|
||||
case rsx::texture_wrap_mode::mirror_once_clamp_to_edge: return GL_MIRROR_CLAMP_TO_EDGE_EXT;
|
||||
case rsx::texture_wrap_mode::mirror_once_border: return GL_MIRROR_CLAMP_TO_BORDER_EXT;
|
||||
case rsx::texture_wrap_mode::mirror_once_clamp: return GL_MIRROR_CLAMP_EXT;
|
||||
}
|
||||
|
||||
LOG_ERROR(RSX, "Texture wrap error: bad wrap (%d)", (u32)wrap);
|
||||
return GL_REPEAT;
|
||||
}
|
||||
|
||||
float texture::max_aniso(rsx::texture_max_anisotropy aniso)
|
||||
{
|
||||
switch (aniso)
|
||||
{
|
||||
case rsx::texture_max_anisotropy::x1: return 1.0f;
|
||||
case rsx::texture_max_anisotropy::x2: return 2.0f;
|
||||
case rsx::texture_max_anisotropy::x4: return 4.0f;
|
||||
case rsx::texture_max_anisotropy::x6: return 6.0f;
|
||||
case rsx::texture_max_anisotropy::x8: return 8.0f;
|
||||
case rsx::texture_max_anisotropy::x10: return 10.0f;
|
||||
case rsx::texture_max_anisotropy::x12: return 12.0f;
|
||||
case rsx::texture_max_anisotropy::x16: return 16.0f;
|
||||
}
|
||||
|
||||
LOG_ERROR(RSX, "Texture anisotropy error: bad max aniso (%d)", (u32)aniso);
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
u16 texture::get_pitch_modifier(u32 format)
|
||||
{
|
||||
switch (format)
|
||||
|
@ -535,49 +583,7 @@ namespace rsx
|
|||
__glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_G, remap_values[2]);
|
||||
__glcheck glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_B, remap_values[3]);
|
||||
|
||||
__glcheck glTexParameteri(m_target, GL_TEXTURE_WRAP_S, gl_wrap(tex.wrap_s()));
|
||||
__glcheck glTexParameteri(m_target, GL_TEXTURE_WRAP_T, gl_wrap(tex.wrap_t()));
|
||||
__glcheck glTexParameteri(m_target, GL_TEXTURE_WRAP_R, gl_wrap(tex.wrap_r()));
|
||||
|
||||
if (tex.get_exact_mipmap_count() <= 1 || m_target == GL_TEXTURE_RECTANGLE)
|
||||
{
|
||||
GLint min_filter = gl_tex_min_filter(tex.min_filter());
|
||||
|
||||
if (min_filter != GL_LINEAR && min_filter != GL_NEAREST)
|
||||
{
|
||||
LOG_WARNING(RSX, "Texture %d, target 0x%x, requesting mipmap filtering without any mipmaps set!", m_id, m_target);
|
||||
|
||||
switch (min_filter)
|
||||
{
|
||||
case GL_NEAREST_MIPMAP_NEAREST:
|
||||
case GL_NEAREST_MIPMAP_LINEAR:
|
||||
min_filter = GL_NEAREST; break;
|
||||
case GL_LINEAR_MIPMAP_NEAREST:
|
||||
case GL_LINEAR_MIPMAP_LINEAR:
|
||||
min_filter = GL_LINEAR; break;
|
||||
default:
|
||||
LOG_ERROR(RSX, "No mipmap fallback defined for rsx_min_filter = 0x%X", (u32)tex.min_filter());
|
||||
min_filter = GL_NEAREST;
|
||||
}
|
||||
}
|
||||
|
||||
__glcheck glTexParameteri(m_target, GL_TEXTURE_MIN_FILTER, min_filter);
|
||||
|
||||
__glcheck glTexParameterf(m_target, GL_TEXTURE_LOD_BIAS, 0.);
|
||||
__glcheck glTexParameteri(m_target, GL_TEXTURE_MIN_LOD, 0);
|
||||
__glcheck glTexParameteri(m_target, GL_TEXTURE_MAX_LOD, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
__glcheck glTexParameteri(m_target, GL_TEXTURE_MIN_FILTER, gl_tex_min_filter(tex.min_filter()));
|
||||
|
||||
__glcheck glTexParameterf(m_target, GL_TEXTURE_LOD_BIAS, tex.bias());
|
||||
__glcheck glTexParameteri(m_target, GL_TEXTURE_MIN_LOD, (tex.min_lod() >> 8));
|
||||
__glcheck glTexParameteri(m_target, GL_TEXTURE_MAX_LOD, (tex.max_lod() >> 8));
|
||||
}
|
||||
|
||||
__glcheck glTexParameteri(m_target, GL_TEXTURE_MAG_FILTER, gl_tex_mag_filter(tex.mag_filter()));
|
||||
__glcheck glTexParameterf(m_target, GL_TEXTURE_MAX_ANISOTROPY_EXT, max_aniso(tex.max_aniso()));
|
||||
//The rest of sampler state is now handled by sampler state objects
|
||||
}
|
||||
|
||||
void texture::init(int index, rsx::vertex_texture& tex)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue