Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enabled anisotropy with nearest filtering #1361

Closed
lexaknyazev opened this issue Sep 2, 2020 · 9 comments
Closed

Enabled anisotropy with nearest filtering #1361

lexaknyazev opened this issue Sep 2, 2020 · 9 comments

Comments

@lexaknyazev
Copy link
Member

lexaknyazev commented Sep 2, 2020

The spec says:

The particular scheme for anisotropic texture filtering is implementation dependent. Implementations should consider the magFilter, minFilter and mipmapMode of the sampler to control the specifics of the anisotropic filtering scheme used.

Consider this sampler state (assuming that samplerAnisotropy feature is enabled):

VkSamplerCreateInfo sampler;
sampler.magFilter = VK_FILTER_NEAREST;
sampler.minFilter = VK_FILTER_NEAREST;
sampler.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
sampler.maxAnisotropy    = 1.0;
sampler.anisotropyEnable = VK_TRUE;

To what extent the implementations are free to interpret this state? Sampling a single-level texture on NVIDIA and AMD produces regular nearest look while the same state on Intel produces an image as if linear interpolation is used.

@TomOlson
Copy link

To what extent the implementations are free to interpret this state?

The unfortunate answer is "very free". This is a legacy of the early days of aniso filtering in GL, when filters and modes were abused (in different ways by different vendors) to serve as quality hints. Those corner-case behaviors don't really serve any purpose today, but they persist in the drivers and can't really be changed. So, using NEAREST with aniso is probably not going to give consistent behavior across implementations, ever. Other corner cases, such as enabling aniso with maxAnisotropy set to one, are similarly likely to reveal implementation differences. The only thing we can recommend is avoiding them: use aniso only when it will give a desired quality boost vs plain LINEAR.

@lexaknyazev
Copy link
Member Author

lexaknyazev commented Sep 14, 2020

Gotcha. I'd suggest adding that explanation to the spec as a note. Also, we probably could ask Intel whether the divergent result is an implementation detail or an occasional driver bug.

@gfxstrand
Copy link
Contributor

On Intel, it's just a driver detail. We could probably make this one case do the same thing that you claim AMD and NVIDIA do. However, there are many more corner cases where things get weird fast (what if one filter mode is NEAREST and the other is LINEAR?) so we'd really rather not make any promises here. As Tom said, if you ask for anisotropic filtering but with NEAREST or maxAnisotropy = 1.0, you get what you get. You're better off setting anisotropyEnable = VK_FALSE if anisotropic linear filtering isn't what you want.

@Novum
Copy link

Novum commented Mar 13, 2023

@gfxstrand why is the behavior of the Intel driver diverging from NVIDIA and AMD? Does the hardware not support aniso + nearest filtering? Because if it does, that is actually a useful state for retro graphics and people would like to be able to use it.

@gfxstrand
Copy link
Contributor

gfxstrand commented Mar 14, 2023

@gfxstrand why is the behavior of the Intel driver diverging from NVIDIA and AMD? Does the hardware not support aniso + nearest filtering? Because if it does, that is actually a useful state for retro graphics and people would like to be able to use it.

As I said above, it's a driver detail. The hardware can't actually do aniso+nearest but we can decide what aniso+nearest means:

https://gitlab.freedesktop.org/mesa/mesa/-/blob/main/src/intel/vulkan/genX_state.c#L771

Right now, we give you aniso in that case but we could make NEAREST ignore anisotropyEnable and always mean NEAREST. But an app can just as easily smash anisotropyEnable to false whenever they want NEAREST.

@Novum
Copy link

Novum commented Mar 14, 2023

Why can't the hardware do it though? I'm not a HW person but I have written a anisotropic filter implementation in software and it basically boils down to taking N bilinear/trilinear samples along the line of anistropy. It seems like it should be easy to take nearest samples for each of them in HW? I don't expect it to change, but it would be nice to have. It's probably too obscure of a use case for people to care.

Also from an API standpoint it's really annoying to have UB like this that we can't even query for. E.g. user facing I would like to disable the option for AF if nearest filtering is selected instead of it just not working.

@gfxstrand
Copy link
Contributor

I can't answer that question, I'm afraid. The hardware doesn't support it. That's all I know. It may, as you say, be quite easy for them to modify the hardware to handle it but I'm no longer at Intel and able to make such a request and even if I did, you'd be seeing it in 5ish years and only if you can make a really solid case that it's needed. Closing a spec corner isn't typically a good enough argument for the PMs in power.

@oddhack
Copy link
Contributor

oddhack commented Apr 27, 2023

Gotcha. I'd suggest adding that explanation to the spec as a note. Also, we probably could ask Intel whether the divergent result is an implementation detail or an occasional driver bug.

