bgfx
bgfx copied to clipboard
VPRT Support (as opposed to MRT)
Is there any support for VPRT render targets? Currently, it seems that the only way to have multiple render targets is through separate buffers with multiple attachments, but it seems that VPRT (through texture arrays) is starting to be used fairly heavily in the AR/VR worlds. It differs from normal multiple render targets because it allows the different invocations of the fragment shader for each layer of the render target, instead of one fragment shader that outputs to multiple gl_FragData.
This works in OpenGL as well as D3D11, and certainly in Vulkan/Metal/D3D12 by setting the gl_Layer in the vertex shader based on gl_InstanceID (by submitting your geometry with multiple instances). This fires off a different fragment/pixel shader for each instance of the geometry, but because the gl_Layer is set in the vertex shader, all of the rasterized fragments/pixels go straight to different layers of the texture array.
I cannot find a way to specify this in bgfx as it stands right now, there is only the option to specify multiple attachments for a framebuffer but no way to specify a framebuffer with a single attachment and multiple layers. I think it's automatic in OpenGL for it to pick up the fact it can spit out the fragments to different layers, and it seems that in D3D11 it is handled through a call to CreateRenderTargetView using D3D11_RTV_DIMENSION_TEXTURE2DARRAY.
If this is already implemented, can you point me in the right direction? If not, can you maybe point me in the right direction where you think the implementation would go so I can knock it out and maybe submit a PR?
gl_Layer
is not supported.
But it's possible to create frame buffer from texture array (21-deferred supports this).
If this is already implemented, can you point me in the right direction? If not, can you maybe point me in the right direction where you think the implementation would go so I can knock it out and maybe submit a PR?
So the best way is to investigate first what's supported and what's needs to be done. And then figure out what's the minimum you need to do to achieve goal you need.
For example: gl_Layer
is SV_RenderTargetArrayIndex
in D3D, what's in Metal?
I have already implemented the gl_Layer inner workings in a way which allows for interoperability with frameworks like OpenXR (which require VPRT), but the problem is that when I try to use other framebuffers than the ones provided by theOpenXR framework, such as ones from bgfx, all of the outputs are only writing to the first layer. See my repo for how the bgfx inner workings play out.
https://github.com/MarkVabulas/bgfx/commit/c3c5dccf1471bc5c837b36017b35ccf7062bc354
There is also another repository showing you the changes necessary to make bgfx function with OpenXR here: https://github.com/VirtualGeo/OpenXR-bgfx
I am completely able to build and run the example repositories on Hololens2 hardware, and I have modified the example heavily for other purposes. The problem comes when trying to use bgfx to do the non-backbuffer (offscreen) rendering. Perhaps a solution would be to request another swapchain of buffers from the OpenXR runtime and then force bgfx to use those externally provided buffers as render targets, but my knowledge of bgfx isn't as yet complete enough to know how to wire that together OR use those same textures later on as samplers.
For Metal, it looks like there's SPIRV-Cross sources in spirv-msl which discuss gl_Layer at: https://chromium.googlesource.com/external/github.com/KhronosGroup/SPIRV-Cross/+/refs/heads/master/spirv_msl.cpp (line 523)
Either way, however, supporting merely D3D11/12 would be great, adding OpenGL/Vulkan would be ideal. For OpenGL and Vulkan, from what I read in the specs, if you supply a framebuffer with only a single colorbuffer attachment and it's a texture array, it automatically assumes it's a render target possible to render to using gl_Layer from the vertex shader. In that case, for OpenGL/Vulkan, perhaps there's no code to write (I'm not sure if Metal carries the same functionality, my knowledge of Metal is limited). It only comes down to manually specifying the views in bgfx if there's a single attachment and the attachment has layers.
Oh, and the reason I can't use the texture array like in 21-deferred is that I need to have a different fragment shader run for each eye, because they're using different view matrices which are selected via the gl_Layer property specified in the vertex shader (and passed as a parameter into the fragment shader inside v_color0). This let's me issue 1 submit call with 2 instances, and have a completely different result spit out of each fragment shader invocation into each layer. I'm not actually doing deferred rendering or anything with a G-buffer, so those classic approaches won't work, sadly. I really do need multiple invocations of the fragment shader to compute per-view/per-layer parameters independently.
You can create PR for this commit: MarkVabulas@c3c5dcc
I will create a PR for that commit, as well as this one:
https://github.com/MarkVabulas/bgfx/commit/c6bee90ff5f6c1a4b8e2a86199ebd941129147fd
This actually seems to solve my problem entirely. It seems that the renderer was specifying that there was only 1 for the array size, instead of the number of layers. Maybe this was an oversight? Maybe this breaks other code, I'm not sure of any side effects, but for VPRT, it solves the issue nicely. As you have a much larger view of how the code interoperates, would you expect this change to cause problems elsewhere?
Actually that second one is incorrect, but I see what it needs to be fixed... The same how you have at.layer
, you should have at.numLayers
(not texture.numLayers
).
I'm not seeing a variable which stores the number of layers in the attachment. Is that something which would need to be implemented? What is the benefit of doing it that way vs. just using the texture's number of layers?
Yeah it needs to be added to Attachment
.
Benefit is that you can set exact number of layers you need. And other is validation. If for example if you set layer=3, then number of layers can't be texture.numLayers, but rather texture.numLayers-at.layer.
I added Attachment.numLayers
:
https://github.com/bkaradzic/bgfx/commit/796acfa98bc69f525d658fc61724195dbb688d8e
You can submit PR for your shaderc changes.
Also in order for this to work we need to enable it: https://docs.microsoft.com/en-us/windows/win32/api/d3d11/ns-d3d11-d3d11_feature_data_d3d11_options3
Added gl_ViewportIndex
and gl_Layer
. https://github.com/bkaradzic/bgfx/commit/812f7712f18928d508bed4eb2d9c468b4f26e9e9