Vixen
caa30e12
csharp
public sealed class TextureStreamer

Mip tails in, a byte budget held, and the coarser picture when it cannot be.

Read the guide page for this →

Remarks

Doc 08's streaming manager, textures only, and the third consumer PageResidency was built for. The service owns the queue, the budget and the eviction order; TexturePagePool owns where the bytes go and how they are read; and this owns the one thing neither can know — what a frame actually wants, and therefore which pages to ask for.

What drives residency is a wanted width, and that is the narrowest seam that works. A caller says how many texels across it needs a texture to be — WantedWidth computes that from a bounding radius and a view, which is the same screen-coverage estimate mesh LOD selection uses — and this turns it into a level and asks for the pages that cover it. Sampling feedback would be a better signal and there is no feedback buffer to read; an authored per-texture priority would be a worse one, because it cannot know where the camera is. When a feedback buffer exists it replaces Want and nothing else.

What says the wanted width is TextureDemand. It surveys the frame's visible drawables, takes the maximum over every user of a texture, and quantises that onto a ladder of mip widths with a dead band — because a wanted width that oscillates at a level boundary is a swap on alternate frames, and a swap is an upload.

MipBias is consumed here rather than on the sampler, and that is a portability decision. SamplerDescription.LodBias reaches the API on Vulkan only — OpenGL drops it on every GLES profile and WebGPU has no such field — so a streamer that expressed pressure as a sampler bias would express it on one backend of three. A bias applied to the wanted width is arithmetic, works everywhere, and has the effect the knob is named for: a positive bias asks for a coarser tail and frees the budget it would have taken.

⚠ Eviction is least-recently-used over pages and not over textures. A page evicted from the middle of a texture's prefix drops that texture's resident level immediately, and leaves the pages above it resident and useless until they age out in their turn. That self-corrects — an unusable page is never touched, so it is the next victim — and the alternative is a second eviction policy that knows about textures, which is the beginning of the per-consumer budget this design exists to not have.

Fields and properties (10)

  • public long Budget

    How many bytes of mip tail may be resident at once.

  • public long ResidentBytes

    How many are.

  • public int PageSize

    How many bytes one page is.

  • public long Loads

    How many pages have been loaded since this was created.

  • public long Evictions

    How many have been evicted.

  • public long Rejections

    How many requests were dropped because nothing could be evicted to make room.

  • public int Loading

    How many loads are in flight.

  • public int PendingRequests

    How many requests are waiting.

  • public int Textures

    How many textures are registered.

  • public float MipBias

    Levels added to every wanted width, positive for coarser.

Methods (12)

  • public TextureStreamer(ITextureStreamSource source, long budgetBytes, int pageSize = 65536)

    Creates a streamer over a source, with a budget.

  • public bool Register(int texture, Ktx2Layout layout)

    Says a texture is streamable, and pins the page that is always resident.

  • public bool IsRegistered(int texture)

    Whether a texture is one this streams.

  • public int PinnedLevel(int texture)

    The coarsest level a texture is guaranteed, whatever the budget.

  • public int ResidentLevel(int texture)

    The largest level of a texture that is completely resident.

  • public void Want(int texture, int width)

    Asks for a texture at a width, and says its pages were used this frame.

  • public int Service(int maxLoads = 8)

    Places what has arrived and starts what there is room for.

  • public void ClearRequests()

    Drops every request that has not started. What a camera that jumped calls.

  • public int CopyTail(int texture, int firstLevel, Span<byte> destination)

    Copies a resident mip tail out of the pool, in file order.

  • public static int WantedWidth(float radius, float distance, float viewportHeight, float verticalFieldOfView)

    The texture width a view wants of an object it can see.

  • public static int WantedWidth(in BoundingSphere bounds, RenderView view, float viewportHeight)

    The same estimate, from the numbers a frame actually holds.

  • public void Dispose()

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

Used by (6)

  • ArenaThirdPersonShooter
  • AssetTextureSourceVixen.Engine.Renderer
  • AssetTextureStreamingTestsVixen.Engine.Renderer.Tests
  • TextureDemandVixen.Engine.Renderer
  • TextureDemandTestsVixen.Engine.Renderer.Tests
  • TextureStreamingTestsVixen.Engine.Renderer.Tests