Workgroup (if the VariablePointerscapability is declared)
I don’t see anything about Uniform pointers not being Logical. I don’t really see why I shouldn’t be able to pass a StorageBuffer pointer either. How am I supposed to make member functions that take arguments (including “this”) from different storage classes without having these pointers? I’m mean, I’m not involving any of the Variable pointer instructions listed in 2.2.2.
To fend off replies like “you should not want to do this,” I have a quality use case:
This is an entire shadertoy program defined as a C++ function object. The function object is bound as a UBO. The render member function is called by the generic fragment shader function template. The implicit object argument therefore has a Uniform storage class. By prohibiting this, all functions have to be inlined into the entry point, and modularity and readability of source goes out the window.
The Logicaladdressing model means pointers are abstract, having no physical size or numeric value. In this mode, pointers can only be created from existing objects, and they cannot be stored into an object, unless additional capabilities, e.g., VariablePointers , are declared to add such functionality.
You aren’t meant to be able to pass pointers to such things to different functions in logical addressing. Variable pointers allow specific exceptions, but only for StorageBuffers.
In logical addressing, pointers are a fiction that mainly exists to allow SPIR-V code for shaders and for OpenCL compute operations to share a lot of functionality. This also allows graphics shaders to gain more functionality over time without having to use a completely different language. This has advanced somewhat with variable pointers and the less restrictive PhysicalStorageBuffer64 addressing mode.
It’s also important to realize what UBOs conceptually represent. They’re not (supposed to be) pointers to memory. They’re static storage within the shader itself. Conceptually, the system uploads to the memory, it gets used during an invocation, and that’s it. You don’t get pointers to it.
That’s why something like PhysicalStorageBuffer64 doesn’t exist for UBOs; that’s not what they’re for.
See 2.16.1 Universal Validation Rules, for logical pointers, where you don’t have VariablePointers or VariablePointersStorageBuffer. Then the following rule applies:
So pointer-to-Uniform is not permitted. That’s the contract with the driver. In particular, conformance tests don’t check this and the driver won’t work.
Now, you say
To fend off replies like “you should not want to do this,” I have a quality use case:
By prohibiting this, all functions have to be inlined into the entry point, and modularity and readability of source goes out the window.
Your Circle compiler can still present a programming model to the user where pointer-to-Uniform is allowed. But then it has the responsibility of inlining that whole stack of functions before presenting the SPIR-V code to the driver. The user doesn’t have to know of the limitation.
In many cases this works just fine. One can construct cases where you get exponential blowup of the code, but those are rare-ish. Secondly, I know there can be loss of utility when debugging the code, but shader debugging is a more advanced case, and “proper” debug info tracks inlining anyway.