-
Notifications
You must be signed in to change notification settings - Fork 259
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
Description of UniformConstant storage class in spec #448
Comments
Glslang's translation is correct. The object in UniformConstant is a handle and not the image itself. This is non-obvious. You cannot store or reassign the image handle, but you can modify the contents of the image. The easiest way to view this difference is by examing OpImageTexelPointer which actually returns a pointer into the Image storage class. That is where the actual texels are. Similarly it is why you can decorate a storage image with NonReadable and still perform queries on the image object (because only handle metadata is accessed). |
Thank you for your response. I agree that the idea of the Image being a handle and not the image itself is non-obvious. Ideally, this would be clarified in the specification. Let's consider this idea further: As far as I am aware, all
it is really an image handle type being declared, right? And since the type of the variable is an
What is the desired value of You said that I can decorate a storage image with
but Please explain a little more what you meant with your Lastly, is there a way to designate that an image (not the handle) is read-only or write-only? If we accept the idea that |
The idea behind OpVariable have a pointer result type is that it is the address of the data. An object of OpTypeImage is a handle to an image. You could view as a pointer and some metadata. So a more accurate C/C++ style of declaration would be:
SPIR-V says the ImageType structure is not mutable, but the texel data may be mutable (e.g. for storage images).
The desired value (assuming you haven't created a data race) is the same as
The queries I was referring to were things like getting the image dimensions or number mip levels (OpImageQuery instructions). Those only access the metadata so can be done on a NonReadable image. Your example is accessing the texel data.
OpImageTexelPointer is like an OpAccessChain into a image. It uses image coordinates to specify a particular texel. That instruction is used only with atomic instructions.
Different APIs do this differently. In OpenCL, you can use the access qualifier image operand. In Vulkan, you'd use the NonReadable or NonWritable decorations on the image variable. However, note that the Sampled operand of the OpTypeImage imposes some restrictions on possible instructions that it can be used with (e.g. cannot write an image with Sampled == 1). |
To summarize, here are things I have gathered from our conversation but cannot find anywhere in the specification:
You say that "Program order within a single invocation should prevent reordering those writes and they both access the same underlying memory", but the point I was trying to make is that even if they do access the same memory, that fact is not readily apparent because the destination operands are different. This idea adds a constraint on any optimizer to recursively track the source for all image operands before reordering (something which I thought was unique to pointers). I think the takeaway is that if the image handle idea is correct, then it has far too many correctness repercussions to leave undocumented. I am sure you are a busy person, can you point me in the right direction of where I could propose formal edits to the spec to include the information discussed? |
This is a mental model. It is sufficient to communicate that there is (often) more at work than just a pointer to data.
This is just fundamental to all types in SPIR-V. If I declare
The decorations detail that they can be applied to storage images (that is an image with Sampled operand of 2). The query instructions indicate they do not read the actual texel data. So this information is a bit spread out.
Images are not aggregates. The load does not load all the texels. This is why the idea of a handle is important and I agree this could probably be explained better somewhere (even if not directly in the spec). Runtime array loading is disallowed for different reasons. Because the length is not known at compile time there would not likely be any efficient way to do this.
That is a reasonable comment. It requires understanding the way images are modelled that I admit is non-obvious.
The SPIR WG will consider this feedback. Some of this information might be appropriate in the SPIR-V Guide (e.g. the proposed image chapter could be further fleshed out). Some is appropriate in the spec. We don't have a good way to take edits directly, but you could make suggestions here about which sections you'd think should be modified and we could take it under advisement. |
I plan to update the SPIRV-Guide new Image Access chapter there is a Storage Class chapter with a small section on As Alan said, there are things that can probably be updated in the spec, but the type of good GLSL examples you gave are something that don't really belong there and why we started the SPIRV-Guide to help spillover that type of information |
This was discussed during last week's WG meeting, I have an action to update the specs based on your feedbacks (and thanks for providing them) and should be present in the next release of the specs. |
This is specifically in regards to the online specification. Please redirect me if this is the wrong place to file a ticket for that.
I think the description for the
UniformConstant
storage class in the unified specification is partially incorrect, and could be improved. It reads:(italic emphasis mine)
Not all graphics uniform memory variables are strictly-speaking read-only. Consider this short shader in GLSL:
image
is a graphics uniform memory variable, but its memory is modified by theimageStore
. Continuing, we useglslang
to convert the shader to SPIR-V. We get:Assuming that
glslang
's translation is correct, we have here a variable of storage classUniformConstant
with necessarily mutable data. Granted, it would be illegal to reassign the image (and perhaps that is meant by "constant"), but the confusion persists. In case it isn't clear, this is the same concept as C'sconst type* ptr
versustype* const ptr
.I would suggest a change of wording:
"Variables declared with this storage class
are read-onlymay not be reassigned."To my knowledge, that correction is accurate, but I am happy to brainstorm alternatives if my statement is proven wrong.
Alternatively, we could decide that
UniformConstant
s should in fact, be read-only. If so, the implication that "Graphics uniform memory" falls underUniformConstant
is incorrect. Admittedly, I am not sure how we should change the spec in that case. Maybe something like:"Graphics non-image uniform memory."
If we continue down this route, I can create an issue for
glslang
to change its translation of GLSL uniforms.The text was updated successfully, but these errors were encountered: