Source code for simvx.graphics.gpu.context

"""GPU context: bundles core Vulkan handles used throughout the renderer."""

from typing import Any

from .commands import CommandContext

__all__ = ["GPUContext"]

[docs] class GPUContext: """Immutable bag of GPU handles shared across all renderer passes. Created once during Vulkan init and stored on Engine as ``engine.ctx``. Renderer passes should accept or store this rather than reaching into engine internals. """ __slots__ = ( "device", "physical_device", "graphics_queue", "present_queue", "graphics_qf", "cmd_ctx", "compute_queue", "transfer_queue", "compute_qf", "transfer_qf", "multi_gpu", "device_count", ) def __init__( self, device: Any, physical_device: Any, graphics_queue: Any, present_queue: Any, graphics_qf: int, cmd_ctx: CommandContext, compute_queue: Any = None, transfer_queue: Any = None, compute_qf: int | None = None, transfer_qf: int | None = None, multi_gpu: bool = False, device_count: int = 1, ) -> None: self.device = device self.physical_device = physical_device self.graphics_queue = graphics_queue self.present_queue = present_queue self.graphics_qf = graphics_qf self.cmd_ctx = cmd_ctx # Dedicated-queue handles + their family indices. All ``None`` on a # single-universal-family GPU (this dev box): the async-compute path is # disabled and every pass records into the primary graphics command # buffer exactly as before. self.compute_queue = compute_queue self.transfer_queue = transfer_queue self.compute_qf = compute_qf self.transfer_qf = transfer_qf # Explicit-multi-adapter state, mirrored from MultiDeviceManager. # ``multi_gpu`` is True only on an opted-in, >=2-device renderer; on this # box / unopted it is False and ``device_count`` is 1 (single-device path, # byte-identical). Read by the offload renderer to decide whether to # split SRUs across devices. self.multi_gpu = multi_gpu self.device_count = device_count
[docs] @property def command_pool(self) -> Any: """Shorthand for ``cmd_ctx.pool``.""" return self.cmd_ctx.pool
[docs] @property def async_compute(self) -> bool: """True when a dedicated compute queue exists (multi-queue GPU). The single capability gate every consumer reads: ``True`` selects the async-compute scheduler path (compute passes -> compute queue, graphics submit waits on a semaphore); ``False`` is the byte-identical single-queue fallback verified on this box. """ return self.compute_queue is not None
[docs] @property def concurrent_compute_families(self) -> list[int] | None: """Distinct ``[graphics_qf, compute_qf]`` for CONCURRENT buffers, or ``None`` when async-compute is off. Pass this to :func:`~simvx.graphics.gpu.memory.create_buffer`'s ``concurrent_families`` for any control buffer (indirect / visibility / light-grid / particle) that crosses the graphics<->compute boundary. ``None`` keeps those buffers EXCLUSIVE (unchanged single-queue path). """ if self.compute_queue is None or self.compute_qf is None: return None return [self.graphics_qf, self.compute_qf]