Vixen
dd8b0a81
csharp
public sealed class MorphRenderFeature

Blend shapes in the frame: a vertex buffer per morphed instance, and the pre-pass that fills it.

Read the guide page for this →

Remarks

The wiring MorphKernel and Pipeline/MorphScatter.rvn were built for and nothing had. Those two are the arithmetic, checked against each other on a device; this is what allocates the buffer, copies the rest pose into it, dispatches once per active shape and points VertexBuffer at the result. Without it a mesh with twenty blend shapes imported, stored, packed and dispatched-for still drew at rest, because nothing in a frame path had a buffer for the answer to go in.

The seam is MeshDraw, and that is what makes the passes agree. A draw record is per render object and every stage reads the same array, so overwriting one object's handle morphs its shading pass, its shadow pass, its velocity pass and its depth pre-pass together — by construction rather than by four features remembering to. That is doc 33 § D4's whole argument for a pre-pass, and it only holds because the handle is written in one place.

⚠ The vertices are per instance and the deltas are per mesh. Two characters wearing the same head share one entry run — 1.28 MB for a twenty-shape face, resident, as SizeInBytes reports — and have a vertex range each, because their weights differ. So the cost of a second instance is the mesh's vertices again and not its shapes: forty-eight bytes a vertex, which is why VertexCapacity is a budget the host sets rather than a number here.

⚠ The rest pose is copied out of the scene's own geometry buffer, not held twice. Source already has the mesh at BaseVertex and a device-to-device copy is what restores it, so the only extra vertex memory is the destination. What that costs instead is a state transition on a buffer the whole scene draws from — see Transition for why it is that type's to make and not this one's.

⚠ A vertex range is copied and dispatched only when its weights have changed, and the first frame counts as a change. A character standing still costs nothing; a character that has never been recorded costs a copy, because a dispatch onto an uninitialised range does not look like a morph gone wrong — it looks like the geometry is missing. Which is also why Attach marks the instance dirty rather than leaving the flag at its zero.

Fields and properties (21)

  • public static int VertexFloats

    How many floats one SurfaceVertex occupies.

  • public const int PositionFloat

    Where the position is within a vertex, in floats.

  • public const int NormalFloat

    Where the normal is within a vertex, in floats.

  • public const int GroupSize

    How many invocations one workgroup of the kernel has.

  • public override string Name

    The sub-feature's name, for logging and profiling.

  • public RenderDataKey<MorphInstance> Instances

    Where each object's morphed vertices are, and which shapes move them.

  • public EffectSystem? Effects

    Where variants are compiled. Unset, nothing is dispatched.

  • public ComputePipelineCache? Pipelines

    Where the compute pipeline comes from. Unset, nothing is dispatched.

  • public DescriptorAllocator? Descriptors

    Where a dispatch's descriptor set comes from. Unset, nothing is dispatched.

  • public GeometryBuffer? Source

    The buffer the rest pose is copied out of — the scene's shared geometry.

  • public BufferHandle Buffer

    The buffer the morphed vertices live in, or invalid until something has attached.

  • public int VertexCapacity

    How many morphed vertices the buffer holds.

  • public int EntryCapacity

    How many blend-shape entries it holds.

  • public int MeshCount

    How many distinct meshes have their shapes resident.

  • public int InstanceCount

    How many objects are being morphed.

  • public int UsedVertices

    How many vertices the attached instances occupy.

  • public int UsedEntries

    How many entries the resident meshes occupy.

  • public int Dispatches

    How many dispatches the last Record put in the frame.

  • public int Copies

    How many vertex ranges the last Record restored to the rest pose.

  • public int Dropped

    How many attachments were refused for want of room, since this feature was made.

  • public string? Degraded

    Why this frame morphed less than it was asked to, or null.

Methods (9)

  • public MorphRenderFeature(IGraphicsDevice device, int vertexCapacity = 65536, int entryCapacity = 262144)

    Creates the feature. The buffers wait until something with shapes is attached.

  • protected internal override void Initialize(RenderSystem system)

    Registers this sub-feature's per-object data. Called once.

  • public bool Attach(RenderSystem system, RenderObjectId id, GeometryKey key, MeshData mesh, in GeometrySlice rest, ref MeshDraw draw)

    Gives an object its own morphed copy of a mesh, and points its draw at it.

  • public bool SetWeights(RenderObjectId id, ReadOnlySpan<float> weights)

    Gives an object this frame's blend-shape weights.

  • public ReadOnlySpan<float> WeightsOf(RenderObjectId id)

    What an object's weights currently are.

  • public ReadOnlySpan<string> ShapesOf(RenderObjectId id)

    What an object's mesh calls each of its weight slots.

  • public bool Forget(RenderObjectId id)

    Gives up an object's morphed range, and its mesh's shapes with the last instance.

  • public bool Record(ICommandList list)

    Records this frame's pre-pass: the rest poses that need restoring, then a dispatch per active shape.

  • public void Dispose()

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

Used by (10)

  • PbrShowcaseGamePbrShowcase
  • CompositorImageTestsVixen.Graphics.Golden.Tests
  • IsolatedVixen.Rendering.Tests
  • MeshExtractionSystemVixen.Rendering
  • MorphRenderFeatureTestsVixen.Rendering.Tests
  • MorphScatterDeviceTestsVixen.Graphics.Golden.Tests
  • MorphWeightSystemVixen.Rendering
  • MorphedClusterTestsVixen.Rendering.Tests
  • WorldRendererVixen.Engine.Renderer
  • EditorWorldRendererVixen.Editor.App