diff options
| author | 2023-06-15 18:19:32 +0200 | |
|---|---|---|
| committer | 2023-06-15 18:19:32 +0200 | |
| commit | 42c944b250d8d5c8147b24b3a453cba29968d46c (patch) | |
| tree | 6d156e8247219bf373edd848bd3a89bbd32eb546 /src | |
| parent | video_core: Apply AF only to samplers with normal LOD range [0, 1+x] (diff) | |
| download | yuzu-42c944b250d8d5c8147b24b3a453cba29968d46c.tar.gz yuzu-42c944b250d8d5c8147b24b3a453cba29968d46c.tar.xz yuzu-42c944b250d8d5c8147b24b3a453cba29968d46c.zip | |
video_core: Add per-image anisotropy heuristics (format & mip count)
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/renderer_opengl/gl_graphics_pipeline.cpp | 25 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_texture_cache.cpp | 70 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_texture_cache.h | 11 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/pipeline_helper.h | 10 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_compute_pipeline.cpp | 6 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp | 6 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_texture_cache.cpp | 49 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_texture_cache.h | 9 | ||||
| -rw-r--r-- | src/video_core/texture_cache/image_view_base.cpp | 39 | ||||
| -rw-r--r-- | src/video_core/texture_cache/image_view_base.h | 2 | ||||
| -rw-r--r-- | src/video_core/textures/texture.cpp | 12 |
11 files changed, 168 insertions, 71 deletions
diff --git a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp index 89000d6e0..0fa0fc594 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<const Sampler*, 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 | } |
| @@ -352,7 +351,7 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { | |||
| 352 | views[views_index++] = {handle.first}; | 351 | views[views_index++] = {handle.first}; |
| 353 | 352 | ||
| 354 | Sampler* const sampler{texture_cache.GetGraphicsSampler(handle.second)}; | 353 | Sampler* const sampler{texture_cache.GetGraphicsSampler(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 Sampler** 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{**(samplers_it++)}; | ||
| 488 | const bool use_fallback_sampler{sampler.HasAddedAnisotropy() && | ||
| 489 | !image_view.SupportsAnisotropy()}; | ||
| 490 | gl_samplers[sampler_binding++] = | ||
| 491 | use_fallback_sampler ? sampler.HandleWithoutAnisotropy() : 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..ee5a0c723 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.cpp +++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp | |||
| @@ -1268,36 +1268,46 @@ 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 max_anisotropy) { |
| 1274 | glSamplerParameteri(handle, GL_TEXTURE_WRAP_T, MaxwellToGL::WrapMode(config.wrap_v)); | 1274 | OGLSampler sampler; |
| 1275 | glSamplerParameteri(handle, GL_TEXTURE_WRAP_R, MaxwellToGL::WrapMode(config.wrap_p)); | 1275 | sampler.Create(); |
| 1276 | glSamplerParameteri(handle, GL_TEXTURE_COMPARE_MODE, compare_mode); | 1276 | const GLuint handle = 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, max_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 sampler; | ||
| 1306 | }; | ||
| 1307 | |||
| 1308 | sampler = create_sampler(max_anisotropy); | ||
| 1309 | if (Settings::values.max_anisotropy.GetValue() > 0 && max_anisotropy > 1.0f) { | ||
| 1310 | sampler_without_anisotropy = create_sampler(1.0f); | ||
| 1301 | } | 1311 | } |
| 1302 | } | 1312 | } |
| 1303 | 1313 | ||
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h index 1148b73d7..82756fca7 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 HandleWithoutAnisotropy() const noexcept { | ||
| 317 | return sampler_without_anisotropy.handle; | ||
| 318 | } | ||
| 319 | |||
| 320 | [[nodiscard]] bool HasAddedAnisotropy() const noexcept { | ||
| 321 | return static_cast<bool>(sampler_without_anisotropy.handle); | ||
| 322 | } | ||
| 323 | |||
| 316 | private: | 324 | private: |
| 317 | OGLSampler sampler; | 325 | OGLSampler sampler; |
| 326 | OGLSampler sampler_without_anisotropy; | ||
| 318 | }; | 327 | }; |
| 319 | 328 | ||
| 320 | class Framebuffer { | 329 | class Framebuffer { |
diff --git a/src/video_core/renderer_vulkan/pipeline_helper.h b/src/video_core/renderer_vulkan/pipeline_helper.h index 983e1c2e1..1632a6f26 100644 --- a/src/video_core/renderer_vulkan/pipeline_helper.h +++ b/src/video_core/renderer_vulkan/pipeline_helper.h | |||
| @@ -178,7 +178,7 @@ public: | |||
| 178 | inline void PushImageDescriptors(TextureCache& texture_cache, | 178 | inline void PushImageDescriptors(TextureCache& texture_cache, |
| 179 | GuestDescriptorQueue& guest_descriptor_queue, | 179 | GuestDescriptorQueue& guest_descriptor_queue, |
| 180 | const Shader::Info& info, RescalingPushConstant& rescaling, | 180 | const Shader::Info& info, RescalingPushConstant& rescaling, |
| 181 | const VkSampler*& samplers, | 181 | const Sampler**& samplers, |
| 182 | const VideoCommon::ImageViewInOut*& views) { | 182 | const VideoCommon::ImageViewInOut*& views) { |
| 183 | const u32 num_texture_buffers = Shader::NumDescriptors(info.texture_buffer_descriptors); | 183 | const u32 num_texture_buffers = Shader::NumDescriptors(info.texture_buffer_descriptors); |
| 184 | const u32 num_image_buffers = Shader::NumDescriptors(info.image_buffer_descriptors); | 184 | const u32 num_image_buffers = Shader::NumDescriptors(info.image_buffer_descriptors); |
| @@ -187,10 +187,14 @@ inline void PushImageDescriptors(TextureCache& texture_cache, | |||
| 187 | for (const auto& desc : info.texture_descriptors) { | 187 | for (const auto& desc : info.texture_descriptors) { |
| 188 | for (u32 index = 0; index < desc.count; ++index) { | 188 | for (u32 index = 0; index < desc.count; ++index) { |
| 189 | const VideoCommon::ImageViewId image_view_id{(views++)->id}; | 189 | const VideoCommon::ImageViewId image_view_id{(views++)->id}; |
| 190 | const VkSampler sampler{*(samplers++)}; | ||
| 191 | ImageView& image_view{texture_cache.GetImageView(image_view_id)}; | 190 | ImageView& image_view{texture_cache.GetImageView(image_view_id)}; |
| 192 | const VkImageView vk_image_view{image_view.Handle(desc.type)}; | 191 | const VkImageView vk_image_view{image_view.Handle(desc.type)}; |
| 193 | guest_descriptor_queue.AddSampledImage(vk_image_view, sampler); | 192 | const Sampler& sampler{**(samplers++)}; |
| 193 | const bool use_fallback_sampler{sampler.HasAddedAnisotropy() && | ||
| 194 | !image_view.SupportsAnisotropy()}; | ||
| 195 | const VkSampler vk_sampler{use_fallback_sampler ? sampler.HandleWithoutAnisotropy() | ||
| 196 | : sampler.Handle()}; | ||
| 197 | guest_descriptor_queue.AddSampledImage(vk_image_view, vk_sampler); | ||
| 194 | rescaling.PushTexture(texture_cache.IsRescaling(image_view)); | 198 | rescaling.PushTexture(texture_cache.IsRescaling(image_view)); |
| 195 | } | 199 | } |
| 196 | } | 200 | } |
diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp index 733e70d9d..eb292dc34 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp | |||
| @@ -115,7 +115,7 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute, | |||
| 115 | 115 | ||
| 116 | static constexpr size_t max_elements = 64; | 116 | static constexpr size_t max_elements = 64; |
| 117 | boost::container::static_vector<VideoCommon::ImageViewInOut, max_elements> views; | 117 | boost::container::static_vector<VideoCommon::ImageViewInOut, max_elements> views; |
| 118 | boost::container::static_vector<VkSampler, max_elements> samplers; | 118 | boost::container::static_vector<const Sampler*, max_elements> samplers; |
| 119 | 119 | ||
| 120 | const auto& qmd{kepler_compute.launch_description}; | 120 | const auto& qmd{kepler_compute.launch_description}; |
| 121 | const auto& cbufs{qmd.const_buffer_config}; | 121 | const auto& cbufs{qmd.const_buffer_config}; |
| @@ -161,7 +161,7 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute, | |||
| 161 | views.push_back({handle.first}); | 161 | views.push_back({handle.first}); |
| 162 | 162 | ||
| 163 | Sampler* const sampler = texture_cache.GetComputeSampler(handle.second); | 163 | Sampler* const sampler = texture_cache.GetComputeSampler(handle.second); |
| 164 | samplers.push_back(sampler->Handle()); | 164 | samplers.push_back(sampler); |
| 165 | } | 165 | } |
| 166 | } | 166 | } |
| 167 | for (const auto& desc : info.image_descriptors) { | 167 | for (const auto& desc : info.image_descriptors) { |
| @@ -192,7 +192,7 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute, | |||
| 192 | buffer_cache.BindHostComputeBuffers(); | 192 | buffer_cache.BindHostComputeBuffers(); |
| 193 | 193 | ||
| 194 | RescalingPushConstant rescaling; | 194 | RescalingPushConstant rescaling; |
| 195 | const VkSampler* samplers_it{samplers.data()}; | 195 | const Sampler** samplers_it{samplers.data()}; |
| 196 | const VideoCommon::ImageViewInOut* views_it{views.data()}; | 196 | const VideoCommon::ImageViewInOut* views_it{views.data()}; |
| 197 | PushImageDescriptors(texture_cache, guest_descriptor_queue, info, rescaling, samplers_it, | 197 | PushImageDescriptors(texture_cache, guest_descriptor_queue, info, rescaling, samplers_it, |
| 198 | views_it); | 198 | views_it); |
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index 506b78f08..e6e004cb6 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp | |||
| @@ -298,7 +298,7 @@ void GraphicsPipeline::AddTransition(GraphicsPipeline* transition) { | |||
| 298 | template <typename Spec> | 298 | template <typename Spec> |
| 299 | void GraphicsPipeline::ConfigureImpl(bool is_indexed) { | 299 | void GraphicsPipeline::ConfigureImpl(bool is_indexed) { |
| 300 | std::array<VideoCommon::ImageViewInOut, MAX_IMAGE_ELEMENTS> views; | 300 | std::array<VideoCommon::ImageViewInOut, MAX_IMAGE_ELEMENTS> views; |
| 301 | std::array<VkSampler, MAX_IMAGE_ELEMENTS> samplers; | 301 | std::array<const Sampler*, MAX_IMAGE_ELEMENTS> samplers; |
| 302 | size_t sampler_index{}; | 302 | size_t sampler_index{}; |
| 303 | size_t view_index{}; | 303 | size_t view_index{}; |
| 304 | 304 | ||
| @@ -368,7 +368,7 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { | |||
| 368 | views[view_index++] = {handle.first}; | 368 | views[view_index++] = {handle.first}; |
| 369 | 369 | ||
| 370 | Sampler* const sampler{texture_cache.GetGraphicsSampler(handle.second)}; | 370 | Sampler* const sampler{texture_cache.GetGraphicsSampler(handle.second)}; |
| 371 | samplers[sampler_index++] = sampler->Handle(); | 371 | samplers[sampler_index++] = sampler; |
| 372 | } | 372 | } |
| 373 | } | 373 | } |
| 374 | if constexpr (Spec::has_images) { | 374 | if constexpr (Spec::has_images) { |
| @@ -453,7 +453,7 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) { | |||
| 453 | 453 | ||
| 454 | RescalingPushConstant rescaling; | 454 | RescalingPushConstant rescaling; |
| 455 | RenderAreaPushConstant render_area; | 455 | RenderAreaPushConstant render_area; |
| 456 | const VkSampler* samplers_it{samplers.data()}; | 456 | const Sampler** samplers_it{samplers.data()}; |
| 457 | const VideoCommon::ImageViewInOut* views_it{views.data()}; | 457 | const VideoCommon::ImageViewInOut* views_it{views.data()}; |
| 458 | const auto prepare_stage{[&](size_t stage) LAMBDA_FORCEINLINE { | 458 | const auto prepare_stage{[&](size_t stage) LAMBDA_FORCEINLINE { |
| 459 | buffer_cache.BindHostStageBuffers(stage); | 459 | buffer_cache.BindHostStageBuffers(stage); |
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index 8711e2a87..0e8f8a064 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp | |||
| @@ -1802,27 +1802,34 @@ Sampler::Sampler(TextureCacheRuntime& runtime, const Tegra::Texture::TSCEntry& t | |||
| 1802 | // Some games have samplers with garbage. Sanitize them here. | 1802 | // Some games have samplers with garbage. Sanitize them here. |
| 1803 | const f32 max_anisotropy = std::clamp(tsc.MaxAnisotropy(), 1.0f, 16.0f); | 1803 | const f32 max_anisotropy = std::clamp(tsc.MaxAnisotropy(), 1.0f, 16.0f); |
| 1804 | 1804 | ||
| 1805 | sampler = device.GetLogical().CreateSampler(VkSamplerCreateInfo{ | 1805 | const auto create_sampler = [&](const f32 max_anisotropy) { |
| 1806 | .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, | 1806 | return device.GetLogical().CreateSampler(VkSamplerCreateInfo{ |
| 1807 | .pNext = pnext, | 1807 | .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, |
| 1808 | .flags = 0, | 1808 | .pNext = pnext, |
| 1809 | .magFilter = MaxwellToVK::Sampler::Filter(tsc.mag_filter), | 1809 | .flags = 0, |
| 1810 | .minFilter = MaxwellToVK::Sampler::Filter(tsc.min_filter), | 1810 | .magFilter = MaxwellToVK::Sampler::Filter(tsc.mag_filter), |
| 1811 | .mipmapMode = MaxwellToVK::Sampler::MipmapMode(tsc.mipmap_filter), | 1811 | .minFilter = MaxwellToVK::Sampler::Filter(tsc.min_filter), |
| 1812 | .addressModeU = MaxwellToVK::Sampler::WrapMode(device, tsc.wrap_u, tsc.mag_filter), | 1812 | .mipmapMode = MaxwellToVK::Sampler::MipmapMode(tsc.mipmap_filter), |
| 1813 | .addressModeV = MaxwellToVK::Sampler::WrapMode(device, tsc.wrap_v, tsc.mag_filter), | 1813 | .addressModeU = MaxwellToVK::Sampler::WrapMode(device, tsc.wrap_u, tsc.mag_filter), |
| 1814 | .addressModeW = MaxwellToVK::Sampler::WrapMode(device, tsc.wrap_p, tsc.mag_filter), | 1814 | .addressModeV = MaxwellToVK::Sampler::WrapMode(device, tsc.wrap_v, tsc.mag_filter), |
| 1815 | .mipLodBias = tsc.LodBias(), | 1815 | .addressModeW = MaxwellToVK::Sampler::WrapMode(device, tsc.wrap_p, tsc.mag_filter), |
| 1816 | .anisotropyEnable = static_cast<VkBool32>(max_anisotropy > 1.0f ? VK_TRUE : VK_FALSE), | 1816 | .mipLodBias = tsc.LodBias(), |
| 1817 | .maxAnisotropy = max_anisotropy, | 1817 | .anisotropyEnable = static_cast<VkBool32>(max_anisotropy > 1.0f ? VK_TRUE : VK_FALSE), |
| 1818 | .compareEnable = tsc.depth_compare_enabled, | 1818 | .maxAnisotropy = max_anisotropy, |
| 1819 | .compareOp = MaxwellToVK::Sampler::DepthCompareFunction(tsc.depth_compare_func), | 1819 | .compareEnable = tsc.depth_compare_enabled, |
| 1820 | .minLod = tsc.mipmap_filter == TextureMipmapFilter::None ? 0.0f : tsc.MinLod(), | 1820 | .compareOp = MaxwellToVK::Sampler::DepthCompareFunction(tsc.depth_compare_func), |
| 1821 | .maxLod = tsc.mipmap_filter == TextureMipmapFilter::None ? 0.25f : tsc.MaxLod(), | 1821 | .minLod = tsc.mipmap_filter == TextureMipmapFilter::None ? 0.0f : tsc.MinLod(), |
| 1822 | .borderColor = | 1822 | .maxLod = tsc.mipmap_filter == TextureMipmapFilter::None ? 0.25f : tsc.MaxLod(), |
| 1823 | arbitrary_borders ? VK_BORDER_COLOR_FLOAT_CUSTOM_EXT : ConvertBorderColor(color), | 1823 | .borderColor = |
| 1824 | .unnormalizedCoordinates = VK_FALSE, | 1824 | arbitrary_borders ? VK_BORDER_COLOR_FLOAT_CUSTOM_EXT : ConvertBorderColor(color), |
| 1825 | }); | 1825 | .unnormalizedCoordinates = VK_FALSE, |
| 1826 | }); | ||
| 1827 | }; | ||
| 1828 | |||
| 1829 | sampler = create_sampler(max_anisotropy); | ||
| 1830 | if (Settings::values.max_anisotropy.GetValue() > 0 && max_anisotropy > 1.0f) { | ||
| 1831 | sampler_without_anisotropy = create_sampler(1.0f); | ||
| 1832 | } | ||
| 1826 | } | 1833 | } |
| 1827 | 1834 | ||
| 1828 | Framebuffer::Framebuffer(TextureCacheRuntime& runtime, std::span<ImageView*, NUM_RT> color_buffers, | 1835 | Framebuffer::Framebuffer(TextureCacheRuntime& runtime, std::span<ImageView*, NUM_RT> color_buffers, |
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h index 0f7a5ffd4..ee0d0480d 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.h +++ b/src/video_core/renderer_vulkan/vk_texture_cache.h | |||
| @@ -279,8 +279,17 @@ public: | |||
| 279 | return *sampler; | 279 | return *sampler; |
| 280 | } | 280 | } |
| 281 | 281 | ||
| 282 | [[nodiscard]] VkSampler HandleWithoutAnisotropy() const noexcept { | ||
| 283 | return *sampler_without_anisotropy; | ||
| 284 | } | ||
| 285 | |||
| 286 | [[nodiscard]] bool HasAddedAnisotropy() const noexcept { | ||
| 287 | return static_cast<bool>(sampler_without_anisotropy); | ||
| 288 | } | ||
| 289 | |||
| 282 | private: | 290 | private: |
| 283 | vk::Sampler sampler; | 291 | vk::Sampler sampler; |
| 292 | vk::Sampler sampler_without_anisotropy; | ||
| 284 | }; | 293 | }; |
| 285 | 294 | ||
| 286 | class Framebuffer { | 295 | class Framebuffer { |
diff --git a/src/video_core/texture_cache/image_view_base.cpp b/src/video_core/texture_cache/image_view_base.cpp index d134b6738..26fa6d63e 100644 --- a/src/video_core/texture_cache/image_view_base.cpp +++ b/src/video_core/texture_cache/image_view_base.cpp | |||
| @@ -45,4 +45,43 @@ ImageViewBase::ImageViewBase(const ImageInfo& info, const ImageViewInfo& view_in | |||
| 45 | 45 | ||
| 46 | ImageViewBase::ImageViewBase(const NullImageViewParams&) : image_id{NULL_IMAGE_ID} {} | 46 | ImageViewBase::ImageViewBase(const NullImageViewParams&) : image_id{NULL_IMAGE_ID} {} |
| 47 | 47 | ||
| 48 | bool ImageViewBase::SupportsAnisotropy() const noexcept { | ||
| 49 | using namespace VideoCommon; | ||
| 50 | switch (format) { | ||
| 51 | case PixelFormat::R8_UNORM: | ||
| 52 | case PixelFormat::R8_SNORM: | ||
| 53 | case PixelFormat::R8_SINT: | ||
| 54 | case PixelFormat::R8_UINT: | ||
| 55 | case PixelFormat::BC4_UNORM: | ||
| 56 | case PixelFormat::BC4_SNORM: | ||
| 57 | case PixelFormat::BC5_UNORM: | ||
| 58 | case PixelFormat::BC5_SNORM: | ||
| 59 | case PixelFormat::R32G32_FLOAT: | ||
| 60 | case PixelFormat::R32G32_SINT: | ||
| 61 | case PixelFormat::R32_FLOAT: | ||
| 62 | case PixelFormat::R16_FLOAT: | ||
| 63 | case PixelFormat::R16_UNORM: | ||
| 64 | case PixelFormat::R16_SNORM: | ||
| 65 | case PixelFormat::R16_UINT: | ||
| 66 | case PixelFormat::R16_SINT: | ||
| 67 | case PixelFormat::R16G16_UNORM: | ||
| 68 | case PixelFormat::R16G16_FLOAT: | ||
| 69 | case PixelFormat::R16G16_UINT: | ||
| 70 | case PixelFormat::R16G16_SINT: | ||
| 71 | case PixelFormat::R16G16_SNORM: | ||
| 72 | case PixelFormat::R8G8_UNORM: | ||
| 73 | case PixelFormat::R8G8_SNORM: | ||
| 74 | case PixelFormat::R8G8_SINT: | ||
| 75 | case PixelFormat::R8G8_UINT: | ||
| 76 | case PixelFormat::R32G32_UINT: | ||
| 77 | case PixelFormat::R32_UINT: | ||
| 78 | case PixelFormat::R32_SINT: | ||
| 79 | case PixelFormat::G4R4_UNORM: | ||
| 80 | return false; | ||
| 81 | default: | ||
| 82 | break; | ||
| 83 | } | ||
| 84 | return range.extent.levels > 1; | ||
| 85 | } | ||
| 86 | |||
| 48 | } // namespace VideoCommon | 87 | } // namespace VideoCommon |
diff --git a/src/video_core/texture_cache/image_view_base.h b/src/video_core/texture_cache/image_view_base.h index a25ae1d4a..87549ffff 100644 --- a/src/video_core/texture_cache/image_view_base.h +++ b/src/video_core/texture_cache/image_view_base.h | |||
| @@ -33,6 +33,8 @@ struct ImageViewBase { | |||
| 33 | return type == ImageViewType::Buffer; | 33 | return type == ImageViewType::Buffer; |
| 34 | } | 34 | } |
| 35 | 35 | ||
| 36 | [[nodiscard]] bool SupportsAnisotropy() const noexcept; | ||
| 37 | |||
| 36 | ImageId image_id{}; | 38 | ImageId image_id{}; |
| 37 | GPUVAddr gpu_addr = 0; | 39 | GPUVAddr gpu_addr = 0; |
| 38 | PixelFormat format{}; | 40 | PixelFormat format{}; |
diff --git a/src/video_core/textures/texture.cpp b/src/video_core/textures/texture.cpp index 560b3af8a..cb24d0399 100644 --- a/src/video_core/textures/texture.cpp +++ b/src/video_core/textures/texture.cpp | |||
| @@ -62,12 +62,14 @@ std::array<float, 4> TSCEntry::BorderColor() const noexcept { | |||
| 62 | } | 62 | } |
| 63 | 63 | ||
| 64 | float TSCEntry::MaxAnisotropy() const noexcept { | 64 | float TSCEntry::MaxAnisotropy() const noexcept { |
| 65 | const bool is_unsupported_mipmap_filter = Settings::values.use_aggressive_anisotropic_filtering | 65 | const bool is_suitable_mipmap_filter = Settings::values.use_aggressive_anisotropic_filtering |
| 66 | ? mipmap_filter == TextureMipmapFilter::None | 66 | ? mipmap_filter != TextureMipmapFilter::None |
| 67 | : mipmap_filter != TextureMipmapFilter::Linear; | 67 | : mipmap_filter == TextureMipmapFilter::Linear; |
| 68 | const bool has_regular_lods = min_lod_clamp == 0 && max_lod_clamp >= 256; | 68 | const bool has_regular_lods = min_lod_clamp == 0 && max_lod_clamp >= 256; |
| 69 | if (max_anisotropy == 0 && | 69 | const bool is_bilinear_filter = min_filter == TextureFilter::Linear && |
| 70 | (depth_compare_enabled.Value() || !has_regular_lods || is_unsupported_mipmap_filter)) { | 70 | reduction_filter == SamplerReduction::WeightedAverage; |
| 71 | if (max_anisotropy == 0 && (depth_compare_enabled.Value() || !has_regular_lods || | ||
| 72 | !is_bilinear_filter || !is_suitable_mipmap_filter)) { | ||
| 71 | return 1.0f; | 73 | return 1.0f; |
| 72 | } | 74 | } |
| 73 | const auto anisotropic_settings = Settings::values.max_anisotropy.GetValue(); | 75 | const auto anisotropic_settings = Settings::values.max_anisotropy.GetValue(); |