mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 10:42: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:
parent
b3162bd41c
commit
57dd611111
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
185
rpcs3/Emu/RSX/GL/glutils/sampler.cpp
Normal file
185
rpcs3/Emu/RSX/GL/glutils/sampler.cpp
Normal 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);
|
||||
}
|
||||
}
|
107
rpcs3/Emu/RSX/GL/glutils/sampler.h
Normal file
107
rpcs3/Emu/RSX/GL/glutils/sampler.h
Normal 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);
|
||||
}
|
||||
};
|
||||
}
|
@ -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)
|
||||
|
@ -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" />
|
||||
|
@ -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">
|
||||
|
Loading…
Reference in New Issue
Block a user