PDA

View Full Version : efficiently clear buffers



Chris Lux
02-18-2011, 02:34 AM
Hi,
I am working on a project utilizing EXT_shader_image_load_store functionality to write buffer objects during rendering. What i am missing from OpenGL is a way to efficiently clear the buffers between invocations. For textures I am going the way of attaching them to a FBO and calling glClearBuffer(), which i think is Ok but still not clean enough.

With buffers i am forced to go the way of dummy rendering passes using fullscreen geometry to clear the buffers. Very ugly and IMO quite inefficient. D3D11 has ID3D11DeviceContext::ClearUnorderedAccessView{}() functions to do this, OpenGL badly requires such functionality.

Am I missing a more efficient way for clearing buffer objects?

Regards
-chris

_arts_
02-18-2011, 04:40 AM
Am I missing a more efficient way for clearing buffer objects?

As far as I understand you these are not buffer objects. Are you talking about FBO ? If so, if glClearBuffer is too slow for you, you can try a CopyTexSubImage which seems fast, but unsure if it's faster than clearing the buffer. If you have no texture attached to the FBO, then I think you have no other choice but glClearBuffer.

Chris Lux
02-18-2011, 04:49 AM
These are buffer objects. I am using the texture buffer functionality to directly access them in the shaders. For texture images the FBO way is fast enough, but for actual buffer objects i need to run a shader which then fills the buffer with the wanted clear value.

_arts_
02-18-2011, 05:00 AM
Sorry for this stupid question again, but:

why you clear buffers with glClearBuffer when you have textures, and why can't you call glClearBuffer when you have a buffer ?

I'm certainly missing a point, but which one...

Chris Lux
02-18-2011, 05:05 AM
The glClearBuffer API is there for clearing color attachments of a FBO (i.e. textures or render buffers). So there is no way to actually clear a buffer object (e.g. pixel buffer).

We now have the functionality to do random writes to buffer objects from a shader, not just fixed writes to textures or render buffers. So we are missing a functionality to clear buffer objects directly.

_arts_
02-18-2011, 10:57 AM
I think you can use asynchronism to do a more quick clear.

According to: http://www.opengl.org/registry/specs/ARB/pixel_buffer_object.txt


when using glDrawPixels with a pixel pack buffer object, glDrawPixels may return prior to image unpacking because future modification of the buffer data requires explicit commands

So, with having 2 PBOs, swapping from one to another between each frame, and clearing the current unused while writting to the current used, it lmight result in performance increase. It's very not pretty, but if I understood well the specs, it should work.

Alfonse Reinheart
02-18-2011, 11:43 AM
So we are missing a functionality to clear buffer objects directly.

Clearing a buffer object means writing the "clear" value to all of its bytes. Which you can do easily enough with glBufferSubData. There's no need for a special API for this.

skynet
02-18-2011, 01:08 PM
Which you can do easily enough with glBufferSubData. There's no need for a special API for this.

This is like suggesting to use memcpy() instead of memset() to clear memory. Not very efficient, wouldn't you agree?

Chris Lux
02-18-2011, 02:57 PM
Which you can do easily enough with glBufferSubData. There's no need for a special API for this.

This is like suggesting to use memcpy() instead of memset() to clear memory. Not very efficient, wouldn't you agree?
That is exactly my point. There are ways, but they are not the most efficient. And clearing a very large buffer using BufferSubData requires either multiple calls or a very large buffer containing the clear values.

Besides the fact, that we have a way to clear textures using the FBO detour it would be nice to be able to clear textures easier in times of direct write access though shader_image_load_store.

Alfonse Reinheart
02-18-2011, 09:03 PM
This is like suggesting to use memcpy() instead of memset() to clear memory. Not very efficient, wouldn't you agree?

That assumes that there is an equivalent to "memset" in the GPU's hardware. That is, that a driver implementation of "memset" wouldn't simply allocate a block of memory and do a DMA. I don't know why GPUs would need a way to clear buffers to some particular value; it's not like this is a common operation.

Clearing render targets is a different thing altogether. The format of the data is 100% controlled by the driver. Indeed, the number of ways to change such an object is generally quite small, limited to glDrawPixels and rendering functions (yes, if the render target happens to be a texture, you can use glTex[Sub]Image, but then you're accessing it as a texture, not a render target). Whereas the format of the data in a buffer object is 100% controlled by the user.

And how exactly would you specify any such buffer clearing operation? Uses of buffers can consider "words" (for the purposes of this conversation, the smallest useful data size) to be anything from one byte to 16 bytes (a GLSL vec4). Or even 64 bytes if your data happens to be matrices. If you want to "clear" a buffer, why shouldn't you be able to clear it to the identity matrix?

So what would this function look like?

kyle_
02-19-2011, 06:36 AM
Cant you use a second buffer with 'clear' data, and glCopyBufferSubData from it when needed?
Hopefully this will be faster than glBufferSubData, and strightforward to try out. May not be the prettiest logically (still a memcpy) and prohibitive if your buffers are too large though.

Chris Lux
02-19-2011, 09:09 AM
Would you still consider this with buffers larger than 30MiB? Because I think the memory overhead is too much just for a clear operation.

kyle_
02-19-2011, 09:37 AM
That would depend on how much it gives you performance wise, target hardware and how much is going on in your application.

Also, you may not need that much, if you just need to zero out everything you could get away with small buffer of zeros that would get copied into destenation buffer several times.

I imagine you should be [way] faster than glBuffer[Sub]Data from main memory. Dont have any idea how it compares with stores from shader though.

mfort
02-20-2011, 01:05 AM
If you want to try CUDA on NVIDIA ....



cudaGLSetGLDevice(...)

// register you glBuffer to CUDA
cudaGraphicsGLRegisterBuffer(...)

...

// GPU side memset
cudaGraphicsMapResources(...)
cudaGraphicsResourceGetMappedPointer(...)
cudaMemset(...)
cudaGraphicsUnmapResources


I think this is the fastest way on NVIDIA. Then you can measure performance of all your other OpenGL based methods with this.