The note has been added in the 1.3.249 spec update (along with moving the theoretical algorithm description into the note, since it was non-normative all along). We can't fix anything about the Intel driver in this repository, so closing the issue - it would have to be taken up with Intel.

@oddhack oddhack closed this as completed Apr 27, 2023
@oddhack
Copy link
Contributor

oddhack commented Apr 27, 2023

(Also, I just noticed a typo in the NOTE - missing "to" in "expected to give a quality improvement" - which will be fixed in the next spec update. No need to raise an issue about it. Unfortunately spec updates are a very heavyweight process so I'm not going to re-do it just for the typo.)

erlehmann added a commit to erlehmann/minetest that referenced this issue Nov 13, 2023
This reverts commit 72ef908.

The reverted commit caused several regressions in rendering textures
using bilinear, trilinear or anisotropic filtering. In particular:

• Textures with a height or width lower than “texture_min_size” were no
  longer first upscaled and then filtered. This change affected how all
  small textures (i.e. almost all Minetest textures) looked if filtering
  was enabled – they were not filtered at all. To users this looked like
  bilinear and trilinear filtering no longer working. Anisotropic filter
  effects were affected in differently, depending on vendor (see below).

• On Intel GPUs (and possibly others), anisotropic filtering would blur
  textures with small height or width extremely due to GL_NEAREST being
  set. The effect of that combination depends on driver internals – see
  <KhronosGroup/Vulkan-Docs#1361> and Vulkan
  1.3.249 spec update for details. Note that Khronos Group explicitly
  warned against using GL_NEAREST in this scenario, as it can not be
  expected to result in a consistent look with different GPUs, ever.
erlehmann added a commit to erlehmann/minetest that referenced this issue Nov 16, 2023
This reverts commit 72ef908.

The reverted commit caused several regressions in rendering textures
using bilinear, trilinear or anisotropic filtering. In particular:

• Textures with a height or width lower than “texture_min_size” were no
  longer first upscaled and then filtered. This change affected how all
  small textures (i.e. almost all Minetest textures) looked if filtering
  was enabled – they were not filtered at all. To users this looked like
  bilinear and trilinear filtering no longer working. Anisotropic filter
  effects were affected in differently, depending on vendor (see below).

• On Intel GPUs (and possibly others), anisotropic filtering would blur
  textures with small height or width extremely due to GL_NEAREST being
  set. The effect of that combination depends on driver internals – see
  <KhronosGroup/Vulkan-Docs#1361> and Vulkan
  1.3.249 spec update for details. Note that Khronos Group explicitly
  warned against using GL_NEAREST in this scenario, as it can not be
  expected to result in a consistent look with different GPUs, ever.
erlehmann added a commit to erlehmann/minetest that referenced this issue Nov 17, 2023
This reverts commit 72ef908.

The reverted commit caused several regressions in rendering textures
using bilinear, trilinear or anisotropic filtering. In particular:

• Textures with a height or width lower than “texture_min_size” were no
  longer first upscaled and then filtered. This change affected how all
  small textures (i.e. almost all Minetest textures) looked if filtering
  was enabled – they were not filtered at all. To users this looked like
  bilinear and trilinear filtering were no longer working. Anisotropic
  filter effects were affected in different ways, depending on vendor.

• On Intel GPUs (and possibly others), anisotropic filtering would blur
  textures with small height or width extremely due to GL_NEAREST being
  set. The effect of that combination depends on driver internals – see
  <KhronosGroup/Vulkan-Docs#1361> and Vulkan
  1.3.249 spec update for details. Note that Khronos Group explicitly
  warned against using GL_NEAREST in this scenario, as it can not be
  expected to result in a consistent look with different GPUs, ever.
erlehmann added a commit to erlehmann/minetest that referenced this issue Nov 17, 2023
This reverts commit 72ef908.

The reverted commit caused several regressions in rendering textures
using bilinear, trilinear or anisotropic filtering. In particular:

• Textures with a height or width lower than “texture_min_size” were no
  longer upscaled and then filtered – textures were not filtered at all
  when being upscaled instead, to achieve a crisper look. To users this
  looked like bilinear and trilinear filtering options were not working,
  as most textures in Minetest are rather small and thus often upscaled.
  Anisotropic filter effects were affected in different ways; depending
  on vendor filtering could happen when upscaling textures (see below).

• On Intel GPUs (and possibly others), anisotropic filtering would blur
  textures with small height or width extremely due to GL_NEAREST being
  set. The effect of that combination depends on driver internals – see
  <KhronosGroup/Vulkan-Docs#1361> and Vulkan
  1.3.249 spec update for details. Note that Khronos Group explicitly
  warned against using GL_NEAREST in this scenario, as it can not be
  expected to result in a consistent look with different GPUs, ever.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants