diff options
| author | 2023-06-18 00:02:05 +0200 | |
|---|---|---|
| committer | 2023-06-18 00:02:05 +0200 | |
| commit | 27a36cd51bbc832b0b73cbbaef6bd8453368a38d (patch) | |
| tree | 00a30700c65665e2eaf2b02f03d73585c4d4f790 /src/video_core/renderer_opengl | |
| parent | Merge pull request #10783 from liamwhite/memory (diff) | |
| parent | video_core: Only apply AF to 2D (array) image types (diff) | |
| download | yuzu-27a36cd51bbc832b0b73cbbaef6bd8453368a38d.tar.gz yuzu-27a36cd51bbc832b0b73cbbaef6bd8453368a38d.tar.xz yuzu-27a36cd51bbc832b0b73cbbaef6bd8453368a38d.zip | |
Merge pull request #10744 from Wollnashorn/af-for-all
video_core: Improved anisotropic filtering heuristics
Diffstat (limited to 'src/video_core/renderer_opengl')
4 files changed, 91 insertions, 42 deletions
diff --git a/src/video_core/renderer_opengl/gl_compute_pipeline.cpp b/src/video_core/renderer_opengl/gl_compute_pipeline.cpp index 1a0cea9b7..3151c0db8 100644 --- a/src/video_core/renderer_opengl/gl_compute_pipeline.cpp +++ b/src/video_core/renderer_opengl/gl_compute_pipeline.cpp | |||
| @@ -87,7 +87,8 @@ void ComputePipeline::Configure() { | |||
| 87 | texture_cache.SynchronizeComputeDescriptors(); | 87 | texture_cache.SynchronizeComputeDescriptors(); |
| 88 | 88 | ||
| 89 | boost::container::static_vector<VideoCommon::ImageViewInOut, MAX_TEXTURES + MAX_IMAGES> views; | 89 | boost::container::static_vector<VideoCommon::ImageViewInOut, MAX_TEXTURES + MAX_IMAGES> views; |
| 90 | std::array<GLuint, MAX_TEXTURES> samplers; | 90 | boost::container::static_vector<VideoCommon::SamplerId, MAX_TEXTURES> samplers; |
| 91 | std::array<GLuint, MAX_TEXTURES> gl_samplers; | ||
| 91 | std::array<GLuint, MAX_TEXTURES> textures; | 92 | std::array<GLuint, MAX_TEXTURES> textures; |
| 92 | std::array<GLuint, MAX_IMAGES> images; | 93 | std::array<GLuint, MAX_IMAGES> images; |
| 93 | GLsizei sampler_binding{}; | 94 | GLsizei sampler_binding{}; |
| @@ -131,7 +132,6 @@ void ComputePipeline::Configure() { | |||
| 131 | for (u32 index = 0; index < desc.count; ++index) { | 132 | for (u32 index = 0; index < desc.count; ++index) { |
| 132 | const auto handle{read_handle(desc, index)}; | 133 | const auto handle{read_handle(desc, index)}; |
| 133 | views.push_back({handle.first}); | 134 | views.push_back({handle.first}); |
| 134 | samplers[sampler_binding++] = 0; | ||
| 135 | } | 135 | } |
| 136 | } | 136 | } |
| 137 | for (const auto& desc : info.image_buffer_descriptors) { | 137 | for (const auto& desc : info.image_buffer_descriptors) { |
| @@ -142,8 +142,8 @@ void ComputePipeline::Configure() { | |||
| 142 | const auto handle{read_handle(desc, index)}; | 142 | const auto handle{read_handle(desc, index)}; |
| 143 | views.push_back({handle.first}); | 143 | views.push_back({handle.first}); |
| 144 | 144 | ||
| 145 | Sampler* const sampler = texture_cache.GetComputeSampler(handle.second); | 145 | VideoCommon::SamplerId sampler = texture_cache.GetComputeSamplerId(handle.second); |
| 146 | samplers[sampler_binding++] = sampler->Handle(); | 146 | samplers.push_back(sampler); |
| 147 | } | 147 | } |
| 148 | } | 148 | } |
| 149 | for (const auto& desc : info.image_descriptors) { | 149 | for (const auto& desc : info.image_descriptors) { |
| @@ -186,10 +186,17 @@ void ComputePipeline::Configure() { | |||
| 186 | 186 | ||
| 187 | const VideoCommon::ImageViewInOut* views_it{views.data() + num_texture_buffers + | 187 | const VideoCommon::ImageViewInOut* views_it{views.data() + num_texture_buffers + |
| 188 | num_image_buffers}; | 188 | num_image_buffers}; |
| 189 | const VideoCommon::SamplerId* samplers_it{samplers.data()}; | ||
| 189 | texture_binding += num_texture_buffers; | 190 | texture_binding += num_texture_buffers; |
| 190 | image_binding += num_image_buffers; | 191 | image_binding += num_image_buffers; |
| 191 | 192 | ||
| 192 | u32 texture_scaling_mask{}; | 193 | u32 texture_scaling_mask{}; |
| 194 | |||
| 195 | for (const auto& desc : info.texture_buffer_descriptors) { | ||
| 196 | for (u32 index = 0; index < desc.count; ++index) { | ||
| 197 | gl_samplers[sampler_binding++] = 0; | ||
| 198 | } | ||
| 199 | } | ||
| 193 | for (const auto& desc : info.texture_descriptors) { | 200 | for (const auto& desc : info.texture_descriptors) { |
| 194 | for (u32 index = 0; index < desc.count; ++index) { | 201 | for (u32 index = 0; index < desc.count; ++index) { |
| 195 | ImageView& image_view{texture_cache.GetImageView((views_it++)->id)}; | 202 | ImageView& image_view{texture_cache.GetImageView((views_it++)->id)}; |
| @@ -198,6 +205,12 @@ void ComputePipeline::Configure() { | |||
| 198 | texture_scaling_mask |= 1u << texture_binding; | 205 | texture_scaling_mask |= 1u << texture_binding; |
| 199 | } | 206 | } |
| 200 | ++texture_binding; | 207 | ++texture_binding; |
| 208 | |||
| 209 | const Sampler& sampler{texture_cache.GetSampler(*(samplers_it++))}; | ||
| 210 | const bool use_fallback_sampler{sampler.HasAddedAnisotropy() && | ||
| 211 | !image_view.SupportsAnisotropy()}; | ||
| 212 | gl_samplers[sampler_binding++] = | ||
| 213 | use_fallback_sampler ? sampler.HandleWithDefaultAnisotropy() : sampler.Handle(); | ||
| 201 | } | 214 | } |
| 202 | } | 215 | } |
| 203 | u32 image_scaling_mask{}; | 216 | u32 image_scaling_mask{}; |
| @@ -228,7 +241,7 @@ void ComputePipeline::Configure() { | |||
| 228 | if (texture_binding != 0) { | 241 | if (texture_binding != 0) { |
| 229 | ASSERT(texture_binding == sampler_binding); | 242 | ASSERT(texture_binding == sampler_binding); |
| 230 | glBindTextures(0, texture_binding, textures.data()); | 243 | glBindTextures(0, texture_binding, textures.data()); |
| 231 | glBindSamplers(0, sampler_binding, samplers.data()); | 244 | glBindSamplers(0, sampler_binding, gl_samplers.data()); |
| 232 | } | 245 | } |
| 233 | if (image_binding != 0) { | 246 | if (image_binding != 0) { |
| 234 | glBindImageTextures(0, image_binding, images.data()); | 247 | glBindImageTextures(0, image_binding, images.data()); |
diff --git a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp index 89000d6e0..c58f760b8 100644 --- a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp +++ b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp | |||
| @@ -275,9 +275,9 @@ GraphicsPipeline::GraphicsPipeline(const Device& device, TextureCache& texture_c | |||
| 275 | template <typename Spec> | 275 | template <typename Spec> |
| 276 | void GraphicsPipeline::ConfigureImpl(bool is_indexed) { | 276 | void GraphicsPipeline::ConfigureImpl(bool is_indexed) { |
| 277 | std::array<VideoCommon::ImageViewInOut, MAX_TEXTURES + MAX_IMAGES> views; | 277 | std::array<VideoCommon::ImageViewInOut, MAX_TEXTURES + MAX_IMAGES> views; |
| 278 | std::array<GLuint, MAX_TEXTURES> samplers; | 278 | std::array<VideoCommon::SamplerId, MAX_TEXTURES> samplers; |
| 279 | size_t views_index{}; | 279 | size_t views_index{}; |
| 280 | GLsizei sampler_binding{}; | 280 | size_t samplers_index{}; |
| 281 | 281 | ||
| 282 | texture_cache.SynchronizeGraphicsDescriptors(); | 282 | texture_cache.SynchronizeGraphicsDescriptors(); |
| 283 | 283 | ||
| @@ -337,7 +337,6 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { | |||
| 337 | for (u32 index = 0; index < desc.count; ++index) { | 337 | for (u32 index = 0; index < desc.count; ++index) { |
| 338 | const auto handle{read_handle(desc, index)}; | 338 | const auto handle{read_handle(desc, index)}; |
| 339 | views[views_index++] = {handle.first}; | 339 | views[views_index++] = {handle.first}; |
| 340 | samplers[sampler_binding++] = 0; | ||
| 341 | } | 340 | } |
| 342 | } | 341 | } |
| 343 | } | 342 | } |
| @@ -351,8 +350,8 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { | |||
| 351 | const auto handle{read_handle(desc, index)}; | 350 | const auto handle{read_handle(desc, index)}; |
| 352 | views[views_index++] = {handle.first}; | 351 | views[views_index++] = {handle.first}; |
| 353 | 352 | ||
| 354 | Sampler* const sampler{texture_cache.GetGraphicsSampler(handle.second)}; | 353 | VideoCommon::SamplerId sampler{texture_cache.GetGraphicsSamplerId(handle.second)}; |
| 355 | samplers[sampler_binding++] = sampler->Handle(); | 354 | samplers[samplers_index++] = sampler; |
| 356 | } | 355 | } |
| 357 | } | 356 | } |
| 358 | if constexpr (Spec::has_images) { | 357 | if constexpr (Spec::has_images) { |
| @@ -445,10 +444,13 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { | |||
| 445 | program_manager.BindSourcePrograms(source_programs); | 444 | program_manager.BindSourcePrograms(source_programs); |
| 446 | } | 445 | } |
| 447 | const VideoCommon::ImageViewInOut* views_it{views.data()}; | 446 | const VideoCommon::ImageViewInOut* views_it{views.data()}; |
| 447 | const VideoCommon::SamplerId* samplers_it{samplers.data()}; | ||
| 448 | GLsizei texture_binding = 0; | 448 | GLsizei texture_binding = 0; |
| 449 | GLsizei image_binding = 0; | 449 | GLsizei image_binding = 0; |
| 450 | GLsizei sampler_binding{}; | ||
| 450 | std::array<GLuint, MAX_TEXTURES> textures; | 451 | std::array<GLuint, MAX_TEXTURES> textures; |
| 451 | std::array<GLuint, MAX_IMAGES> images; | 452 | std::array<GLuint, MAX_IMAGES> images; |
| 453 | std::array<GLuint, MAX_TEXTURES> gl_samplers; | ||
| 452 | const auto prepare_stage{[&](size_t stage) { | 454 | const auto prepare_stage{[&](size_t stage) { |
| 453 | buffer_cache.runtime.SetImagePointers(&textures[texture_binding], &images[image_binding]); | 455 | buffer_cache.runtime.SetImagePointers(&textures[texture_binding], &images[image_binding]); |
| 454 | buffer_cache.BindHostStageBuffers(stage); | 456 | buffer_cache.BindHostStageBuffers(stage); |
| @@ -465,6 +467,13 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { | |||
| 465 | u32 stage_image_binding{}; | 467 | u32 stage_image_binding{}; |
| 466 | 468 | ||
| 467 | const auto& info{stage_infos[stage]}; | 469 | const auto& info{stage_infos[stage]}; |
| 470 | if constexpr (Spec::has_texture_buffers) { | ||
| 471 | for (const auto& desc : info.texture_buffer_descriptors) { | ||
| 472 | for (u32 index = 0; index < desc.count; ++index) { | ||
| 473 | gl_samplers[sampler_binding++] = 0; | ||
| 474 | } | ||
| 475 | } | ||
| 476 | } | ||
| 468 | for (const auto& desc : info.texture_descriptors) { | 477 | for (const auto& desc : info.texture_descriptors) { |
| 469 | for (u32 index = 0; index < desc.count; ++index) { | 478 | for (u32 index = 0; index < desc.count; ++index) { |
| 470 | ImageView& image_view{texture_cache.GetImageView((views_it++)->id)}; | 479 | ImageView& image_view{texture_cache.GetImageView((views_it++)->id)}; |
| @@ -474,6 +483,12 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { | |||
| 474 | } | 483 | } |
| 475 | ++texture_binding; | 484 | ++texture_binding; |
| 476 | ++stage_texture_binding; | 485 | ++stage_texture_binding; |
| 486 | |||
| 487 | const Sampler& sampler{texture_cache.GetSampler(*(samplers_it++))}; | ||
| 488 | const bool use_fallback_sampler{sampler.HasAddedAnisotropy() && | ||
| 489 | !image_view.SupportsAnisotropy()}; | ||
| 490 | gl_samplers[sampler_binding++] = | ||
| 491 | use_fallback_sampler ? sampler.HandleWithDefaultAnisotropy() : sampler.Handle(); | ||
| 477 | } | 492 | } |
| 478 | } | 493 | } |
| 479 | for (const auto& desc : info.image_descriptors) { | 494 | for (const auto& desc : info.image_descriptors) { |
| @@ -534,7 +549,7 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { | |||
| 534 | if (texture_binding != 0) { | 549 | if (texture_binding != 0) { |
| 535 | ASSERT(texture_binding == sampler_binding); | 550 | ASSERT(texture_binding == sampler_binding); |
| 536 | glBindTextures(0, texture_binding, textures.data()); | 551 | glBindTextures(0, texture_binding, textures.data()); |
| 537 | glBindSamplers(0, sampler_binding, samplers.data()); | 552 | glBindSamplers(0, sampler_binding, gl_samplers.data()); |
| 538 | } | 553 | } |
| 539 | if (image_binding != 0) { | 554 | if (image_binding != 0) { |
| 540 | glBindImageTextures(0, image_binding, images.data()); | 555 | glBindImageTextures(0, image_binding, images.data()); |
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp index 1c5dbcdd8..3b446be07 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.cpp +++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp | |||
| @@ -1268,36 +1268,48 @@ Sampler::Sampler(TextureCacheRuntime& runtime, const TSCEntry& config) { | |||
| 1268 | 1268 | ||
| 1269 | UNIMPLEMENTED_IF(config.cubemap_anisotropy != 1); | 1269 | UNIMPLEMENTED_IF(config.cubemap_anisotropy != 1); |
| 1270 | 1270 | ||
| 1271 | sampler.Create(); | 1271 | const f32 max_anisotropy = std::clamp(config.MaxAnisotropy(), 1.0f, 16.0f); |
| 1272 | const GLuint handle = sampler.handle; | 1272 | |
| 1273 | glSamplerParameteri(handle, GL_TEXTURE_WRAP_S, MaxwellToGL::WrapMode(config.wrap_u)); | 1273 | const auto create_sampler = [&](const f32 anisotropy) { |
| 1274 | glSamplerParameteri(handle, GL_TEXTURE_WRAP_T, MaxwellToGL::WrapMode(config.wrap_v)); | 1274 | OGLSampler new_sampler; |
| 1275 | glSamplerParameteri(handle, GL_TEXTURE_WRAP_R, MaxwellToGL::WrapMode(config.wrap_p)); | 1275 | new_sampler.Create(); |
| 1276 | glSamplerParameteri(handle, GL_TEXTURE_COMPARE_MODE, compare_mode); | 1276 | const GLuint handle = new_sampler.handle; |
| 1277 | glSamplerParameteri(handle, GL_TEXTURE_COMPARE_FUNC, compare_func); | 1277 | glSamplerParameteri(handle, GL_TEXTURE_WRAP_S, MaxwellToGL::WrapMode(config.wrap_u)); |
| 1278 | glSamplerParameteri(handle, GL_TEXTURE_MAG_FILTER, mag); | 1278 | glSamplerParameteri(handle, GL_TEXTURE_WRAP_T, MaxwellToGL::WrapMode(config.wrap_v)); |
| 1279 | glSamplerParameteri(handle, GL_TEXTURE_MIN_FILTER, min); | 1279 | glSamplerParameteri(handle, GL_TEXTURE_WRAP_R, MaxwellToGL::WrapMode(config.wrap_p)); |
| 1280 | glSamplerParameterf(handle, GL_TEXTURE_LOD_BIAS, config.LodBias()); | 1280 | glSamplerParameteri(handle, GL_TEXTURE_COMPARE_MODE, compare_mode); |
| 1281 | glSamplerParameterf(handle, GL_TEXTURE_MIN_LOD, config.MinLod()); | 1281 | glSamplerParameteri(handle, GL_TEXTURE_COMPARE_FUNC, compare_func); |
| 1282 | glSamplerParameterf(handle, GL_TEXTURE_MAX_LOD, config.MaxLod()); | 1282 | glSamplerParameteri(handle, GL_TEXTURE_MAG_FILTER, mag); |
| 1283 | glSamplerParameterfv(handle, GL_TEXTURE_BORDER_COLOR, config.BorderColor().data()); | 1283 | glSamplerParameteri(handle, GL_TEXTURE_MIN_FILTER, min); |
| 1284 | 1284 | glSamplerParameterf(handle, GL_TEXTURE_LOD_BIAS, config.LodBias()); | |
| 1285 | if (GLAD_GL_ARB_texture_filter_anisotropic || GLAD_GL_EXT_texture_filter_anisotropic) { | 1285 | glSamplerParameterf(handle, GL_TEXTURE_MIN_LOD, config.MinLod()); |
| 1286 | const f32 max_anisotropy = std::clamp(config.MaxAnisotropy(), 1.0f, 16.0f); | 1286 | glSamplerParameterf(handle, GL_TEXTURE_MAX_LOD, config.MaxLod()); |
| 1287 | glSamplerParameterf(handle, GL_TEXTURE_MAX_ANISOTROPY, max_anisotropy); | 1287 | glSamplerParameterfv(handle, GL_TEXTURE_BORDER_COLOR, config.BorderColor().data()); |
| 1288 | } else { | 1288 | |
| 1289 | LOG_WARNING(Render_OpenGL, "GL_ARB_texture_filter_anisotropic is required"); | 1289 | if (GLAD_GL_ARB_texture_filter_anisotropic || GLAD_GL_EXT_texture_filter_anisotropic) { |
| 1290 | } | 1290 | glSamplerParameterf(handle, GL_TEXTURE_MAX_ANISOTROPY, anisotropy); |
| 1291 | if (GLAD_GL_ARB_texture_filter_minmax || GLAD_GL_EXT_texture_filter_minmax) { | 1291 | } else { |
| 1292 | glSamplerParameteri(handle, GL_TEXTURE_REDUCTION_MODE_ARB, reduction_filter); | 1292 | LOG_WARNING(Render_OpenGL, "GL_ARB_texture_filter_anisotropic is required"); |
| 1293 | } else if (reduction_filter != GL_WEIGHTED_AVERAGE_ARB) { | 1293 | } |
| 1294 | LOG_WARNING(Render_OpenGL, "GL_ARB_texture_filter_minmax is required"); | 1294 | if (GLAD_GL_ARB_texture_filter_minmax || GLAD_GL_EXT_texture_filter_minmax) { |
| 1295 | } | 1295 | glSamplerParameteri(handle, GL_TEXTURE_REDUCTION_MODE_ARB, reduction_filter); |
| 1296 | if (GLAD_GL_ARB_seamless_cubemap_per_texture || GLAD_GL_AMD_seamless_cubemap_per_texture) { | 1296 | } else if (reduction_filter != GL_WEIGHTED_AVERAGE_ARB) { |
| 1297 | glSamplerParameteri(handle, GL_TEXTURE_CUBE_MAP_SEAMLESS, seamless); | 1297 | LOG_WARNING(Render_OpenGL, "GL_ARB_texture_filter_minmax is required"); |
| 1298 | } else if (seamless == GL_FALSE) { | 1298 | } |
| 1299 | // We default to false because it's more common | 1299 | if (GLAD_GL_ARB_seamless_cubemap_per_texture || GLAD_GL_AMD_seamless_cubemap_per_texture) { |
| 1300 | LOG_WARNING(Render_OpenGL, "GL_ARB_seamless_cubemap_per_texture is required"); | 1300 | glSamplerParameteri(handle, GL_TEXTURE_CUBE_MAP_SEAMLESS, seamless); |
| 1301 | } else if (seamless == GL_FALSE) { | ||
| 1302 | // We default to false because it's more common | ||
| 1303 | LOG_WARNING(Render_OpenGL, "GL_ARB_seamless_cubemap_per_texture is required"); | ||
| 1304 | } | ||
| 1305 | return new_sampler; | ||
| 1306 | }; | ||
| 1307 | |||
| 1308 | sampler = create_sampler(max_anisotropy); | ||
| 1309 | |||
| 1310 | const f32 max_anisotropy_default = static_cast<f32>(1U << config.max_anisotropy); | ||
| 1311 | if (max_anisotropy > max_anisotropy_default) { | ||
| 1312 | sampler_default_anisotropy = create_sampler(max_anisotropy_default); | ||
| 1301 | } | 1313 | } |
| 1302 | } | 1314 | } |
| 1303 | 1315 | ||
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h index 1148b73d7..3676eaaa9 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.h +++ b/src/video_core/renderer_opengl/gl_texture_cache.h | |||
| @@ -309,12 +309,21 @@ class Sampler { | |||
| 309 | public: | 309 | public: |
| 310 | explicit Sampler(TextureCacheRuntime&, const Tegra::Texture::TSCEntry&); | 310 | explicit Sampler(TextureCacheRuntime&, const Tegra::Texture::TSCEntry&); |
| 311 | 311 | ||
| 312 | GLuint Handle() const noexcept { | 312 | [[nodiscard]] GLuint Handle() const noexcept { |
| 313 | return sampler.handle; | 313 | return sampler.handle; |
| 314 | } | 314 | } |
| 315 | 315 | ||
| 316 | [[nodiscard]] GLuint HandleWithDefaultAnisotropy() const noexcept { | ||
| 317 | return sampler_default_anisotropy.handle; | ||
| 318 | } | ||
| 319 | |||
| 320 | [[nodiscard]] bool HasAddedAnisotropy() const noexcept { | ||
| 321 | return static_cast<bool>(sampler_default_anisotropy.handle); | ||
| 322 | } | ||
| 323 | |||
| 316 | private: | 324 | private: |
| 317 | OGLSampler sampler; | 325 | OGLSampler sampler; |
| 326 | OGLSampler sampler_default_anisotropy; | ||
| 318 | }; | 327 | }; |
| 319 | 328 | ||
| 320 | class Framebuffer { | 329 | class Framebuffer { |