Hi @goazevedo and welcome to the forums !
It is complicated. I would suggest that you capture the frame and examine all the attachments on the GPU for the various passes.
The structure GBufferOut
is defined in the shader file Deferred.metal. It is a list of three textures: albedo, normal, and position. Each of these has an attribute [[color(x)]]
which specifies the color attachment index. Albedo is index 1, normal is index 2, and position is index 3 (enum RenderTargetIndices
, defined in Common.h). The textures for these color attachments are loaded into the descriptor at the top of TiledDeferredRenderPass.draw(commandBuffer:scene:uniforms:params:)
. When you create the render command encoder, it uses the descriptor, which points at these color attachments. Color attachment 0 is the view’s drawable texture by default.
Previously, you were simply returning a color from the fragment function, which is written to the texture in color attachment 0. This is the view’s drawable texture. But now, you’re setting up multiple color attachment textures, and you need a way of returning multiple textures from the one fragment function. That’s why you set up a structure containing the multiple textures.
fragment_gBuffer
writes to this structure, which is the return from the fragment function. Notice that you don’t write anything to color attachment 0, because the GBuffer pass is an interim pass which doesn’t draw anything to the screen.
Using the albedo, normal and position textures, you can then calculate the lighting. Both fragment_tiled_pointLight
and fragment_tiled_deferredSun
are passed GBufferOut
containing these textures to calculate the relevant lighting. Both these functions then write the final pixel to the texture in color attachment 0, which is the view’s drawable texture.
The difference between an immediate-mode (IM) GPU and a TBDR GPU is that the TBDR GPU retains the GBufferOut
textures in tile memory, rather than writing the textures back to system memory.
The non-TBDR GBuffer pass creates the textures, which are transferred to system memory, then the separate lighting pass has to transfer the system memory textures back to the GPU using renderEncoder.setFragmentTexture(texture, index: x)
.
The TBDR GBuffer pass creates the textures, which are retained in GPU tile memory, then, in the same pass, calls the GPU lighting functions which read the GPU tile memory.
I hope this helps.