问题
I have an OpenCL program that adjusts the vertex coordinates of a VBO object in a shared context. The OpenCL device is a GPU device.
However, I get the following warning:
Buffer performance warning: Buffer object 1 (bound to GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB (0), GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB (4), and GL_ARRAY_BUFFER_ARB, usage hint is GL_DYNAMIC_DRAW) is being copied/moved from VIDEO memory to HOST memory.
As near as I can tell (had to add some glFlush()
calls to help), this occurs during the call to glDrawElements(...)
. Vertex attribute array at shader location 0 is vertex and vertex attribute array at shader location 4 is texture coordinate.
The question is, why does this occur?
EDIT: the loop is of the following form:
glFinish()
clEnqueueAcquireGLObjects(...)
clEnqueueNDRangeKernel(...)
clFinish(...)
clEnqueueReleaseGLObjects(...)
回答1:
For the same reason that before OpenGL supported VBOs every call to glDrawElements (...)
would pull memory from the client immediately (rather than when the GPU started executing the command). GL queues up commands in the background, but for some operations it has to block and/or make a copy of data to prevent a concurrent processor (CPU or OpenCL in this case) from modifying the data before OpenGL actually finishes the command. It needs a copy of the data as it existed when glDrawElements (...)
was actually called.
VBOs solved this fundamental problem by giving the OpenGL server explicit control over all access to vertex memory. It was no longer possible to modify vertex memory concurrently in a way that the OpenGL server did not know about. Any attempt to modify vertex memory required a command in the GL pipeline, so ensuring that queued commands have the correct copy of vertex data could be managed entirely by GL itself without resorting to unnecessary copying or blocking.
When you share buffer objects between GL and CL you actually break some of the beauty of buffer objects in GL. It gives a separate concurrent pipeline access to GL owned memory, and thus GL can no longer be sure that nothing has modified the data it owns without its knowledge.
clEnqueueAcquireGLObjects
Acquire OpenCL memory objects that have been created from OpenGL objects.
[...]
Notes
Prior to calling clEnqueueAcquireGLObjects, the application must ensure that any pending GL operations which access the objects specified in mem_objects have completed. This may be accomplished portably by issuing and waiting for completion of a glFinish command on all GL contexts with pending references to these objects. Implementations may offer more efficient synchronization methods; for example on some platforms calling glFlush may be sufficient, or synchronization may be implicit within a thread, or there may be vendor-specific extensions that enable placing a fence in the GL command stream and waiting for completion of that fence in the CL command queue. Note that no synchronization methods other than glFinish are portable between OpenGL implementations at this time.
Similarly, after calling clEnqueueReleaseGLObjects, the application is responsible for ensuring that any pending OpenCL operations which access the objects specified in mem_objects have completed prior to executing subsequent GL commands which reference these objects. This may be accomplished portably by calling clWaitForEvents with the event object returned by clEnqueueReleaseGLObjects, or by calling glFinish. As above, some implementations may offer more efficient methods.
You need GL / CL synchronization to properly deal with this, which explains why glFlush (...)
helps. However, flushing the command queue is usually inadequate. This only tells GL to start working on all of the commands it has buffered immediately, but does not even attempt to ensure that they will finish before control returns to the CPU.
To completely answer this question, more details are necessary; particularly the sequence of CL and GL commands that are using the buffer data and what synchronization you are using.
来源:https://stackoverflow.com/questions/23000584/opencl-host-copying-performance-warning