Skip to main content

Module context

Module context 

Source
Expand description

Instance, adapter and lazy logical-device creation: RenderContext and DeviceHandle.

This is the crate’s entry point — everything else in frust-gpu consumes a DeviceHandle rather than reaching for a wgpu::Adapter itself. A RenderContext owns one wgpu::Instance and at most one logical device, created lazily on the first surface (or the first RenderContext::device call) and then reused: a logical device is display-independent, so surface loss and recreation (rotation, backgrounding) must not rebuild it.

This is also the type frust-render re-exports as its own frust_render::RenderContext, which is what every platform shell holds: the device/surface foundation lives here, and the renderer above adds only the render-path decisions specific to how a frame is drawn.

Surface creation itself lives in crate::surface and the raw-pointer constructors in crate::lifecycle; RenderContext::create_render_surface is the one entry point that ties them to a device.

§Pure decision vs. platform lookup

Every environment-sensitive choice here is split into a pure function taking the environment as an argument (effective_instance_flags, effective_limits, device_features, decide_log_action) plus a separate lookup that answers what the environment actually is (is_android_emulator, is_ios_simulator). Only the lookups are platform-gated, so the policies stay unit-testable on any host with no GPU and no mobile target in the loop — the same split crate::caps::TierCaps::probe/crate::caps::TierCaps::fake gives adapter capabilities.

§Two mitigations worth knowing about

  • The Android emulator cannot survive wgpu::InstanceFlags::DEBUG, so the instance is built with those flags stripped there and nowhere else (effective_instance_flags).
  • The iOS Simulator misreports its uniform-buffer alignment, so a device request made there is forced back up to 256 bytes (effective_limits).

§The Android hardware-buffer device

wgpu’s own request_device never enables VK_ANDROID_external_memory_android_hardware_buffer, so a device it opens can never import an AHardwareBuffer (crate::import). On Android, with the FRUST_ANDROID_HWBUFFER_IMPORT knob on (the compile-time or runtime environment variable, or the debug.frust.hwbuffer_import system property, any value but 0), a Vulkan device is instead opened by this module itself: the same features, limits and memory hints request_device would have been given, plus the import extensions (hwbuffer_import_extensions), through wgpu_hal::vulkan::Adapter::open_with_callback and wgpu::Adapter::create_device_from_hal. When any extension is missing the device is opened through wgpu as usual, and TierCaps::hwbuffer_import records which path produced it. Knob off — and on every other target — the device request is exactly the plain request_device one.

Structs§

ContextOptions
How a RenderContext should build its instance and request its device.
DeviceHandle
A logical device, the adapter it was created from, the queue that executes its command buffers, and the capabilities that adapter reported.
RenderContext
Owns the wgpu::Instance and the single logical device this crate’s consumers render with.

Enums§

LogAction
What the uncaptured-error handler should do for the count-th uncaptured error (1-indexed) it has observed on a given device.

Functions§

decide_log_action
Pure latch policy for the uncaptured-error handler (see LogAction).
effective_limits
Given a base wgpu::Limits and whether the process is currently running on an iOS Simulator, decides the Limits a device request should actually use.
is_ios_simulator
Whether this binary is running on the iOS Simulator (aarch64-apple-ios-sim / x86_64-apple-ios under the simulator), which sets target_abi = "sim". Compile-time constant: the simulator mitigation only needs to apply to simulator builds, never physical-device or desktop ones.
optional_device_features
The wgpu::Features a device request opportunistically asks for when the adapter exposes them.
test_device_limits
The wgpu::Limits a test fixture’s own request_device call should ask for, given adapter and its already-probed caps — exactly the derivation [create_device] uses for the production device request (shared via [base_device_limits] plus effective_limits), so a fixture requesting these limits can never over-ask relative to what the production path would request for the very same adapter.