Reputation: 1
I have some legacy DX11 code that renders to multiple 3d render targets. Destination target is passed via SV_TARGETxx
and the slice is set via SV_RenderTargetArrayIndex
in GS. Is there any way to do the same in Vulkan?
My plan is to create individual view for each slice of each 3d target and pass them all together as attachments to a single frame buffer, then in GS I can have something like gl_Layer = sliceNo + targetOffsets[xx]
. Is there any better solution?
Upvotes: 0
Views: 2396
Reputation: 6787
In Vulkan, the GS SV_RenderTargetArrayIndex is called Layer
in SPIR-V or gl_Layer
in GLSL. It behaves the same as in D3D. You create one view per 3D target, and attach that to the framebuffer. The Layer
output from the GS will say which layer (of all the targets) the output primitive is drawn to.
In Vulkan there's no "true" 3D framebuffer attachments, in the sense that after projection to screen space coordinates everything exists in a 2D plane. So attachment image views can have 2D_ARRAY dimensionality, but not 3D. The Image and image view parameter compatibility requirements table says that given a 3D image, you can create a 2D_ARRAY
image view with layerCount >= 1
. Note that you have to create the image with the VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT
flag.
So if you want to have N 3D render target images:
VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT
flag.VK_IMAGE_VIEW_TYPE_2D_ARRAY
and layerCount
equal to the number of slices you want to be able to render to.VkRenderPass
with one VkAttachmentDescription
per 3D render target, plus whatever others you need for depth/stencil, resolve target, etc.VkFrameBuffer
based on that VkRenderPass
, and pass your image views in the VkFrameBufferCreateInfo::pAttachments
array. Set VkFramebufferCreateInfo::layerCount
to the number of layers/slices you want to be able to render to.[Edit: Below paragraph can be ignored based on first comment. Leaving it for transparency.]
I'm confused what you're trying to do with SV_Target[n]
. In both D3D and Vulkan, if you've got multiple render targets / color attachments, the fragment shader will write to all of them -- if your fragment shader doesn't provide a value for a bound target, the value written is undefined. So SV_Target[n]
is used to tell which shader output variables go to which target, but they don't let you write to some without writing to others. Vulkan works similarly, using output variables gl_FragData[n]
in GLSL.
Upvotes: 1
Reputation: 29240
If you're talking about having 1 draw call rendered from multiple points of view (but otherwise using the same pipeline) then you want VK_KHR_multiview. This is an extension in Vulkan 1.0, but core in 1.1.
There's an example of it's usage here and the corresponding shader functionality is here. It functions similar to what you seem to describe. You attach multiple images from a texture array to a single framebuffer ("rendertarget" in D3D) and then in the vertex shader you can determine which layer you're rendering to via the gl_ViewIndex
variable. There's no need for a geometry shader with this approach.
Upvotes: 0