1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-22 02:32:36 +01:00

gl: Fix incomplete stencil view of depth-stencil texture

- Samplers must use point sampling for stencil views
This commit is contained in:
kd-11 2022-07-31 16:56:20 +03:00 committed by kd-11
parent b3162bd41c
commit 57dd611111
12 changed files with 327 additions and 285 deletions

View File

@ -471,6 +471,7 @@ target_sources(rpcs3_emu PRIVATE
RSX/GL/glutils/image.cpp
RSX/GL/glutils/program.cpp
RSX/GL/glutils/ring_buffer.cpp
RSX/GL/glutils/sampler.cpp
RSX/GL/GLCommonDecompiler.cpp
RSX/GL/GLCompute.cpp
RSX/GL/GLDraw.cpp

View File

@ -305,6 +305,15 @@ namespace gl
auto depth_view = src->get_view(GL_REMAP_IDENTITY, rsx::default_remap_vector, gl::image_aspect::depth);
auto stencil_view = src->get_view(GL_REMAP_IDENTITY, rsx::default_remap_vector, gl::image_aspect::stencil);
if (!m_sampler)
{
m_sampler.create();
m_sampler.apply_defaults();
}
gl::saved_sampler_state save_0(GL_COMPUTE_BUFFER_SLOT(0), m_sampler);
gl::saved_sampler_state save_1(GL_COMPUTE_BUFFER_SLOT(1), m_sampler);
depth_view->bind(cmd, GL_COMPUTE_BUFFER_SLOT(0));
stencil_view->bind(cmd, GL_COMPUTE_BUFFER_SLOT(1));
dst->bind_range(gl::buffer::target::ssbo, GL_COMPUTE_BUFFER_SLOT(2), out_offset, row_pitch * 4 * region.height);
@ -345,6 +354,14 @@ namespace gl
auto data_view = src->get_view(GL_REMAP_IDENTITY, rsx::default_remap_vector, gl::image_aspect::color);
if (!m_sampler)
{
m_sampler.create();
m_sampler.apply_defaults();
}
gl::saved_sampler_state save(GL_COMPUTE_BUFFER_SLOT(0), m_sampler);
data_view->bind(cmd, GL_COMPUTE_BUFFER_SLOT(0));
dst->bind_range(gl::buffer::target::ssbo, GL_COMPUTE_BUFFER_SLOT(1), out_offset, row_pitch * 4 * region.height);

View File

@ -25,7 +25,7 @@ namespace gl
void initialize();
void create();
void destroy();
virtual void destroy();
virtual void bind_resources() {}
@ -343,8 +343,13 @@ namespace gl
struct pixel_buffer_layout;
struct cs_image_to_ssbo : compute_task
class cs_image_to_ssbo : public compute_task
{
protected:
gl::sampler_state m_sampler;
public:
void destroy() override { m_sampler.remove(); compute_task::destroy(); }
virtual void run(gl::command_context& cmd, gl::viewable_image* src, const gl::buffer* dst, u32 out_offset, const coordu& region, const gl::pixel_buffer_layout& layout) = 0;
};

View File

@ -22,6 +22,7 @@
// TODO: Include on use
#include "glutils/buffer_object.h"
#include "glutils/image.h"
#include "glutils/sampler.h"
#include "glutils/pixel_settings.hpp"
#include "glutils/state_tracker.hpp"

View File

@ -35,28 +35,6 @@ namespace gl
GLenum primitives = GL_TRIANGLE_STRIP;
GLenum input_filter = GL_NEAREST;
struct saved_sampler_state
{
GLuint saved = GL_NONE;
GLuint unit = 0;
saved_sampler_state(GLuint _unit, const gl::sampler_state& sampler)
{
glActiveTexture(GL_TEXTURE0 + _unit);
glGetIntegerv(GL_SAMPLER_BINDING, reinterpret_cast<GLint*>(&saved));
unit = _unit;
sampler.bind(_unit);
}
saved_sampler_state(const saved_sampler_state&) = delete;
~saved_sampler_state()
{
glBindSampler(unit, saved);
}
};
void create();
void destroy();

View File

@ -199,197 +199,6 @@ namespace gl
return ret;
}
GLenum get_srgb_format(GLenum in_format)
{
switch (in_format)
{
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;
case GL_RGBA8:
return GL_SRGB8_ALPHA8;
default:
//rsx_log.error("No gamma conversion for format 0x%X", in_format);
return in_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;
}
rsx_log.error("Texture wrap error: bad wrap (%d)", static_cast<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;
}
rsx_log.error("Texture anisotropy error: bad max aniso (%d)", static_cast<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("Unknown min filter");
}
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("Unknown mag filter");
}
// Apply sampler state settings
void sampler_state::apply(const rsx::fragment_texture& tex, const rsx::sampled_image_descriptor_base* sampled_image)
{
set_parameteri(GL_TEXTURE_WRAP_S, wrap_mode(tex.wrap_s()));
set_parameteri(GL_TEXTURE_WRAP_T, wrap_mode(tex.wrap_t()));
set_parameteri(GL_TEXTURE_WRAP_R, wrap_mode(tex.wrap_r()));
if (const auto color = tex.border_color();
get_parameteri(GL_TEXTURE_BORDER_COLOR) != color)
{
m_propertiesi[GL_TEXTURE_BORDER_COLOR] = color;
const color4f border_color = rsx::decode_border_color(color);
glSamplerParameterfv(samplerHandle, GL_TEXTURE_BORDER_COLOR, border_color.rgba);
}
if (sampled_image->upload_context != rsx::texture_upload_context::shader_read ||
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:
rsx_log.error("No mipmap fallback defined for rsx_min_filter = 0x%X", static_cast<u32>(tex.min_filter()));
min_filter = GL_NEAREST;
}
}
set_parameteri(GL_TEXTURE_MIN_FILTER, min_filter);
set_parameterf(GL_TEXTURE_LOD_BIAS, 0.f);
set_parameterf(GL_TEXTURE_MIN_LOD, -1000.f);
set_parameterf(GL_TEXTURE_MAX_LOD, 1000.f);
}
else
{
set_parameteri(GL_TEXTURE_MIN_FILTER, tex_min_filter(tex.min_filter()));
set_parameterf(GL_TEXTURE_LOD_BIAS, tex.bias());
set_parameterf(GL_TEXTURE_MIN_LOD, tex.min_lod());
set_parameterf(GL_TEXTURE_MAX_LOD, tex.max_lod());
}
const f32 af_level = max_aniso(tex.max_aniso());
set_parameterf(GL_TEXTURE_MAX_ANISOTROPY_EXT, af_level);
set_parameteri(GL_TEXTURE_MAG_FILTER, tex_mag_filter(tex.mag_filter()));
const u32 texture_format = tex.format() & ~(CELL_GCM_TEXTURE_UN | CELL_GCM_TEXTURE_LN);
if (texture_format == CELL_GCM_TEXTURE_DEPTH16 || texture_format == CELL_GCM_TEXTURE_DEPTH24_D8 ||
texture_format == CELL_GCM_TEXTURE_DEPTH16_FLOAT || texture_format == CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT)
{
//NOTE: The stored texture function is reversed wrt the textureProj compare function
GLenum compare_mode = static_cast<GLenum>(tex.zfunc()) | GL_NEVER;
switch (compare_mode)
{
case GL_GREATER: compare_mode = GL_LESS; break;
case GL_GEQUAL: compare_mode = GL_LEQUAL; break;
case GL_LESS: compare_mode = GL_GREATER; break;
case GL_LEQUAL: compare_mode = GL_GEQUAL; break;
}
set_parameteri(GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
set_parameteri(GL_TEXTURE_COMPARE_FUNC, compare_mode);
}
else
set_parameteri(GL_TEXTURE_COMPARE_MODE, GL_NONE);
}
void sampler_state::apply(const rsx::vertex_texture& tex, const rsx::sampled_image_descriptor_base* /*sampled_image*/)
{
if (const auto color = tex.border_color();
get_parameteri(GL_TEXTURE_BORDER_COLOR) != color)
{
m_propertiesi[GL_TEXTURE_BORDER_COLOR] = color;
const color4f border_color = rsx::decode_border_color(color);
glSamplerParameterfv(samplerHandle, GL_TEXTURE_BORDER_COLOR, border_color.rgba);
}
set_parameteri(GL_TEXTURE_WRAP_S, wrap_mode(tex.wrap_s()));
set_parameteri(GL_TEXTURE_WRAP_T, wrap_mode(tex.wrap_t()));
set_parameteri(GL_TEXTURE_WRAP_R, wrap_mode(tex.wrap_r()));
set_parameteri(GL_TEXTURE_MIN_FILTER, GL_NEAREST);
set_parameteri(GL_TEXTURE_MAG_FILTER, GL_NEAREST);
set_parameterf(GL_TEXTURE_LOD_BIAS, tex.bias());
set_parameterf(GL_TEXTURE_MIN_LOD, tex.min_lod());
set_parameterf(GL_TEXTURE_MAX_LOD, tex.max_lod());
set_parameteri(GL_TEXTURE_COMPARE_MODE, GL_NONE);
}
void sampler_state::apply_defaults(GLenum default_filter)
{
set_parameteri(GL_TEXTURE_WRAP_S, GL_REPEAT);
set_parameteri(GL_TEXTURE_WRAP_T, GL_REPEAT);
set_parameteri(GL_TEXTURE_WRAP_R, GL_REPEAT);
set_parameteri(GL_TEXTURE_MIN_FILTER, default_filter);
set_parameteri(GL_TEXTURE_MAG_FILTER, default_filter);
set_parameterf(GL_TEXTURE_LOD_BIAS, 0.f);
set_parameteri(GL_TEXTURE_MIN_LOD, 0);
set_parameteri(GL_TEXTURE_MAX_LOD, 0);
set_parameteri(GL_TEXTURE_COMPARE_MODE, GL_NONE);
}
std::array<GLenum, 4> get_swizzle_remap(u32 texture_format)
{
// NOTE: This must be in ARGB order in all forms below.

View File

@ -35,8 +35,6 @@ namespace gl
GLenum get_sized_internal_format(u32 texture_format);
std::tuple<GLenum, GLenum> get_format_type(u32 texture_format);
pixel_buffer_layout get_format_type(texture::internal_format format);
GLenum wrap_mode(rsx::texture_wrap_mode wrap);
float max_aniso(rsx::texture_max_anisotropy aniso);
std::array<GLenum, 4> get_swizzle_remap(u32 texture_format);
viewable_image* create_texture(u32 gcm_format, u16 width, u16 height, u16 depth, u16 mipmaps, rsx::texture_dimension_extended type);
@ -53,73 +51,6 @@ namespace gl
void upload_texture(gl::command_context& cmd, texture* dst, u32 gcm_format, bool is_swizzled, const std::vector<rsx::subresource_layout>& subresources_layout);
class sampler_state
{
GLuint samplerHandle = 0;
std::unordered_map<GLenum, GLuint> m_propertiesi;
std::unordered_map<GLenum, GLfloat> m_propertiesf;
public:
void create()
{
glGenSamplers(1, &samplerHandle);
}
void remove()
{
glDeleteSamplers(1, &samplerHandle);
}
void bind(int index) const
{
glBindSampler(index, samplerHandle);
}
void set_parameteri(GLenum pname, GLuint value)
{
auto prop = m_propertiesi.find(pname);
if (prop != m_propertiesi.end() &&
prop->second == value)
{
return;
}
m_propertiesi[pname] = value;
glSamplerParameteri(samplerHandle, pname, value);
}
void set_parameterf(GLenum pname, GLfloat value)
{
auto prop = m_propertiesf.find(pname);
if (prop != m_propertiesf.end() &&
prop->second == value)
{
return;
}
m_propertiesf[pname] = value;
glSamplerParameterf(samplerHandle, pname, value);
}
GLuint get_parameteri(GLenum pname)
{
auto prop = m_propertiesi.find(pname);
return (prop == m_propertiesi.end()) ? 0 : prop->second;
}
GLfloat get_parameterf(GLenum pname)
{
auto prop = m_propertiesf.find(pname);
return (prop == m_propertiesf.end()) ? 0 : prop->second;
}
void apply(const rsx::fragment_texture& tex, const rsx::sampled_image_descriptor_base* sampled_image);
void apply(const rsx::vertex_texture& tex, const rsx::sampled_image_descriptor_base* sampled_image);
void apply_defaults(GLenum default_filter = GL_NEAREST);
};
namespace debug
{
extern std::unique_ptr<texture> g_vis_texture;

View File

@ -0,0 +1,185 @@
#include "stdafx.h"
#include "sampler.h"
#include "Emu/RSX/gcm_enums.h"
#include "Emu/RSX/rsx_utils.h"
#include "Emu/RSX/Common/TextureUtils.h"
//GLenum wrap_mode(rsx::texture_wrap_mode wrap);
//float max_aniso(rsx::texture_max_anisotropy aniso);
namespace gl
{
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;
}
rsx_log.error("Texture wrap error: bad wrap (%d)", static_cast<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;
}
rsx_log.error("Texture anisotropy error: bad max aniso (%d)", static_cast<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("Unknown min filter");
}
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("Unknown mag filter");
}
// Apply sampler state settings
void sampler_state::apply(const rsx::fragment_texture& tex, const rsx::sampled_image_descriptor_base* sampled_image)
{
set_parameteri(GL_TEXTURE_WRAP_S, wrap_mode(tex.wrap_s()));
set_parameteri(GL_TEXTURE_WRAP_T, wrap_mode(tex.wrap_t()));
set_parameteri(GL_TEXTURE_WRAP_R, wrap_mode(tex.wrap_r()));
if (const auto color = tex.border_color();
get_parameteri(GL_TEXTURE_BORDER_COLOR) != color)
{
m_propertiesi[GL_TEXTURE_BORDER_COLOR] = color;
const color4f border_color = rsx::decode_border_color(color);
glSamplerParameterfv(sampler_handle, GL_TEXTURE_BORDER_COLOR, border_color.rgba);
}
if (sampled_image->upload_context != rsx::texture_upload_context::shader_read ||
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:
rsx_log.error("No mipmap fallback defined for rsx_min_filter = 0x%X", static_cast<u32>(tex.min_filter()));
min_filter = GL_NEAREST;
}
}
set_parameteri(GL_TEXTURE_MIN_FILTER, min_filter);
set_parameterf(GL_TEXTURE_LOD_BIAS, 0.f);
set_parameterf(GL_TEXTURE_MIN_LOD, -1000.f);
set_parameterf(GL_TEXTURE_MAX_LOD, 1000.f);
}
else
{
set_parameteri(GL_TEXTURE_MIN_FILTER, tex_min_filter(tex.min_filter()));
set_parameterf(GL_TEXTURE_LOD_BIAS, tex.bias());
set_parameterf(GL_TEXTURE_MIN_LOD, tex.min_lod());
set_parameterf(GL_TEXTURE_MAX_LOD, tex.max_lod());
}
const f32 af_level = max_aniso(tex.max_aniso());
set_parameterf(GL_TEXTURE_MAX_ANISOTROPY_EXT, af_level);
set_parameteri(GL_TEXTURE_MAG_FILTER, tex_mag_filter(tex.mag_filter()));
const u32 texture_format = tex.format() & ~(CELL_GCM_TEXTURE_UN | CELL_GCM_TEXTURE_LN);
if (texture_format == CELL_GCM_TEXTURE_DEPTH16 || texture_format == CELL_GCM_TEXTURE_DEPTH24_D8 ||
texture_format == CELL_GCM_TEXTURE_DEPTH16_FLOAT || texture_format == CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT)
{
//NOTE: The stored texture function is reversed wrt the textureProj compare function
GLenum compare_mode = static_cast<GLenum>(tex.zfunc()) | GL_NEVER;
switch (compare_mode)
{
case GL_GREATER: compare_mode = GL_LESS; break;
case GL_GEQUAL: compare_mode = GL_LEQUAL; break;
case GL_LESS: compare_mode = GL_GREATER; break;
case GL_LEQUAL: compare_mode = GL_GEQUAL; break;
}
set_parameteri(GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
set_parameteri(GL_TEXTURE_COMPARE_FUNC, compare_mode);
}
else
set_parameteri(GL_TEXTURE_COMPARE_MODE, GL_NONE);
}
void sampler_state::apply(const rsx::vertex_texture& tex, const rsx::sampled_image_descriptor_base* /*sampled_image*/)
{
if (const auto color = tex.border_color();
get_parameteri(GL_TEXTURE_BORDER_COLOR) != color)
{
m_propertiesi[GL_TEXTURE_BORDER_COLOR] = color;
const color4f border_color = rsx::decode_border_color(color);
glSamplerParameterfv(sampler_handle, GL_TEXTURE_BORDER_COLOR, border_color.rgba);
}
set_parameteri(GL_TEXTURE_WRAP_S, wrap_mode(tex.wrap_s()));
set_parameteri(GL_TEXTURE_WRAP_T, wrap_mode(tex.wrap_t()));
set_parameteri(GL_TEXTURE_WRAP_R, wrap_mode(tex.wrap_r()));
set_parameteri(GL_TEXTURE_MIN_FILTER, GL_NEAREST);
set_parameteri(GL_TEXTURE_MAG_FILTER, GL_NEAREST);
set_parameterf(GL_TEXTURE_LOD_BIAS, tex.bias());
set_parameterf(GL_TEXTURE_MIN_LOD, tex.min_lod());
set_parameterf(GL_TEXTURE_MAX_LOD, tex.max_lod());
set_parameteri(GL_TEXTURE_COMPARE_MODE, GL_NONE);
}
void sampler_state::apply_defaults(GLenum default_filter)
{
set_parameteri(GL_TEXTURE_WRAP_S, GL_REPEAT);
set_parameteri(GL_TEXTURE_WRAP_T, GL_REPEAT);
set_parameteri(GL_TEXTURE_WRAP_R, GL_REPEAT);
set_parameteri(GL_TEXTURE_MIN_FILTER, default_filter);
set_parameteri(GL_TEXTURE_MAG_FILTER, default_filter);
set_parameterf(GL_TEXTURE_LOD_BIAS, 0.f);
set_parameteri(GL_TEXTURE_MIN_LOD, 0);
set_parameteri(GL_TEXTURE_MAX_LOD, 0);
set_parameteri(GL_TEXTURE_COMPARE_MODE, GL_NONE);
}
}

