Labs / QUBICENGINE HANDBOOK

Texture transfer & mipmaps

Step from a disk file to a sampled material, compare backend staging rules, and inspect prefiltered detail.

Inspect the relationship#

Step from a disk file to a sampled material, compare backend staging rules, and inspect prefiltered detail.

INTERACTIVE ILLUSTRATIONSIMULATION / BROWSER

Follow a texture to the GPU This illustration uses canvas. The explanation below describes the same process.

Change a control to inspect the result. Values describe the simulation, not native engine benchmarks. Open full lab ↗

Try these experiments#

  1. Step through all seven lifecycle stages and read the state explanation after each step.
  2. Scrub to a stage, press Play, and follow the transfer. Pause to inspect one owner boundary.
  3. Change mip level and compare texel dimensions, meaningful row bytes, and staging row bytes.
  4. Switch the backend. The lifecycle stays recognizable, while the displayed DX12 pitch and Vulkan tightly packed copy model differ.

What the illustration calculates#

The base checker is 128 × 128 RGBA8. Each mip halves its dimensions. At small levels the prefiltered image approaches the average rather than preserving detail that cannot be represented. DX12 rows are padded to the required upload RowPitch alignment. The Vulkan illustration uses a tightly packed VkBufferImageCopy case, not a universal native image-memory layout. Production resource copies use actual backend requirements. DX12 GetCopyableFootprints handles subresources and format layout. Vulkan copy descriptions use texel/block rules and explicit buffer offsets. Neither staging form is the same as a compressed PNG file.

Connect the stages to ownership#

AssetStore owns source identity and decode state. UploadManager owns staging and pending destinations. GraphicsDevice records copies, transitions, and completion. A material retains a stable handle and uses a fallback descriptor until a safe boundary publishes the ready resource.

Reference excerpt: existing texture and recording context, after a copy command has been recorded. Lifetime completion is tracked separately.

C++ / DIRECTX 12
// Destination texture: copied on this direct queue.
D3D12_RESOURCE_BARRIER b{};
b.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
b.Transition.pResource = texture;
b.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST;
b.Transition.StateAfter = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
b.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
list->ResourceBarrier(1, &b);

What readiness means#

Creating a GPU allocation is not sufficient. Its copy must be ordered before use, its usage/layout must permit sampling, its descriptor must be populated and bound, and its lifetime must cover all readers. Staging can retire after the copy completes; the sampled texture continues living while materials and in-flight frames reference it.

What to inspect when it is wrong#

Striped rows suggest a stride/pitch error. Washed-out color suggests encoded/linear confusion. Flicker after loading suggests a binding/lifetime issue. Missing fine detail can be a deliberate streaming fallback rather than failed import. Read assets and complete DX12 texture loading. The latter contains the actual WIC decode and native copy implementation.

Search titles and full article text.