Page MenuHome

(WIP) Shader/Geometry Nodes: Enabled image texture extensions to be set independently for X/U and Y/V axes
Changes PlannedPublic

Authored by Ethan Hall (Ethan1080) on Mar 3 2022, 12:29 PM.

Details

Reviewers
None
Summary

This patch is a work in progress.
I am currently working on dividing this up into smaller diffs.
I will take what I learn from feedback on the smaller diffs and apply it here after I make progress on them.
Currently I am prioritizing the following patches and need feedback there:

FeaturePatch
Cycles Texture Sampler RefactorD14295
Geometry Nodes Texture Sampler RefactorD14304
EEVEE Sampler RefactorD14366

Here are some related patches that make minor non functional changes:

Minor FeaturePatch
Cleanup: Replace shader image defines with image texture enumsD14297
Node UI: Updated descriptions for a few node texture settingsD14308

The goal of this patch is to enable the user to set the image extension settings independently for the X/U and Y/V axes.
This patch also helps refactor certain parts of the sampler code for EEVEE and Cycles to facilitate more features in the future.
Specifically, I would like to add mirrored repeat to the list of extension settings, but this patch is already getting big.

Demo:

On top of the regular worries about messing things up, I have some additional doubts:
I have not and cannot test the Metal and HIP implementations.
I am unsure about how to handle the versioning of animated values.
Adjustments need to be made to ensure support for animating the image extension settings.
I have made changes to the way samplers are managed that might interfere with the EEVEE Rewrite branch.

Diff Detail

Repository
rB Blender
Branch
independent_axis_image_extensions (branched from master)
Build Status
Buildable 20823
Build 20823: arc lint + arc unit

Event Timeline

Ethan Hall (Ethan1080) requested review of this revision.Mar 3 2022, 12:29 PM
Ethan Hall (Ethan1080) created this revision.
Ethan Hall (Ethan1080) edited the summary of this revision. (Show Details)Mar 3 2022, 1:10 PM

It is not clear to me why you have to break the eGPUSamplerState enum into smaller ones. I don't think being able to reuse the enums in nodes is enough to justify this. To me it just adds complexity.
I don't really like ImageTextureExtensionType being a DNA member referenced in GPU . The name makes it confusing. Maybe there should be a corresponding eGPUSamplerExtensionType, but again I don't find this.

If you would introduce repeat mirror extent mode, you could just add a new bit to the eGPUSamplerState enum that modifies the behavior of the extent flag just like GPU_SAMPLER_CLAMP_BORDER changes the clamp behavior.
But this would prevent having one dimension being repeat normal and the other repeat mirror. So I can see the benefit of your approach. However, there is still the concern that it creates a lot of samplers variations which can become a problem.

Another approach would be to have a separate Texture sampler list that does not include all the variations we dont need. I would keep eGPUSamplerState as the only state definition for API simplicity. Maybe you could have something like this:

enum eGPUSamplerState {
   /* General Purpose States */
   ...
   /* Image samplers
     * These samplers do not have GPU_SAMPLER_COMPARE and GPU_SAMPLER_ANISO usage is automatic.
     */
   GPU_SAMPLER_IMAGE_WRAP_S_REPEAT = (1 << 16)
   GPU_SAMPLER_IMAGE_WRAP_S_REPEAT_MIRROR = (2 << 16)
   ....
};

General purpose GPU_SAMPLER_* would be incompatible to mix with the GPU_SAMPLER_IMAGE_*. In the bind function, you could then use the image sampler array if sampler_state > 0xFFFF.

I would prefer to have the GPU changes (and their side effects) in another patch.

source/blender/gpu/opengl/gl_texture.cc
563

Note that the typo was copy pasted. Also notes these were voluntary shortened (omitting _to) because the debug names were getting very long.

@Clément Foucault (fclem) First of all, thank you for your time.

It is not clear to me why you have to break the eGPUSamplerState enum into smaller ones. I don't think being able to reuse the enums in nodes is enough to justify this. To me it just adds complexity.

The reason this is because the extension types are mutually exclusive. I don't think of GPU_SAMPLER_CLAMP_BORDER as changing the clamp behavior. I think of it as one of (currently) three separate modes. This is how it is portrayed in the various graphics library specifications.
I find it is easier to assign the settings if they are separated like this. Mapping the settings to a sampler index is also easier for me to comprehend and I was able to reduce the total number of samplers.

The eGPUSamplerState enum had me asking questions like:
What does GPU_SAMPLER_CLAMP_BORDER bit flag do when the extension type is set to repeat?
What do all of the bits mean when the GPU_SAMPLER_ICON flag is set?

I had to look deeper into the code to figure out which setting overrides another.

The method GPU_texture_wrap_mode was quite confusing to me. Not just for the questions raised above but also because the name use_clamp does not indicate if the sampler will use clamp to border or clamp to edge.