View File

@ -0,0 +1,107 @@
#pragma once
#include "common.h"
namespace rsx
{
class fragment_texture;
class vertex_texture;
struct sampled_image_descriptor_base;
}
namespace gl
{
class sampler_state
{
GLuint sampler_handle = 0;
std::unordered_map<GLenum, GLuint> m_propertiesi;
std::unordered_map<GLenum, GLfloat> m_propertiesf;
public:
void create()
{
glGenSamplers(1, &sampler_handle);
}
void remove()
{
if (sampler_handle)
{
glDeleteSamplers(1, &sampler_handle);
}
}
void bind(int index) const
{
glBindSampler(index, sampler_handle);
}
void set_parameteri(GLenum pname, GLuint value)
{
auto prop = m_propertiesi.find(pname);
if (prop != m_propertiesi.end() &&
prop->second == value)
{
return;
}
m_propertiesi[pname] = value;
glSamplerParameteri(sampler_handle, pname, value);
}
void set_parameterf(GLenum pname, GLfloat value)
{
auto prop = m_propertiesf.find(pname);
if (prop != m_propertiesf.end() &&
prop->second == value)
{
return;
}
m_propertiesf[pname] = value;
glSamplerParameterf(sampler_handle, pname, value);
}
GLuint get_parameteri(GLenum pname)
{
auto prop = m_propertiesi.find(pname);
return (prop == m_propertiesi.end()) ? 0 : prop->second;
}
GLfloat get_parameterf(GLenum pname)
{
auto prop = m_propertiesf.find(pname);
return (prop == m_propertiesf.end()) ? 0 : prop->second;
}
void apply(const rsx::fragment_texture& tex, const rsx::sampled_image_descriptor_base* sampled_image);
void apply(const rsx::vertex_texture& tex, const rsx::sampled_image_descriptor_base* sampled_image);
void apply_defaults(GLenum default_filter = GL_NEAREST);
operator bool() const { return sampler_handle != GL_NONE; }
};
struct saved_sampler_state
{
GLuint saved = GL_NONE;
GLuint unit = 0;
saved_sampler_state(GLuint _unit, const gl::sampler_state& sampler)
{
glActiveTexture(GL_TEXTURE0 + _unit);
glGetIntegerv(GL_SAMPLER_BINDING, reinterpret_cast<GLint*>(&saved));
unit = _unit;
sampler.bind(_unit);
}
saved_sampler_state(const saved_sampler_state&) = delete;
~saved_sampler_state()
{
glBindSampler(unit, saved);
}
};
}

