Improve scaling and separate sampler state from texture state

This commit is contained in:
kd-11 2017-03-18 21:38:50 +03:00
parent 604e42bde8
commit fe0600866c
6 changed files with 111 additions and 71 deletions

View file

@ -397,6 +397,7 @@ void GLGSRender::end()
std::chrono::time_point<steady_clock> textures_start = steady_clock::now();
//Setup textures
//Setting unused texture to 0 is not needed, but makes program validation happy if we choose to enforce it
for (int i = 0; i < rsx::limits::fragment_textures_count; ++i)
{
int location;
@ -411,6 +412,7 @@ void GLGSRender::end()
{
m_gl_textures[i].set_target(get_gl_target_for_texture(rsx::method_registers.fragment_textures[i]));
__glcheck m_gl_texture_cache.upload_texture(i, rsx::method_registers.fragment_textures[i], m_gl_textures[i], m_rtts);
__glcheck m_gl_sampler_states[i].apply(rsx::method_registers.fragment_textures[i]);
}
}
@ -561,6 +563,12 @@ void GLGSRender::on_init_thread()
if (g_cfg_rsx_overlay)
m_text_printer.init();
for (int i = 0; i < rsx::limits::fragment_textures_count; ++i)
{
m_gl_sampler_states[i].create();
m_gl_sampler_states[i].bind(i);
}
m_gl_texture_cache.initialize(this);
}
@ -595,6 +603,11 @@ void GLGSRender::on_exit()
tex.remove();
}
for (auto &sampler : m_gl_sampler_states)
{
sampler.remove();
}
m_attrib_ring_buffer->remove();
m_transform_constants_buffer->remove();
m_fragment_constants_buffer->remove();

View file

@ -58,6 +58,7 @@ private:
rsx::gl::texture m_gl_textures[rsx::limits::fragment_textures_count];
rsx::gl::texture m_gl_vertex_textures[rsx::limits::vertex_textures_count];
gl::sampler_state m_gl_sampler_states[rsx::limits::fragment_textures_count];
gl::glsl::program *m_program;

View file

@ -172,6 +172,13 @@ OPENGL_PROC(PFNGLMULTIDRAWARRAYSPROC, MultiDrawArrays);
OPENGL_PROC(PFNGLGETTEXTUREIMAGEEXTPROC, GetTextureImageEXT);
//Sampler Objects
OPENGL_PROC(PFNGLGENSAMPLERSPROC, GenSamplers);
OPENGL_PROC(PFNGLDELETESAMPLERSPROC, DeleteSamplers);
OPENGL_PROC(PFNGLBINDSAMPLERPROC, BindSampler);
OPENGL_PROC(PFNGLSAMPLERPARAMETERIPROC, SamplerParameteri);
OPENGL_PROC(PFNGLSAMPLERPARAMETERFVPROC, SamplerParameterfv);
//Texture Buffers
OPENGL_PROC(PFNGLTEXBUFFERPROC, TexBuffer);
OPENGL_PROC(PFNGLTEXTUREBUFFERRANGEEXTPROC, TextureBufferRangeEXT);

View file

@ -67,6 +67,54 @@ 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_BORDER;
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;
}
//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);
}
}
namespace
@ -230,42 +278,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_BORDER;
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)
@ -431,8 +443,8 @@ namespace rsx
return true;
return false;
}
}
void texture::init(int index, rsx::fragment_texture& tex)
{
switch (tex.dimension())
@ -527,9 +539,9 @@ 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()));
__glcheck glTexParameteri(m_target, GL_TEXTURE_WRAP_S, ::gl::wrap_mode(tex.wrap_s()));
__glcheck glTexParameteri(m_target, GL_TEXTURE_WRAP_T, ::gl::wrap_mode(tex.wrap_t()));
__glcheck glTexParameteri(m_target, GL_TEXTURE_WRAP_R, ::gl::wrap_mode(tex.wrap_r()));
if (tex.get_exact_mipmap_count() <= 1 || m_target == GL_TEXTURE_RECTANGLE)
{
@ -569,7 +581,7 @@ namespace rsx
}
__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()));
__glcheck glTexParameterf(m_target, GL_TEXTURE_MAX_ANISOTROPY_EXT, ::gl::max_aniso(tex.max_aniso()));
}
void texture::init(int index, rsx::vertex_texture& tex)

View file

@ -5,7 +5,42 @@ namespace rsx
{
class vertex_texture;
class fragment_texture;
}
namespace gl
{
GLenum get_sized_internal_format(u32 gcm_format);
std::tuple<GLenum, GLenum> get_format_type(u32 texture_format);
GLenum wrap_mode(rsx::texture_wrap_mode wrap);
float max_aniso(rsx::texture_max_anisotropy aniso);
class sampler_state
{
GLuint samplerHandle = 0;
public:
void create()
{
glGenSamplers(1, &samplerHandle);
}
void remove()
{
glDeleteSamplers(1, &samplerHandle);
}
void bind(int index)
{
glBindSampler(index, samplerHandle);
}
void apply(rsx::fragment_texture& tex);
};
}
namespace rsx
{
namespace gl
{
class texture
@ -16,28 +51,6 @@ namespace rsx
public:
void create();
int gl_wrap(rsx::texture_wrap_mode in);
float max_aniso(rsx::texture_max_anisotropy aniso);
inline static u8 convert_4_to_8(u8 v)
{
// Swizzle bits: 00001234 -> 12341234
return (v << 4) | (v);
}
inline static u8 convert_5_to_8(u8 v)
{
// Swizzle bits: 00012345 -> 12345123
return (v << 3) | (v >> 2);
}
inline static u8 convert_6_to_8(u8 v)
{
// Swizzle bits: 00123456 -> 12345612
return (v << 2) | (v >> 4);
}
void init(int index, rsx::fragment_texture& tex);
void init(int index, rsx::vertex_texture& tex);
@ -64,9 +77,3 @@ namespace rsx
};
}
}
namespace gl
{
GLenum get_sized_internal_format(u32 gcm_format);
std::tuple<GLenum, GLenum> get_format_type(u32 texture_format);
}

View file

@ -1073,7 +1073,7 @@ namespace gl
const u32 dst_address = (u32)((u64)dst.pixels - (u64)vm::base(0));
//Check if src/dst are parts of render targets
surface_subresource src_subres = m_rtts.get_surface_subresource_if_applicable(src_address, src.width, src.slice_h, src.pitch, true, true);
surface_subresource src_subres = m_rtts.get_surface_subresource_if_applicable(src_address, src.width, src.height, src.pitch, true, true);
src_is_render_target = src_subres.surface != nullptr;
//Prepare areas and offsets