I don't really like ImageTextureExtensionType being a DNA member referenced in GPU . The name makes it confusing. Maybe there should be a corresponding eGPUSamplerExtensionType

I can agree to this. I couldn't quite make up my mind on what to do, but using the same enum isn't worth the confusion. Having a separate enum for this would Indicate the context change better. If you recall, the old texture system had extension settings (checker for example) that do not correspond to OpenGL or other graphics libraries' extension settings. I don't know if something like that would ever be added to the image texture nodes, but regardless it makes sense to have separate enums for the higher level extension settings and lower level graphics library compatible extension settings.

If you would introduce repeat mirror extent mode, you could just add a new bit to the eGPUSamplerState enum that modifies the behavior of the extent flag just like GPU_SAMPLER_CLAMP_BORDER changes the clamp behavior.
But this would prevent having one dimension being repeat normal and the other repeat mirror. So I can see the benefit of your approach.

Yeah, that's basically it. In my opinion, adding these features would overcomplicate the eGPUSamplerState enum, and that is why I chose to break it apart.

However, there is still the concern that it creates a lot of samplers variations which can become a problem.

Perhaps I am wrong about this, but in the current implementation we are initializing 257 samplers.
In my implementation, we initialize 145 samplers.
If we add Mirrored Repeat to my implementation we would be initializing 257 samplers.
It looks like the samplers are only bound as needed and the array to store bound samplers can store 64 unique samplers.

Another approach would be to have a separate Texture sampler list that does not include all the variations we don't need. I would keep eGPUSamplerState as the only state definition for API simplicity. Maybe you could have something like this:

enum eGPUSamplerState {
   /* General Purpose States */
   ...
   /* Image samplers
     * These samplers do not have GPU_SAMPLER_COMPARE and GPU_SAMPLER_ANISO usage is automatic.
     */
   GPU_SAMPLER_IMAGE_WRAP_S_REPEAT = (1 << 16)
   GPU_SAMPLER_IMAGE_WRAP_S_REPEAT_MIRROR = (2 << 16)
   ....
};

General purpose GPU_SAMPLER_* would be incompatible to mix with the GPU_SAMPLER_IMAGE_*. In the bind function, you could then use the image sampler array if sampler_state > 0xFFFF.

I'm not exactly sure what you mean by General Purpose States. How many samplers would be included? Is a General Purpose State made of a combination of flags, or is it more like the GPU_SAMPLER_ICON type that I called a Custom Sampler.
I don't favor this approach for a couple of reasons:
It doesn't distinguish the mutually exclusive settings from the other settings.
It seems to be more complicated, but that could be because I don't know what the General Purpose States would encompass.

In my mind, having more variables carry the state is simpler because each component is very simple. The flags enum is used only as flags and every paramutation of bits should be a valid set of flags. Having one variable to carry the state that is split in such a way seems more complicated and less clear.

If GPU_SAMPLER_COMPARE or non-ANISO samplers are not used much, then it would be better just to make a few Custom Samplers via my implementation.
This way the programmer always knows where to look. If they need a GPU_SAMPLER_COMPARE, they can find it in the Custom Samplers enum list or define a new Custom Sampler.

From what I saw, there appears to be only one unique sampler state that has compare mode enabled.

Ethan Hall (Ethan1080) edited the summary of this revision. (Show Details)
  • Added eGPUSamplerExtensionTypes enum, and fixed some typos.
  • Fixed unintentional changes to node_shader_utils.py. Removed debug print statement.
source/blender/draw/engines/eevee/eevee_effects.c
250
Ethan Hall (Ethan1080) marked an inline comment as done.Mar 4 2022, 5:14 AM
Ethan Hall (Ethan1080) added inline comments.
intern/cycles/kernel/device/gpu/image.h
244
255
source/blender/gpu/GPU_texture.h
358–361
source/blender/gpu/intern/gpu_shader_create_info.hh
601–603
  • Made a few small fixes.
  • Removed GPU_SAMPLER_COMPARE flag and replaced with a single eGPUCustomSamplerType
Ethan Hall (Ethan1080) edited the summary of this revision. (Show Details)Mar 8 2022, 12:38 AM
Ethan Hall (Ethan1080) edited the summary of this revision. (Show Details)Mar 10 2022, 12:22 AM
intern/cycles/util/texture.h
9

Remove this problematic reference to a GPL licensed header.

Ethan Hall (Ethan1080) edited the summary of this revision. (Show Details)Mar 11 2022, 12:13 AM
Ethan Hall (Ethan1080) planned changes to this revision.Mar 15 2022, 8:41 AM
Ethan Hall (Ethan1080) retitled this revision from Shader/Geometry Nodes: Enabled image texture extensions to be set independently for X/U and Y/V axes. to (WIP) Shader/Geometry Nodes: Enabled image texture extensions to be set independently for X/U and Y/V axes.Mar 17 2022, 2:41 PM
Ethan Hall (Ethan1080) edited the summary of this revision. (Show Details)