How some Nanite passes work?

We would like to understand how some Nanite passes work so that to improve our debugging process. These passes belong to the MainPass scope:

HierarchyCellCull

InstanceHierarchyAppendUncullable

InstanceCull - GroupWork

PersistentCull

CalculateSafeRasterizerArgs

RasterBinCount

ClearBuffer

RasterBinReserve

RasterBinScatter

HW Rasterize

Could you please explain the purpose of these passes, what data do their buffers store, and how is this data passed between other passes?

Hello,

Thank you for reaching out.

I’ve been assigned this issue, and we will be looking into these passes for you.

Any update please?

Hello,

Here is a brief breakdown of each pass and what it does.

HierarchyCellCull

This pass culls instances based on instance hierarchy, a more broad culling phase than per-instance. This pass prepares the input data needed for per-instance culling. The shader is “FInstanceHierarchyCull_CS”, from NaniteCullRaster.cpp.

InstanceHierarchyAppendUncullable

This pass adds instances to the data for per-instance culling that cannot be culled by hierarchical cell culling. The shader is “FInstanceHierarchyAppendUncullable_CS” from NaniteCullRaster.cpp.

InstanceCull - GroupWork

This pass is a form of per-instance culling (distance, occlusion, and similar) that is used with the shader’s Group Params are valid. The shader is “FInstanceCull_CS”, from NaniteCullRaster.cpp.

PersistentCull

This pass culls clusters and nodes, and is used when the CVar “r.Nanite.PersistentThreadsCulling” is enabled. It combines the work of several other passes. For more information, please see “FRenderer::AddPass_NodeAndClusterCull” from NaniteCullRaster.cpp. The shader is “FNodeAndClusterCull_CS”, from NaniteCullRaster.cpp.

CalculateSafeRasterizerArgs

The comment on “CalculateSafeRasterizerArgs()” from NaniteClusterCulling.usf explains this pass, reading: “Make sure the indirect args we give to the rasterizer are not out of bounds and that the SW/HW ranges are not overlapping.” The shader is “FCalculateSafeRasterizerArgs_CS”, from NaniteCullRaster.cpp.

RasterBinCount

This pass counts the number of hardware and software raster bins there are, so that bin ranges can be reserved. The shader is “FRasterBinBuild_CS”, from NaniteCullRaster.cpp.

Raster Bins represent clusters to rasterize, per shader to support the programmable raster path. Ideally most clusters are rendered via Fixed Function paths, with exceptions from Materials using features like WPO and Masking. Each of these materials and Fixed Function rasters will create a unique bin.

ClearBuffer

If the clear you are mentioning is the clear between RasterBinCount and RasterBinReserve, it is clearing the buffer used to allocate bin ranges (“Nanite.RangeAllocatorBuffer”), and is about to be populated by RasterBinReserve.

RasterBinReserve

This pass reserves the raster bin ranges, based on how large each bin needs to be and the number of bins counted by RasterBinCount. The shader is “FRasterBinReserve_CS”, from NaniteCullRaster.cpp

HW Rasterize

This pass performs rasterization using the graphics pipeline (vertex or mesh shaders and pixel shaders) unlike SW Rasterize that runs using compute shaders. One draw call is issued per bin. See “FRenderer::AddPass_Rasterize(…)” for the usage, and “FRasterizePassParameters” for the parameter struct, both from NaniteCullRaster.cpp.

If you have specific questions about one or more of them, please do not hesitate to ask.

Please let us know if this helps.

Thanks for your response, these are really helpful.

This ticket can be closed