Vixen
02b45cc4
csharp
public sealed class GrassDispatch

The host for GrassScatter.rvn: the cell records, the ring of device buffers, and the dispatch that fills them.

Read the guide page for this →

Remarks

[docs/plan/31 § T6]'s owed device half. GrassRenderer is the CPU reference — what a headless test and a machine with no compute queue use — and this is the dispatch that does the same arithmetic where a forest can afford it. Neither is the definition: Hash is, and both transliterate it.

⚠ One counter per cell, not one for the dispatch. A global head would serialise every invocation of every cell on one cache line, and it would make a cell's run depend on the order the workgroups happened to retire in — which is the one thing a scatter that has to be reproducible cannot afford.

⚠ The instance buffer is the ring, and its slots are assigned by the host. Each resident cell owns a fixed run, so an invocation never negotiates for space with another cell — only with the other candidates of its own. That is what makes the atomic local and the memory bounded.

⚠ The counts buffer is cleared before every dispatch and not after. A pass that cleared afterwards leaves the buffer holding last frame's numbers for anything that reads it in between — and what reads it is the indirect draw, which would then draw a cell's previous population out of its current bytes.

Fields and properties (12)

  • public const int GroupSize

    How many candidates a workgroup covers on each axis. `[ComputeShader(8, 8, 1)]`.

  • public static int DrawCommandBytes

    How many bytes one indirect command is — DrawIndexedIndirect's stride.

  • public int Capacity

    How many cells one dispatch may cover.

  • public DrawCommand Mesh

    What one blade is drawn with: its index count, its first index and its vertex offset.

  • public int BladesPerCell

    How many blades a cell's run holds.

  • public int CellCount

    How many cells the last Prepare wrote records for.

  • public long Ceiling

    How many blades the last dispatch could produce at most.

  • public (int X, int Y, int Z) Groups

    How many workgroups the last Prepare would dispatch, on each axis.

  • public int Refused

    How many cells were refused because the dispatch was full.

  • public BufferHandle Instances

    The buffer the draw reads its instances from.

  • public BufferHandle Counts

    And the one holding how many each cell produced.

  • public BufferHandle Commands

    And the indirect arguments the draw reads.

Methods (7)

  • public GrassDispatch(IGraphicsDevice device, ShaderHandle shader, ShaderHandle arguments, int capacity = 256, int bladesPerCell = 4096)

    Creates the pass and its buffers.

  • public int Prepare(in GrassType type, FoliageCellGrid grid, IReadOnlyList<GrassSlot> resident, in GrassTerrainSource terrain, float densityScale = 1)

    Writes the cell records and the constants for one grass type.

  • public int Record(ICommandList commands)

    Records the dispatch.

  • public int RecordDraws(ICommandList commandList)

    Issues one indirect draw per resident cell.

  • public long CommandOf(int index)

    Where a cell's indirect command is, for the draw that reads it.

  • public (long Offset, long Length) RunOf(int slot)

    Where a cell's blades are, for the draw that reads them.

  • public void Dispose()

    Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.

Used by (3)

  • GrassDispatchTestsVixen.Rendering.Terrain.Tests
  • GrassDrawPassVixen.Rendering.Terrain
  • GrassDrawPassTestsVixen.Rendering.Terrain.Tests