video_core: Add per-image anisotropy heuristics (format & mip count)
This commit is contained in:
parent
0de6b9e3f5
commit
42c944b250
11 changed files with 167 additions and 70 deletions
|
@ -275,9 +275,9 @@ GraphicsPipeline::GraphicsPipeline(const Device& device, TextureCache& texture_c
|
|||
template <typename Spec>
|
||||
void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
|
||||
std::array<VideoCommon::ImageViewInOut, MAX_TEXTURES + MAX_IMAGES> views;
|
||||
std::array<GLuint, MAX_TEXTURES> samplers;
|
||||
std::array<const Sampler*, MAX_TEXTURES> samplers;
|
||||
size_t views_index{};
|
||||
GLsizei sampler_binding{};
|
||||
size_t samplers_index{};
|
||||
|
||||
texture_cache.SynchronizeGraphicsDescriptors();
|
||||
|
||||
|
@ -337,7 +337,6 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
|
|||
for (u32 index = 0; index < desc.count; ++index) {
|
||||
const auto handle{read_handle(desc, index)};
|
||||
views[views_index++] = {handle.first};
|
||||
samplers[sampler_binding++] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -352,7 +351,7 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
|
|||
views[views_index++] = {handle.first};
|
||||
|
||||
Sampler* const sampler{texture_cache.GetGraphicsSampler(handle.second)};
|
||||
samplers[sampler_binding++] = sampler->Handle();
|
||||
samplers[samplers_index++] = sampler;
|
||||
}
|
||||
}
|
||||
if constexpr (Spec::has_images) {
|
||||
|
@ -445,10 +444,13 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
|
|||
program_manager.BindSourcePrograms(source_programs);
|
||||
}
|
||||
const VideoCommon::ImageViewInOut* views_it{views.data()};
|
||||
const Sampler** samplers_it{samplers.data()};
|
||||
GLsizei texture_binding = 0;
|
||||
GLsizei image_binding = 0;
|
||||
GLsizei sampler_binding{};
|
||||
std::array<GLuint, MAX_TEXTURES> textures;
|
||||
std::array<GLuint, MAX_IMAGES> images;
|
||||
std::array<GLuint, MAX_TEXTURES> gl_samplers;
|
||||
const auto prepare_stage{[&](size_t stage) {
|
||||
buffer_cache.runtime.SetImagePointers(&textures[texture_binding], &images[image_binding]);
|
||||
buffer_cache.BindHostStageBuffers(stage);
|
||||
|
@ -465,6 +467,13 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
|
|||
u32 stage_image_binding{};
|
||||
|
||||
const auto& info{stage_infos[stage]};
|
||||
if constexpr (Spec::has_texture_buffers) {
|
||||
for (const auto& desc : info.texture_buffer_descriptors) {
|
||||
for (u32 index = 0; index < desc.count; ++index) {
|
||||
gl_samplers[sampler_binding++] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const auto& desc : info.texture_descriptors) {
|
||||
for (u32 index = 0; index < desc.count; ++index) {
|
||||
ImageView& image_view{texture_cache.GetImageView((views_it++)->id)};
|
||||
|
@ -474,6 +483,12 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
|
|||
}
|
||||
++texture_binding;
|
||||
++stage_texture_binding;
|
||||
|
||||
const Sampler& sampler{**(samplers_it++)};
|
||||
const bool use_fallback_sampler{sampler.HasAddedAnisotropy() &&
|
||||
!image_view.SupportsAnisotropy()};
|
||||
gl_samplers[sampler_binding++] =
|
||||
use_fallback_sampler ? sampler.HandleWithoutAnisotropy() : sampler.Handle();
|
||||
}
|
||||
}
|
||||
for (const auto& desc : info.image_descriptors) {
|
||||
|
@ -534,7 +549,7 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
|
|||
if (texture_binding != 0) {
|
||||
ASSERT(texture_binding == sampler_binding);
|
||||
glBindTextures(0, texture_binding, textures.data());
|
||||
glBindSamplers(0, sampler_binding, samplers.data());
|
||||
glBindSamplers(0, sampler_binding, gl_samplers.data());
|
||||
}
|
||||
if (image_binding != 0) {
|
||||
glBindImageTextures(0, image_binding, images.data());
|
||||
|
|
|
@ -1268,36 +1268,46 @@ Sampler::Sampler(TextureCacheRuntime& runtime, const TSCEntry& config) {
|
|||
|
||||
UNIMPLEMENTED_IF(config.cubemap_anisotropy != 1);
|
||||
|
||||
sampler.Create();
|
||||
const GLuint handle = sampler.handle;
|
||||
glSamplerParameteri(handle, GL_TEXTURE_WRAP_S, MaxwellToGL::WrapMode(config.wrap_u));
|
||||
glSamplerParameteri(handle, GL_TEXTURE_WRAP_T, MaxwellToGL::WrapMode(config.wrap_v));
|
||||
glSamplerParameteri(handle, GL_TEXTURE_WRAP_R, MaxwellToGL::WrapMode(config.wrap_p));
|
||||
glSamplerParameteri(handle, GL_TEXTURE_COMPARE_MODE, compare_mode);
|
||||
glSamplerParameteri(handle, GL_TEXTURE_COMPARE_FUNC, compare_func);
|
||||
glSamplerParameteri(handle, GL_TEXTURE_MAG_FILTER, mag);
|
||||
glSamplerParameteri(handle, GL_TEXTURE_MIN_FILTER, min);
|
||||
glSamplerParameterf(handle, GL_TEXTURE_LOD_BIAS, config.LodBias());
|
||||
glSamplerParameterf(handle, GL_TEXTURE_MIN_LOD, config.MinLod());
|
||||
glSamplerParameterf(handle, GL_TEXTURE_MAX_LOD, config.MaxLod());
|
||||
glSamplerParameterfv(handle, GL_TEXTURE_BORDER_COLOR, config.BorderColor().data());
|
||||
const f32 max_anisotropy = std::clamp(config.MaxAnisotropy(), 1.0f, 16.0f);
|
||||
|
||||
if (GLAD_GL_ARB_texture_filter_anisotropic || GLAD_GL_EXT_texture_filter_anisotropic) {
|
||||
const f32 max_anisotropy = std::clamp(config.MaxAnisotropy(), 1.0f, 16.0f);
|
||||
glSamplerParameterf(handle, GL_TEXTURE_MAX_ANISOTROPY, max_anisotropy);
|
||||
} else {
|
||||
LOG_WARNING(Render_OpenGL, "GL_ARB_texture_filter_anisotropic is required");
|
||||
}
|
||||
if (GLAD_GL_ARB_texture_filter_minmax || GLAD_GL_EXT_texture_filter_minmax) {
|
||||
glSamplerParameteri(handle, GL_TEXTURE_REDUCTION_MODE_ARB, reduction_filter);
|
||||
} else if (reduction_filter != GL_WEIGHTED_AVERAGE_ARB) {
|
||||
LOG_WARNING(Render_OpenGL, "GL_ARB_texture_filter_minmax is required");
|
||||
}
|
||||
if (GLAD_GL_ARB_seamless_cubemap_per_texture || GLAD_GL_AMD_seamless_cubemap_per_texture) {
|
||||
glSamplerParameteri(handle, GL_TEXTURE_CUBE_MAP_SEAMLESS, seamless);
|
||||
} else if (seamless == GL_FALSE) {
|
||||
// We default to false because it's more common
|
||||
LOG_WARNING(Render_OpenGL, "GL_ARB_seamless_cubemap_per_texture is required");
|
||||
const auto create_sampler = [&](const f32 max_anisotropy) {
|
||||
OGLSampler sampler;
|
||||
sampler.Create();
|
||||
const GLuint handle = sampler.handle;
|
||||
glSamplerParameteri(handle, GL_TEXTURE_WRAP_S, MaxwellToGL::WrapMode(config.wrap_u));
|
||||
glSamplerParameteri(handle, GL_TEXTURE_WRAP_T, MaxwellToGL::WrapMode(config.wrap_v));
|
||||
glSamplerParameteri(handle, GL_TEXTURE_WRAP_R, MaxwellToGL::WrapMode(config.wrap_p));
|
||||
glSamplerParameteri(handle, GL_TEXTURE_COMPARE_MODE, compare_mode);
|
||||
glSamplerParameteri(handle, GL_TEXTURE_COMPARE_FUNC, compare_func);
|
||||
glSamplerParameteri(handle, GL_TEXTURE_MAG_FILTER, mag);
|
||||
glSamplerParameteri(handle, GL_TEXTURE_MIN_FILTER, min);
|
||||
glSamplerParameterf(handle, GL_TEXTURE_LOD_BIAS, config.LodBias());
|
||||
glSamplerParameterf(handle, GL_TEXTURE_MIN_LOD, config.MinLod());
|
||||
glSamplerParameterf(handle, GL_TEXTURE_MAX_LOD, config.MaxLod());
|
||||
glSamplerParameterfv(handle, GL_TEXTURE_BORDER_COLOR, config.BorderColor().data());
|
||||
|
||||
if (GLAD_GL_ARB_texture_filter_anisotropic || GLAD_GL_EXT_texture_filter_anisotropic) {
|
||||
glSamplerParameterf(handle, GL_TEXTURE_MAX_ANISOTROPY, max_anisotropy);
|
||||
} else {
|
||||
LOG_WARNING(Render_OpenGL, "GL_ARB_texture_filter_anisotropic is required");
|
||||
}
|
||||
if (GLAD_GL_ARB_texture_filter_minmax || GLAD_GL_EXT_texture_filter_minmax) {
|
||||
glSamplerParameteri(handle, GL_TEXTURE_REDUCTION_MODE_ARB, reduction_filter);
|
||||
} else if (reduction_filter != GL_WEIGHTED_AVERAGE_ARB) {
|
||||
LOG_WARNING(Render_OpenGL, "GL_ARB_texture_filter_minmax is required");
|
||||
}
|
||||
if (GLAD_GL_ARB_seamless_cubemap_per_texture || GLAD_GL_AMD_seamless_cubemap_per_texture) {
|
||||
glSamplerParameteri(handle, GL_TEXTURE_CUBE_MAP_SEAMLESS, seamless);
|
||||
} else if (seamless == GL_FALSE) {
|
||||
// We default to false because it's more common
|
||||
LOG_WARNING(Render_OpenGL, "GL_ARB_seamless_cubemap_per_texture is required");
|
||||
}
|
||||
return sampler;
|
||||
};
|
||||
|
||||
sampler = create_sampler(max_anisotropy);
|
||||
if (Settings::values.max_anisotropy.GetValue() > 0 && max_anisotropy > 1.0f) {
|
||||
sampler_without_anisotropy = create_sampler(1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -309,12 +309,21 @@ class Sampler {
|
|||
public:
|
||||
explicit Sampler(TextureCacheRuntime&, const Tegra::Texture::TSCEntry&);
|
||||
|
||||
GLuint Handle() const noexcept {
|
||||
[[nodiscard]] GLuint Handle() const noexcept {
|
||||
return sampler.handle;
|
||||
}
|
||||
|
||||
[[nodiscard]] GLuint HandleWithoutAnisotropy() const noexcept {
|
||||
return sampler_without_anisotropy.handle;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool HasAddedAnisotropy() const noexcept {
|
||||
return static_cast<bool>(sampler_without_anisotropy.handle);
|
||||
}
|
||||
|
||||
private:
|
||||
OGLSampler sampler;
|
||||
OGLSampler sampler_without_anisotropy;
|
||||
};
|
||||
|
||||
class Framebuffer {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue