KhronosGroup / OpenGL-API

OpenGL and OpenGL ES API Issue Tracker
34 stars 5 forks source link

Multidraw and invocation groups. #15

Closed NicolBolas closed 6 years ago

NicolBolas commented 7 years ago

In the Vulkan specification, the standard explicitly says, "For indirect drawing commands with drawCount greater than one, invocations from separate draws are in distinct invocation groups." However, OpenGL has no similar statement, either for indirect or direct multidraw commands. The GLSL specification only says, "single rendering command, as defined by the client API," (copied word-for-word from the SPIR-V spec).

But the "client API" (OpenGL) never really defines it. As such, it is not clear if the individual draws in a multidraw command represent distinct invocation groups, as defined in the GLSL/SPIR-V specifications.

ghost commented 6 years ago

I think this is just a question about SPIR-V/GL, but if this affects GLSL as well, please add the ES tag @pdaniell-nv

nhaehnle commented 6 years ago

One could argue that OpenGL does define it, though rather indirectly, because it uses pseudo code to define the indirect drawing commands in terms of a sequence of non-indirect drawing commands that are said to be equivalent except for OpenGL error generation.

I agree though that a clarification would be helpful.

NicolBolas commented 6 years ago

If you use that definition, then each instance within a single drawing command would be considered an "invocation group", since instanced rendering commands are defined in terms of multiple calls to the hypothetical glDraw*OneInstance function. And that's very much not what Vulkan requires, so it's highly unlikely that desktop OpenGL would be more lenient, since the hardware certainly isn't.

nhaehnle commented 6 years ago

That's a good point, actually. So we really need to clear that up.

pdaniell-nv commented 6 years ago

We discussed this in the 2017-10-13 OpenGL WG meeting. We decided that best the spec can guarantee is that the entire multidraw API call represents one invocation group. In particular some hardware may not be able to update dynamically uniform values between draw iterations of a multidraw call, so we can't have the API spec state that each draw in a multidraw is a distinct invocation group.

I'm not sure what the best place to define this in the OpenGL spec is. Perhaps somewhere in the "10.4 Drawing Commands Using Vertex Arrays" section? Just need to put a sentence that says that each call to an OpenGL draw command (and not the special internal ones) represents one shader invocation group.

Suggestions?

NicolBolas commented 6 years ago

In particular some hardware may not be able to update dynamically uniform values between draw iterations of a multidraw call, so we can't have the API spec state that each draw in a multidraw is a distinct invocation group.

If you do that, then the specification would contradict itself. OpenGL 4.6 says (emphasis added):

gl_DrawID holds the integer draw number [of] the current draw being processed by the shader invocation. It is dynamically uniform. In MultiDraw* variants, this is the zero-based index of the draw within the list of draws processed by the command. In non-MultiDraw* commands, the value of gl_DrawID is always zero.

And GLSL 4.60 says (emphasis added):

An expression is dynamically uniform for a dynamic instance consuming it when its value is the same for all invocations (in the invocation group) that execute that dynamic instance.

gl_DrawID cannot resolve to different values in the same invocation group and still adhere to the definition of "dynamically uniform". So it seems to me that the possibilities are:

  1. Individual draw operations in a multidraw command (direct or indirect) must be separate invocation groups.
  2. gl_DrawID cannot be required to be dynamically uniform.
  3. Redefine the meaning of "dynamically uniform" as it applies to gl_DrawID.

It also seems odd that, in Vulkan, hardware can give a guarantee of (indirect) multidraw invocation groups, but the same hardware cannot do this under OpenGL.


As for exactly where to put this information, I would suggest doing as the Vulkan specification does and giving this information a section in Chapter 7. That is, put the information about shader invocation groups in the chapter about shaders.

pdaniell-nv commented 6 years ago

Good point about Vulkan being explicit that each iteration of a multi-draw command is a separate invocation group. I see no reason why OpenGL can't be the same in this regard. We'll discuss this at the next meeting.

pdaniell-nv commented 6 years ago

For reference, here is the Vulkan spec: https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#shaders-invocationgroups

pdaniell-nv commented 6 years ago

Taking another stab at this issue. As noted in the original description, the OpenGL spec is lacking a definition of "invocation group", which is referenced by the GLSL spec. The GLSL spec expects the client API to define this, which OpenGL does not. As @NicolBolas helpfully points out, we can probably add a new sub-section to section 7 to do this.

Add new Section 7.10 "Invocation Groups":

An invocation group (see the subsection “Shader Invocation Group Functions” of section 8.18 of the GLSL 4.60 specification) for a compute shader is the set of invocations in a single local workgroup. For graphics shaders, an invocation group is an implementation-dependent subset(1) of the set of shader invocations of a given shader stage which are produced by a single drawing command. For MultiDraw* commands with drawcount greater than one, invocations from separate draws are in distinct invocation groups.

(1) Footnote: Because the partitioning of invocations into invocation groups is implementation-dependent and not observable, applications generally need to assume the worst case of all invocations in a draw belong to a single invocation group.

NicolBolas commented 6 years ago

That definition seems to contradict itself. It explicitly says that individual draws in MultiDraw* commands are "in distinct invocation groups", but the footnote says that they all may be in a single invocation group.

pdaniell-nv commented 6 years ago

That footnote comes from the Vulkan note. I’m not sure if it applies here.

pdaniell-nv commented 6 years ago

@NicolBolas I updated the spec above to clarify the footnote to not reference "MultiDraw". This is actually more like the Vulkan one now. Does it look okay?

pdaniell-nv commented 6 years ago

Assigned to @oddhack to make the spec change based on comment https://github.com/KhronosGroup/OpenGL-API/issues/15#issuecomment-370951171.

oddhack commented 6 years ago

The fixes identified by @pdaniell-nv will be in the next GL & ES spec updates, coming soon.