UAVs (D3D11 renderer) and SSBO (OpenGL)

Discussion area about developing or extending OGRE, adding plugins for it or building applications on it. No newbie questions please, use the Help forum for that.
Post Reply
User avatar
bishopnator
Goblin
Posts: 223
Joined: Thu Apr 26, 2007 11:43 am
Location: Slovakia / Switzerland
x 5

UAVs (D3D11 renderer) and SSBO (OpenGL)

Post by bishopnator »

Hello everyone,
I wanted to verify some rendering technique in Ogre and I didn't find support for UAVs in D3D11 render system neither also in GL renderer. I found in forums very brief discussion about this topic from 2015 (link) but there was not a lot. What is the status of this? Most specifically I am interested only in support of read/write shader buffers in pixel shaders.

I am trying to compose a rendering technique which requires to collect all pixels (with some additional data per pixel) from pixel shaders - using just textures is not enough as the pixels are overwriting there and also it is harder to extend the collected pixel information. As quick test I already extended D3D11 renderer to have support for it so it is possible to create addition buffers (and UAVs) through D3D11MultiRenderTarget. As I am not working with OpenGL, I am studying how an equivalent support can be added there, but as pointed also in the forum link above, the OpenGL has different concept about SSBO compared to D3D11 with buffer+UAV.

Is it desired feature for Ogre? Is it worth to check further and come with some proposals, prototype, patches for Ogre?

D3D11 example shader:

Code: Select all

struct FragmentData
{
    int2 coords;
    int visible;    
};
RWStructuredBuffer<FragmentData> fragmentData;

PS_OUTPUT PSMain(PS_INPUT v, ...)
{
    FragmentData output;
    ... // initialize output
    uint index = fragmentData.IncrementCounter();
    fragmentData[index] = output;
    ...
}
What I found so far, OpenGL has no support for internal counter for SSBO so it must be somehow emulated like:

Code: Select all

struct FragmentData
{
    ivec2 coords;
    int visible;    
};
layout(std430, binding = 0) buffer fragmentData
{
   int count;
   FragmentData data[];
};

void main()
{
    FragmentData output;
    ... // initialize output
    uint index = atomicAdd(fragmentData.count, 1);
    fragmentData.data[index] = output;
    ...
}
The GL renderer should then hides the 'count' variable properly through some getter method. Support for unstructured buffers should be also supported - however support for structured part + unbound variable in OpenGL cannot be implemented in D3D11:

Code: Select all

layout(std430, binding = 0) buffer fragmentData
{
   // structured part
   int var1;
   float var2;
   ...
   // unbound part
   FragmentData data[];
};
So I think if something like this would be needed, then through Ogre's renderer interface it would require to create 2 shader buffers to split the definition and upload then 2 UAVs in D3D11 or 2 SSBO in OpenGL even if OpenGL's shader could be implemented with just a single SSBO.

I didn't think further how it would be possible to declare/create/use those shader buffers through scripts (program / material / compositor scripts). Do you see deeper usage in such feature? Is it worth to look further?
paroj
OGRE Team Member
OGRE Team Member
Posts: 1993
Joined: Sun Mar 30, 2014 2:51 pm
x 1073
Contact:

Re: UAVs (D3D11 renderer) and SSBO (OpenGL)

Post by paroj »

depends on which branch you look at. Ogre2.1 has UAV/ SSBO support:
https://ogrecave.github.io/ogre/api/2.1 ... esUavQueue

and AFAIR uses it for screen space reflections.

Ogre1 only has some rudimentary SSBO classes in the GL3+ rendersystem. If you would like to have proper UAV/ SSBO in Ogre1, according patches are welcome.
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5292
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1278
Contact:

Re: UAVs (D3D11 renderer) and SSBO (OpenGL)

Post by dark_sylinc »

As paroj says, UAV & SSBOs are fully supported in Ogre 2.1

We're currently using them for Screen Space Reflections, fast large-radius gaussian filters using compute shaders, large-radius mipmap generation, and terrain shadows in real time.
User avatar
bishopnator
Goblin
Posts: 223
Joined: Thu Apr 26, 2007 11:43 am
Location: Slovakia / Switzerland
x 5

Re: UAVs (D3D11 renderer) and SSBO (OpenGL)

Post by bishopnator »

I briefly checked the support and I am missing some parts. I have to check deeper and collect more information about OpenGL how it works there. In DX there is a support for "structured" buffer which is an array of fixed size structures - in OpenGL there is equivalent in form of unbound array (last variable in a structure bound as SSBO) and I would like to mimic this feature in Ogre's renderer (but still keep the support of just a single struct if needed). I will try to study the current support in 2.1 branch and adapt/improve the implementation and backport/integrate it into 1.x branch. I have no idea how much time I'll need for it, I hope I will post some updates here in this thread.
User avatar
bishopnator
Goblin
Posts: 223
Joined: Thu Apr 26, 2007 11:43 am
Location: Slovakia / Switzerland
x 5

Re: UAVs (D3D11 renderer) and SSBO (OpenGL)

Post by bishopnator »

I am going deeper and deeper with integration. The D3D11 renderer I have already done and I am able to do through it what I wanted to achieve. GL3Plus renderer is little bit tricky as there is already some support for SSBO. In code (and I mean in both 1.x and 2.x branches) I see a lot of "fixme" and "todo" notes around the UAV and SSBO. So I am trying to code in certain (probably different) directions as the current support is and try to achieve some nice features at the and.

