Using Shader Buffer Objects with Double or Triple Buffering

Hi,

I’d like to use use a shader storage buffer with persistant and coherent mapping and double or triple buffering to avoid syncronisation issues but I’m not sure how to get the shader to use the alternating part of the buffer. Anyone know a comprehensive turotial? google didn’t yield too much helpful.

Thanks in advance for any hint :slight_smile:

[QUOTE=saski;1287745]
I’d like to use use a shader storage buffer with persistant and coherent mapping and double or triple buffering to avoid syncronisation issues but I’m not sure how to get the shader to use the alternating part of the buffer.[/QUOTE]
Either modify the array index used within the shader (if the buffer isn’t already an array, make it one), or change the portion of the buffer which is bound to the target via the offset parameter to glBindBufferRange().

But if you’re using multi-buffering, why make the mapping coherent? You can flush the mapping whenever you swap.

[QUOTE=GClements;1287747]Either modify the array index used within the shader (if the buffer isn’t already an array, make it one), or change the portion of the buffer which is bound to the target via the offset parameter to glBindBufferRange().

But if you’re using multi-buffering, why make the mapping coherent? You can flush the mapping whenever you swap.[/QUOTE]

Well I want to use a mapped-once “pinned” buffer so I can access the uniforms without calling glMapBuffer…() every time because I have to do this a lot and so far the performance is abyssimal. The Idea with an index came to my mind as well but do I have to pass the index uniform to the share the “traditional way”, i.e. glUniform…() ? This would ruin my effords of reducing GL calls.
I’ve already tried to “rebind” a coherent buffer with glBindBufferRange(GL_SHADER_STORAGE_BUFFER, …) however the driver didn’t like it :(. Is calling glBindBufferRange() multiple times on a buffer storage created with GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT possible at all?

[QUOTE=saski;1287754]

Well I want to use a mapped-once “pinned” buffer so I can access the uniforms without calling glMapBuffer…() every time because I have to do this a lot and so far the performance is abyssimal.[/QUOTE]

Right. Normal glMapBuffer…() triggers synchronization in the driver. It’s slow in my experience too.

OTOH, Map UNSYNCHRONIZED with buffer orphaning instead of pages works well for lots of maps per frame (update+draw+update+draw+…) with a single-threaded GL driver. NVidia says it can trigger driver sync on a multithreaded GL driver though.

For that use case and in general, they recommend using PERSISENT+COHERENT maps with pages instead (AZDO, among other places).

For more on these, see Buffer Object Streaming in the wiki.

Re flushing the mapping when you swap (w/ normal buffer maps), I think the issue there may be that you can’t submit a draw call referencing data in a buffer while the buffer is mapped. So unless you do oneBigUpdate() + drawEverything() in your frames (which sometimes isn’t convenient, though it may be more efficient), you’ve got a number of calls to MapBuffer per frame (update()+draw()+update+draw()…, where each update() == Map,memcpy,Unmap). UNSYNC or PERSISENT+COHERENT reduces the overhead of this usage. And of course with PERSISENT+COHERENT, update() just == memcpy).

I don’t know about comprehensive, but apitest (John McDonald) has an example which illustrates doing buffer object streaming using PERSISTENT+COHERENT maps and triple-buffering, using sync objects for page synchronization. See mappersistent.cpp for the guts of it, with bufferlock.cpp wrapping the sync objects. The AZDO presentation above contains a walkthrough of this.