View File

@ -47,7 +47,7 @@ namespace rsx
if (m_cur_pos != index)
{
m_cur_pos = index;
m_text.set_pos(10, index * 18);
m_text.set_pos(10, static_cast<u16>(index * 18));
}
if ((m_expiration_time - time) < 2'000'000)

View File

@ -68,6 +68,7 @@
<ClInclude Include="Emu\RSX\GL\glutils\pixel_settings.hpp" />
<ClInclude Include="Emu\RSX\GL\glutils\program.h" />
<ClInclude Include="Emu\RSX\GL\glutils\ring_buffer.h" />
<ClInclude Include="Emu\RSX\GL\glutils\sampler.h" />
<ClInclude Include="Emu\RSX\GL\glutils\state_tracker.hpp" />
<ClInclude Include="Emu\RSX\GL\glutils\image.h" />
<ClInclude Include="Emu\RSX\GL\glutils\sync.hpp" />
@ -95,6 +96,7 @@
<ClCompile Include="Emu\RSX\GL\glutils\program.cpp" />
<ClCompile Include="Emu\RSX\GL\glutils\ring_buffer.cpp" />
<ClCompile Include="Emu\RSX\GL\glutils\image.cpp" />
<ClCompile Include="Emu\RSX\GL\glutils\sampler.cpp" />
<ClCompile Include="Emu\RSX\GL\GLVertexProgram.cpp" />
<ClCompile Include="Emu\RSX\GL\GLHelpers.cpp" />
<ClCompile Include="Emu\RSX\GL\GLPresent.cpp" />

View File

@ -38,6 +38,9 @@
<ClCompile Include="Emu\RSX\GL\glutils\program.cpp">
<Filter>glutils</Filter>
</ClCompile>
<ClCompile Include="Emu\RSX\GL\glutils\sampler.cpp">
<Filter>glutils</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Emu\RSX\GL\GLTexture.h" />
@ -92,6 +95,9 @@
<ClInclude Include="Emu\RSX\GL\glutils\sync.hpp">
<Filter>glutils</Filter>
</ClInclude>
<ClInclude Include="Emu\RSX\GL\glutils\sampler.h">
<Filter>glutils</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="glutils">