问题
I have just spent around five hours studying parts of the OpenGL 4.5 specification found here (or a slightly earlier version of it): https://www.khronos.org/registry/OpenGL/specs/gl/glspec45.core.pdf
Unfortunately, I seem to be getting mixed messages.
In section 5.3.1 “Determining Completion of Changes to an object” beginning on page 54 (75 of 805) it states in a footnote on that page that:
“The GL already specifies that a single context processes commands in the order they are received. This means that a change to an object in a context at time t must be completed by the time a command issued in the same context at time t + 1 uses the result of that change.”
In section 5.3.3 “Rules” beginning on page 55 (76 of 805), it states on that page:
“Rule 1 If the contents of an object T are changed in the current context while T is directly or indirectly attached, then all operations on T will use the new contents in the current context.”
Both of these statements seem to imply that when using only a single context, the OpenGL functions MemoryBarrier()
– described in section 7.12.2 “Shader Memory Access Synchronization” beginning on page 152 (173 of 805) – and FenceSync()
– described in section 4.1 “Sync Objects and Fences” beginning on page 36 (57 of 805) – are completely unnecessary except when a buffer is being memory-mapped for direct client access.
But in section 7.12.2 “Shader Memory Access Synchronization” beginning on page 152 (173 of 805) it states on that page that:
“To permit cases where textures or buffers may be read or written in different pipeline stages without the overhead of automatic synchronization, buffer object and texture stores performed by shaders are not automatically synchronized with other GL operations using the same memory.
Explicit synchronization is required to ensure that the effects of buffer and texture data stores performed by shaders will be visible to subsequent operations using the same objects and will not overwrite data still to be read by previously requested operations.”
It also states on the same page that:
“For the purposes of this ordering, memory transactions performed by shaders are considered to be issued by the rendering command that triggered the execution of the shader.”
And it states on page 155 (176 of 805) that:
“Data written to image variables in one rendering pass and read by the shader in a later pass need not use coherent variables or
memoryBarrier
. CallingMemoryBarrier
with theSHADER_IMAGE_ACCESS_BARRIER_BIT
set in barriers between passes is necessary.Data written by the shader in one rendering pass and read by another mechanism (e.g., vertex or index buffer pulling) in a later pass need not use coherent variables or
memoryBarrier
. CallingMemoryBarrier
with the appropriate bits set in barriers between passes is necessary.”
These latter statements seem to me to contradict the former. So my questions pertain to the use of a single context without any direct memory mapping or explicit synchronisation (hypothetically), with both rendering shaders (invoked with glDrawArrays()
) and compute shaders (invoked with glDispatchCompute()
), and are as follows:
1: Are all changes made by the client application BEFORE invoking shaders guaranteed to be seen by those shader invocations (and associated fixed-function rendering operations), including:
1.1: Changes to rendering state, such as with glEnable()
/glDisable()
, glStencilFunc()
, glStencilOp()
,glClearColor()
, glStencilMask()
, glClearStencil()
, glBlendFunc()
, glColorMask()
, etc.?
1.2: Changes to uniform buffer bindings, as with glBindBufferBase()
?
1.3: Changes to shader storage buffer bindings, as with glBindBufferBase()
?
1.4: Changes to texture image bindings, as with glBindImageTexture()
?
1.5: Changes to uniform buffer data, as with glNamedBufferSubData()
?
1.6: Changes to shader storage buffer data, as with glNamedBufferSubData()
?
1.7: Changes to texture image data, as with glTextureSubImage3D()
?
2: Are all changes made by the client application AFTER invoking shaders guaranteed NOT to be seen by those shader invocations (and associated fixed-function rendering operations), including:
2.1 to 2.7: (As 1.1 to 1.7 respectively)?
3: Are all reads made by the client application AFTER invoking shaders guaranteed to see changes made by those shaders (and associated fixed-function rendering operations), including:
3.1: Reads of shader storage buffer data, as with glGetNamedBufferSubData()
?
3.2: Reads of texture image data written explicitly by the shaders, as with glGetTextureImage()
?
3.3: Reads of texture image data written by rendering output to textures bound to a FrameBufferObject (as colour, depth, and stencil buffers), as with glGetTextureImage()
?
3.4: Reads of colour, depth, and stencil data from the current FrameBuffer, as with glReadPixels()
?
4: Are all reads made by the client application BEFORE invoking shaders guaranteed NOT to see changes made by those shaders (and associated fixed-function rendering operations), including:
4.1 to 4.4: (As 3.1 to 3.4 respectively)?
5: Are all texture image reads of texture image data written by rendering output to textures bound to a FrameBufferObject (as colour, depth, and stencil buffers) guaranteed to see changes made by those rendering operations when the reads are made by shaders invoked AFTER those rendering operations were invoked?
6: For any and each of the above questions to which the answer is NO, what forms of synchronisation when added would change the answer to YES?
Any help would be much appreciated.
EDIT:
Changes to rendering state (point 1.1 above) should also include calls to glUseProgram()
.
来源:https://stackoverflow.com/questions/59265147/synchronisation-in-opengl