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]