So far what I thought about is following:
* adding Ogre::ShaderBufferManager and Ogre::ShaderBuffer - those are more like ResourceManager and Resource so the shader buffer can be accessed at any time by name using Ogre::ShaderBufferManager::getSingleton().getByName(...)
* instance of ShaderBuffer can be created also through *.program or *.material script (syntax not finished)
* shader buffers can be attached to render targets (not necessary limited to MRT, anything inherited from Ogre::RenderTarget gets the support)
* compositor script should be able to refer to shader buffers when defining render targets

The D3D11 automatically binds the attached UAVs ("shader buffers") to the bound GPU programs, but in GLSL it is necessary to bind them manually by referring the variable names and their binding points so in GLSL it should be possible to attach the shader buffer through parameters. I see that in 1.x branch it is somehow done by accessing shared parameters by using variable's name from GLSL program and hence all GPU programs using SSBO under the same name will by automatically bound to the same buffer - the idea is interesting - I would like to keep that by adding reference to the shared parameters when creating ShaderBuffer in script. I would like to extend also GpuProgramParameters::AutoConstantType values to be able to refer to the ShaderBuffers attached to current RenderTarget (this will be useful for configuring GLSL programs in material scripts).

In GL3Plus it is necessary to issue proper memory barriers - through compositor script it should be easy to follow the usage of ShaderBuffer(s) and hence insert required memory barriers between the passes.

The changes are growing and I will try to prepare whole big patch with deep description. I have to check also whether my approach is nicely usable with compute shaders.
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5292
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1278
Contact:

Re: UAVs (D3D11 renderer) and SSBO (OpenGL)

Post by dark_sylinc »

bishopnator wrote: Wed Feb 06, 2019 4:58 pm In code (and I mean in both 1.x and 2.x branches) I see a lot of "fixme" and "todo" notes around the UAV and SSBO. So I am trying to code in certain (probably different) directions as the current support is and try to achieve some nice features at the and.
Beware that when it comes to 2.1, there's nothing WIP or incomplete about UAV, SSBO, Image_load_store support and memory barriers(*). Those fixme and todo notes are probably from dead paths from 1.x that haven't been removed, or outdated comments.

GL3PlusHardwareShaderStorageBuffer is not used at all and it just hasn't been removed. Ogre 2.1 uses UavBufferPacked instead for UAV/SSBOs and a regular texture with TU_UAV set when using image_load_store.

The relevant UAV functions are RenderSystem::setUavStartingSlot, queueBindUAV, clearUAVs, flushUAVs (when the UAVs are run in rendering pipeline such as vertex/geometry/pixel/etc shaders) and _bindTextureUavCS (when the UAVs are run in compute shaders).

Compute shaders are run through HlmsComputeJob and HlmsCompute, and not via the older low level materials interface (note: running compute shaders via low level materials is not planned, nor desired as compute jobs are much better fit for that purpose).

(*) Memory barriers may be marked incomplete in the sense that they've also been designed to hold D3D12 and Vulkan barrier information, but it is not yet fully coded as we don't yet have either a D3D12 nor Vulkan RenderSystem. But when it comes to GL3+, memory barriers are handled correctly.

Cheers
paroj
OGRE Team Member
OGRE Team Member
Posts: 1993
Joined: Sun Mar 30, 2014 2:51 pm
x 1073
Contact:

Re: UAVs (D3D11 renderer) and SSBO (OpenGL)

Post by paroj »

bishopnator wrote: Wed Feb 06, 2019 4:58 pm So far what I thought about is following:
* adding Ogre::ShaderBufferManager and Ogre::ShaderBuffer - those are more like ResourceManager and Resource so the shader buffer can be accessed at any time by name using Ogre::ShaderBufferManager::getSingleton().getByName(...)
* instance of ShaderBuffer can be created also through *.program or *.material script (syntax not finished)
* shader buffers can be attached to render targets (not necessary limited to MRT, anything inherited from Ogre::RenderTarget gets the support)
* compositor script should be able to refer to shader buffers when defining render targets
I would rather suggest extending the GpuProgramManager as it is already responsible for creating UBOs (GpuSharedParameters) which have .material support:
https://ogrecave.github.io/ogre/api/lat ... Parameters

Note that GpuSharedParameters currently are not actually backed by UBOs, but rather copied into uniforms for backwards compatibility (share the same shader with GL/ GL3+ and GLES2/ GLES3).
We could add a flag here though to force hardware UBOs ("shared_params.gpu_buffer").

Ideally your ShaderBuffer class should derive from GpuSharedParameters as UBOs and SSBOs are conceptually similar (at least on GL).
However feel free to open a "WIP" pull request for discussion as is.
paroj
OGRE Team Member
OGRE Team Member
Posts: 1993
Joined: Sun Mar 30, 2014 2:51 pm
x 1073
Contact:

Re: UAVs (D3D11 renderer) and SSBO (OpenGL)

Post by paroj »

dark_sylinc wrote: Wed Feb 06, 2019 5:17 pm Compute shaders are run through HlmsComputeJob and HlmsCompute, and not via the older low level materials interface (note: running compute shaders via low level materials is not planned, nor desired as compute jobs are much better fit for that purpose).
compute shaders are best dispatched using compositors on Ogre1 as well:
https://ogrecave.github.io/ogre/api/lat ... tor-Passes

compositors reference the buffers and constants they need via plain materials. See the Compute sample:
https://github.com/OGRECave/ogre/blob/v ... terial#L28
Post Reply