mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-25 20:22:30 +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/image.cpp
|
||||||
RSX/GL/glutils/program.cpp
|
RSX/GL/glutils/program.cpp
|
||||||
RSX/GL/glutils/ring_buffer.cpp
|
RSX/GL/glutils/ring_buffer.cpp
|
||||||
|
RSX/GL/glutils/sampler.cpp
|
||||||
RSX/GL/GLCommonDecompiler.cpp
|
RSX/GL/GLCommonDecompiler.cpp
|
||||||
RSX/GL/GLCompute.cpp
|
RSX/GL/GLCompute.cpp
|
||||||
RSX/GL/GLDraw.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 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);
|
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));
|
depth_view->bind(cmd, GL_COMPUTE_BUFFER_SLOT(0));
|
||||||
stencil_view->bind(cmd, GL_COMPUTE_BUFFER_SLOT(1));
|
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);
|
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);
|
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));
|
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);
|
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 initialize();
|
||||||
void create();
|
void create();
|
||||||
void destroy();
|
virtual void destroy();
|
||||||
|
|
||||||
virtual void bind_resources() {}
|
virtual void bind_resources() {}
|
||||||
|
|
||||||
@ -343,8 +343,13 @@ namespace gl
|
|||||||
|
|
||||||
struct pixel_buffer_layout;
|
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;
|
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
|
// TODO: Include on use
|
||||||
#include "glutils/buffer_object.h"
|
#include "glutils/buffer_object.h"
|
||||||
#include "glutils/image.h"
|
#include "glutils/image.h"
|
||||||
|
#include "glutils/sampler.h"
|
||||||
#include "glutils/pixel_settings.hpp"
|
#include "glutils/pixel_settings.hpp"
|
||||||
#include "glutils/state_tracker.hpp"
|
#include "glutils/state_tracker.hpp"
|
||||||
|
|
||||||
|
@ -35,28 +35,6 @@ namespace gl
|
|||||||
GLenum primitives = GL_TRIANGLE_STRIP;
|
GLenum primitives = GL_TRIANGLE_STRIP;
|
||||||
GLenum input_filter = GL_NEAREST;
|
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 create();
|
||||||
void destroy();
|
void destroy();
|
||||||
|
|
||||||
|
@ -199,197 +199,6 @@ namespace gl
|
|||||||
return ret;
|
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)
|
std::array<GLenum, 4> get_swizzle_remap(u32 texture_format)
|
||||||
{
|
{
|
||||||
// NOTE: This must be in ARGB order in all forms below.
|
// 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);
|
GLenum get_sized_internal_format(u32 texture_format);
|
||||||
std::tuple<GLenum, GLenum> get_format_type(u32 texture_format);
|
std::tuple<GLenum, GLenum> get_format_type(u32 texture_format);
|
||||||
pixel_buffer_layout get_format_type(texture::internal_format 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);
|
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);
|
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);
|
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
|
namespace debug
|
||||||
{
|
{
|
||||||
extern std::unique_ptr<texture> g_vis_texture;
|
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)
|
if (m_cur_pos != index)
|
||||||
{
|
{
|
||||||
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)
|
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\pixel_settings.hpp" />
|
||||||
<ClInclude Include="Emu\RSX\GL\glutils\program.h" />
|
<ClInclude Include="Emu\RSX\GL\glutils\program.h" />
|
||||||
<ClInclude Include="Emu\RSX\GL\glutils\ring_buffer.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\state_tracker.hpp" />
|
||||||
<ClInclude Include="Emu\RSX\GL\glutils\image.h" />
|
<ClInclude Include="Emu\RSX\GL\glutils\image.h" />
|
||||||
<ClInclude Include="Emu\RSX\GL\glutils\sync.hpp" />
|
<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\program.cpp" />
|
||||||
<ClCompile Include="Emu\RSX\GL\glutils\ring_buffer.cpp" />
|
<ClCompile Include="Emu\RSX\GL\glutils\ring_buffer.cpp" />
|
||||||
<ClCompile Include="Emu\RSX\GL\glutils\image.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\GLVertexProgram.cpp" />
|
||||||
<ClCompile Include="Emu\RSX\GL\GLHelpers.cpp" />
|
<ClCompile Include="Emu\RSX\GL\GLHelpers.cpp" />
|
||||||
<ClCompile Include="Emu\RSX\GL\GLPresent.cpp" />
|
<ClCompile Include="Emu\RSX\GL\GLPresent.cpp" />
|
||||||
|
@ -38,6 +38,9 @@
|
|||||||
<ClCompile Include="Emu\RSX\GL\glutils\program.cpp">
|
<ClCompile Include="Emu\RSX\GL\glutils\program.cpp">
|
||||||
<Filter>glutils</Filter>
|
<Filter>glutils</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="Emu\RSX\GL\glutils\sampler.cpp">
|
||||||
|
<Filter>glutils</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="Emu\RSX\GL\GLTexture.h" />
|
<ClInclude Include="Emu\RSX\GL\GLTexture.h" />
|
||||||
@ -92,6 +95,9 @@
|
|||||||
<ClInclude Include="Emu\RSX\GL\glutils\sync.hpp">
|
<ClInclude Include="Emu\RSX\GL\glutils\sync.hpp">
|
||||||
<Filter>glutils</Filter>
|
<Filter>glutils</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="Emu\RSX\GL\glutils\sampler.h">
|
||||||
|
<Filter>glutils</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Filter Include="glutils">
|
<Filter Include="glutils">
|
||||||
|
Loading…
Reference in New Issue
Block a user