Donner SVG main
0.8.0 ยท 382bd0190.8.0 main
SVG editor and embeddable C⁠+⁠+⁠20 engine.
Loading...
Searching...
No Matches
donner::gpu::vulkan::VulkanDevice Class Referencefinal

Vulkan backend of the Donner GPU runtime. More...

#include "donner/gpu/vulkan/VulkanDevice.h"

Inheritance diagram for donner::gpu::vulkan::VulkanDevice:
[legend]

Classes

struct  SystemCapabilities
 What the physical device Create selects supports, which every device it opens shares. More...
struct  RecordedImageBarrierForTest
 One image barrier the backend recorded, reported as plain numbers so this header stays free of Vulkan types. Test accessor: which barriers are emitted is the whole contract of the resource-state model, and it is not observable in the pixels a test reads back. More...
struct  NativeContextForTest
 Borrowed native objects for tests that submit their own synchronization gate. Valid only until this device is destroyed; callers must use the owning thread, release every gate, and finish their native work before destroying any of these objects or the device. More...
struct  BufferWriteStats
 Snapshot of queued buffer-write ownership, without polling the queue. More...
struct  SurfaceAcquisitionForTest
 What a surface's acquisition bookkeeping looks like from outside, for the contracts whose only other symptom is timing dependent. More...

Public Types

enum class  TrackedTextureLayout : uint8_t {
  Undefined ,
  General ,
  ShaderReadOnly ,
  TransferSrc ,
  TransferDst ,
  ColorAttachment ,
  Other
}
 The image layout a texture is tracked in, as the backend's own bookkeeping records it. More...
enum class  UploadFailureModeForTest : uint8_t {
  BeforeSubmit ,
  AfterSubmit
}
 Where an injected upload failure happens, which is what decides whether the transitions it recorded describe anything the GPU will run. More...

Public Member Functions

ShaderSourceKind shaderSourceKind () const override
 Native shader representation accepted by this device.
bool supportsFullIndexRange (IndexFormat format) const override
 True for Uint16 always; for Uint32 only when the physical device offered fullDrawIndexUint32 and Create enabled it, since without that feature index values above maxDrawIndexedIndexValue are undefined.
void disableFullUint32IndexRangeForTest ()
 Reports Uint32 as lacking its full range from now on, whatever the device enabled, so the refusal path runs on a device that has the feature. Only ever narrows the capability.
bool supportsPresentation () const
 Whether this device was created with presentation support. Test accessor, so a suite can say which device it is looking at rather than inferring it from a refusal.
void forceSurfaceRetirementUnprovenForTest ()
 Test seam: make the next external-surface destruction retain its native prerequisites. A test uses this only in a child process because the disposition is terminal.
void setBeforeExternalSurfaceQueryHookForTest (std::function< void()> hook)
 Test seam run after accepting an external surface but before its first Vulkan query.
void * nativeInstance () const
 The Vulkan instance this device was created on, for an embedder that creates its own surface.
 ~VulkanDevice () override
 Destructor.
uint64_t completedSerial () const override
 Serial of the most recent submission whose fence has signaled (0 if none). Polls pending fences with vkGetFenceStatus and advances a monotonic counter.
Result< std::vector< uint8_t > > readBackBuffer (const Buffer &buffer)
 Copies the full contents of buffer back to the host and returns the bytes.
Result< TrackedTextureLayout > trackedTextureLayoutForTest (const Texture &texture) const
 Returns the layout texture is tracked in.
Result< bool > hasNativeViewForTest (const TextureView &view) const
 Whether view has a native image view.
void setImageBarrierRecordingForTest (bool enabled)
 Enables an empty barrier history or disables recording and releases the history. Recording is disabled by default.
std::vector< RecordedImageBarrierForTest > recordedImageBarriersForTest () const
 Image barriers since recording was last enabled, oldest first; empty while disabled.
void failNextTextureUploadForTest (UploadFailureModeForTest mode)
 Makes the next internal texture upload report failure at mode, so a test can prove what the tracker is left holding in each case. Test seam; the upload's Vulkan work is recorded either way, only its reported result is replaced.
size_t pendingTextureUploadCountForTest () const
 Returns the number of timed-out uploads still owned by the device, without polling.
void deferTextureUploadPollingForTest (bool defer)
 Defers upload fence polling to exercise ownership before device teardown.
NativeContextForTest nativeContextForTest () const
 Returns borrowed native objects solely for deterministic backend synchronization tests.
void attachWorkForTeardownTest (bool upload, uint64_t fenceHandle, uint64_t commandBufferHandle)
 Adds fake pending native work to the real ownership graph, without submitting to a GPU.
VulkanSurfaceContext surfaceContextForTeardownTest () const
 Returns the fake device's borrowed native context and shared child lifetime token.
void attachSurfaceForTeardownTest (std::unique_ptr< VulkanSwapchain > surface)
 Attaches a real swapchain owner to the fake device teardown graph.
BufferWriteStats bufferWriteStatsForTest () const
 Returns the current queued-write counters without waiting or changing state.
void setBufferWriteByteBudgetForTest (uint64_t byteBudget)
 Lowers the combined pending/in-flight payload limit for deterministic budget tests.
void failNextSubmissionForTest (bool deviceLost=false)
 Makes the next native submission fail before it reaches the queue, after encoding finishes.
void setBeforeQueueSubmitHookForTest (std::function< void()> hook)
 Calls p hook after encoding and before queue submission while the root execution lock is held. Test-only, one-shot; a hook must not submit another device's work synchronously.
void setFenceWaitStepHookForTest (std::function< void()> hook)
 Calls hook each time a step of a fence wait times out, in a serial wait or a texture upload, before the wait checks the root's loss condition, so a test can declare a loss while a wait is known to be blocked. Test accessor; an empty function removes the hook.
Status pauseSubmissionsForTest ()
 Holds every command buffer submitted from now on, each waiting for its own turn in submission order until releasePausedCommandBuffersForTest lets it run, so a test can let one submission's command buffers run a few at a time. Each held command buffer goes to the queue as a submission of its own, and the last of them carries the submission's fence. Needs timeline semaphore support, as on a device from CreateWithTimelineSemaphoreForTest or over a root from CreateSharedRootWithTimelineSemaphoreForTest.
void releasePausedCommandBuffersForTest (uint64_t count)
 Lets the first count command buffers submitted since pauseSubmissionsForTest run and keeps the rest held. Callable from any thread while the device's own thread waits.
void resumeSubmissionsForTest ()
 Lets every held command buffer run and stops holding new ones. Safe when no pause is active.
void forceNextAcquireOutOfDateForTest (uint32_t surfaceSlotIndex)
 Makes the next acquisition on the surface at surfaceSlotIndex report the swapchain as out of date, so its rebuild-and-retry path runs. Test seam; see the swapchain's own note for why a headless surface needs one.
void forceMinimumImageCountOnceForTest (uint32_t surfaceSlotIndex)
 Makes the next swapchain creation for the surface at surfaceSlotIndex ask for the fewest images allowed, so a rebuild shrinks its acquisition ring. Test seam.
SurfaceAcquisitionForTest surfaceAcquisitionForTest (uint32_t surfaceSlotIndex) const
 Reads the acquisition bookkeeping of the surface at surfaceSlotIndex. Test accessor.
std::string lastErrorForTest () const
 First latched Vulkan failure observed during submission, polling, or waiting on fences (e.g. VK_ERROR_DEVICE_LOST), or an empty string if none occurred. Test/diagnostic accessor.
Public Member Functions inherited from donner::gpu::Device
virtual ~Device ()
 Destructor; expires the device-alive token (so handles that outlive the device release nothing) and frees all remaining resources. Backends that submit asynchronously must wait for in-flight submissions in their own destructor before backend state is torn down.
 Device (const Device &)=delete
Device & operator= (const Device &)=delete
 Device (Device &&)=delete
Device & operator= (Device &&)=delete
uint64_t deviceId () const
 Process-unique identity of this device (starts at 1, never reused). Baked into every handle for cross-device validation.
bool isLost () const
 True once the backend root this device drives has been declared lost, either by the backend's device-lost callback or by a bounded wait giving up on it.
DeviceLossSnapshot deviceLossSnapshot () const
 First-winner loss attribution, once its diagnostic fields have settled.
virtual RcString deviceLostReason () const
 Backend-provided loss reason, when the backend retains one. Empty otherwise.
void markLostAfterWaitTimeout (DeviceLostWaitSite site, std::chrono::milliseconds elapsed, const char *reason) const
 Declares this device's backend root lost because a bounded wait gave up, recording which wait it was and how long it actually ran.
Result< Buffer > createBuffer (const BufferDescriptor &descriptor)
 Creates a buffer.
Result< Texture > createTexture (const TextureDescriptor &descriptor)
 Creates a 2D texture.
Result< TextureDescriptor > textureDescriptor (const Texture &texture) const
 Returns the descriptor texture was created with, by value.
Result< TextureView > createTextureView (const Texture &texture, const TextureViewDescriptor &descriptor)
 Creates a view of texture covering the whole texture.
Result< Sampler > createSampler (const SamplerDescriptor &descriptor)
 Creates a sampler.
Result< BindGroupLayout > createBindGroupLayout (const BindGroupLayoutDescriptor &descriptor)
 Creates a bind group layout.
Result< BindGroup > createBindGroup (const BindGroupDescriptor &descriptor)
 Creates a bind group.
Result< PipelineLayout > createPipelineLayout (const PipelineLayoutDescriptor &descriptor)
 Creates a pipeline layout.
Result< ShaderModule > createShaderModule (const ShaderModuleDescriptor &descriptor)
 Creates a shader module from trusted generated source.
Result< RenderPipeline > createRenderPipeline (const RenderPipelineDescriptor &descriptor)
 Creates a render pipeline.
Result< ComputePipeline > createComputePipeline (const ComputePipelineDescriptor &descriptor)
 Creates a compute pipeline.
Status destroyBuffer (Buffer &&buffer)
 Destroys a buffer (see the destroy contract above).
Status destroyTexture (Texture &&texture)
 Destroys a texture (see the destroy contract above).
Status destroyTextureView (TextureView &&textureView)
 Destroys a texture view (see the destroy contract above).
Status destroySampler (Sampler &&sampler)
 Destroys a sampler (see the destroy contract above).
Status destroyBindGroupLayout (BindGroupLayout &&bindGroupLayout)
 Destroys a bind group layout (see the destroy contract above).
Status destroyBindGroup (BindGroup &&bindGroup)
 Destroys a bind group (see the destroy contract above).
Status destroyPipelineLayout (PipelineLayout &&pipelineLayout)
 Destroys a pipeline layout (see the destroy contract above).
Status destroyShaderModule (ShaderModule &&shaderModule)
 Destroys a shader module (see the destroy contract above).
Status destroyRenderPipeline (RenderPipeline &&renderPipeline)
 Destroys a render pipeline (see the destroy contract above).
Status destroyComputePipeline (ComputePipeline &&computePipeline)
 Destroys a compute pipeline (see the destroy contract above).
Status destroyBufferBacking (Buffer &&buffer)
 Destroys buffer and releases its backend allocation at once, rather than leaving the allocation to the backend's own collector.
Status destroyTextureBacking (Texture &&texture)
 Destroys texture and releases its backend allocation at once, the texture counterpart of destroyBufferBacking; a succession of resized render targets is where the deferred release shows up as retained memory.
bool ownsTextureBacking (const Texture &texture) const
 Whether texture names backing this device allocated, rather than memory some other owner holds and this device only named.
Result< TextureExport > exportTexture (const Texture &texture)
 Exports texture so another runtime device over the same backend device can register it.
Result< Texture > registerTexture (const TextureExport &source)
 Registers a texture another runtime device exported, as a read-only texture of this one.
bool waitForTextureSource (const Texture &registration, double timeoutSeconds)
 Waits until work naming registration may be submitted, the budget runs out, or either device is lost, and reports whether it may.
SerialWaitResult waitForTextureSourceUnlessStalled (const Texture &registration, std::chrono::milliseconds stallBound)
 waitForTextureSource for a caller whose bound exists to detect a hung producer: the wait gives up only once the producer has made no progress for stallBound, measured from that progress, rather than giving the producer's whole backlog a fixed budget.
uint64_t sharedTextureTailBytes () const
 Bytes of this device's exported textures that are still held by an export token or a registration after this device released its own handle.
Result< std::unique_ptr< CommandEncoder > > createCommandEncoder ()
 Creates a command encoder recording against this device. The encoder must not outlive the device.
Result< Surface > createSurface (const SurfaceDescriptor &descriptor)
 Creates a surface presenting to a platform object.
Result< SurfaceCapabilities > surfaceCapabilities (const Surface &surface) const
 What surface supports, for choosing a configuration.
Status configureSurface (const Surface &surface, const SurfaceConfiguration &configuration)
 Configures how surface presents, replacing any previous configuration.
Result< SurfaceTexture > acquireCurrentTexture (const Surface &surface)
 Acquires the texture for the next frame of surface.
Result< SurfaceStatus > presentSurface (const Surface &surface)
 Presents the texture acquired from surface and invalidates it.
Status abandonCurrentTexture (const Surface &surface)
 Releases the acquired texture of surface without presenting it, for a frame the caller decided not to show.
Status destroySurface (Surface &&surface)
 Destroys a surface (see the destroy contract above).
Result< BufferMapping > mapBufferAsync (const Buffer &buffer, MapMode mode, uint64_t offsetBytes, uint64_t byteCount)
 Begins mapping a range of buffer for host access, and returns the handle that names the mapping.
Result< MapSliceReport > pollMapping (const BufferMapping &mapping)
 Polls a mapping once without blocking or yielding; ready mappings become readable.
Result< MapWaitReport > waitForMapping (const BufferMapping &mapping, const MapWaitParams &params, const std::function< bool()> &shouldCancel, const MapWaitTestHooks &testHooks={})
 Waits for a pending mapping in slices, until it completes, the caller stops it, the budget runs out, or the device is lost.
Result< std::span< const uint8_t > > mappedBytes (const BufferMapping &mapping) const
 Returns the mapped bytes of a completed mapping.
Status unmapBuffer (BufferMapping &&mapping)
 Releases a mapping, invalidating the handle and every copy of it.
Status writeBuffer (const Buffer &buffer, uint64_t offsetBytes, std::span< const uint8_t > data)
 Writes data into buffer at offsetBytes.
Status writeTexture (const Texture &texture, std::span< const uint8_t > data, const TexelCopyBufferLayout &dataLayout, const Extent2d &writeSize, const Origin2d &destinationOrigin={})
 Writes texel rows from data into the writeSize rectangle of texture whose top-left texel is destinationOrigin, leaving every texel outside that rectangle unchanged.
Result< uint64_t > submit (CommandBuffer commandBuffer)
 Submits a finished command buffer, consuming it, and returns the assigned submission serial.
Result< uint64_t > submit (std::span< CommandBuffer > commandBuffers)
 Submits finished command buffers as one submission, consuming them, and returns the single assigned submission serial.
void poll ()
 Processes deferred destructions: releases the backend object of every destroyed resource whose last referencing submission has completed (completedSerial), and recycles its slot.
void pollCompletionOnce ()
 Drive one nonblocking backend completion iteration even when no resource destroy is pending.
bool hasPendingDestroys () const
 Whether a completed submission can still release a backend object. Owner-thread only.
uint64_t lastSubmittedSerial () const
 Serial assigned to the most recent submission (0 if none yet).
bool waitForSerial (uint64_t serial, double timeoutSeconds)
 Blocks until completedSerial reaches serial, timeoutSeconds elapses, or the backend gives up on the work, and reports whether the submission completed.
SerialWaitResult waitForSerialUnlessStalled (uint64_t serial, std::chrono::milliseconds stallBound)
 Blocks until completedSerial reaches serial, giving up only when the work the serial waits behind stops making progress.
std::optional< std::chrono::steady_clock::time_point > lastProgress ()
 When the work this device's submissions wait behind last made progress, or nothing when the backend has no notion of progress.
Status installObserver (DeviceObserver &observer)
 Installs observer to be notified of the work this device accepts (see DeviceObserver).
void removeObserver (const DeviceObserver &observer)
 Removes observer when it is the installed one and otherwise changes nothing, so an owner can only ever remove its own.
const DeviceObserver * observer () const
 The installed observer, or null when there is none.

Static Public Member Functions

static std::optional< SystemCapabilities > QuerySystemCapabilities ()
 Asks the physical device Create selects what it supports, without creating a logical device on it: a transient instance is created, the same physical device is chosen, and its limits are read before the instance is destroyed.
static std::shared_ptr< VulkanSharedRoot > CreateSharedRoot (std::shared_ptr< DeviceLostState > lostState=nullptr)
 Opens one headless native Vulkan root for several runtime devices.
static std::shared_ptr< VulkanSharedRoot > CreateSharedRootWithPresentationSupport (std::span< const char *const > requiredInstanceExtensions, std::shared_ptr< DeviceLostState > lostState=nullptr)
 Opens one shared root with VK_KHR_swapchain and the instance extensions the embedder needs to make a window-system surface. The extension names are borrowed until this call returns; unsupported names fail selection instead of falling back to a headless root.
static std::unique_ptr< VulkanPresentationProbe > CreatePresentationProbe (std::span< const char *const > requiredInstanceExtensions, std::shared_ptr< DeviceLostState > lostState=nullptr)
 Opens only a presentation-capable instance so an embedder can make its native surface.
static std::shared_ptr< VulkanSharedRoot > CompletePresentationRoot (VulkanPresentationProbe &probe, uint64_t surfaceHandle)
 Selects a presenting physical device and graphics queue for the probe's actual surface. No logical device is created when the surface has no compatible candidate.
static std::shared_ptr< VulkanSharedRoot > CreateSharedRootWithTimelineSemaphoreForTest (std::shared_ptr< DeviceLostState > lostState=nullptr)
 Opens a shared root with timeline-semaphore support solely for native queue-gate tests. Returns null when the test extension or physical-device feature is unavailable.
static std::unique_ptr< VulkanDevice > CreateOverSharedRoot (const std::shared_ptr< VulkanSharedRoot > &root)
 Opens a runtime device with independent resources and serials over root.
static std::unique_ptr< VulkanDevice > Create (std::shared_ptr< DeviceLostState > lostState=nullptr)
 Creates a headless device: a VkInstance without surface extensions (enabling VK_LAYER_KHRONOS_validation only when the loader enumerates it), the first physical device exposing a graphics queue family, and a single VkDevice + VkQueue.
static std::unique_ptr< VulkanDevice > CreateWithTimelineSemaphoreForTest (std::shared_ptr< DeviceLostState > lostState=nullptr)
 Creates a device with VK_KHR_timeline_semaphore enabled solely for test-owned host gates. Returns nullptr if the test extension/feature is unavailable; ordinary Create needs neither.
static std::unique_ptr< VulkanDevice > CreateWithPresentationSupport (std::span< const char *const > requiredInstanceExtensions={}, std::shared_ptr< DeviceLostState > lostState=nullptr)
 Creates a device that can present: an instance with the surface extensions the loader offers and a device with VK_KHR_swapchain enabled.
static std::unique_ptr< VulkanDevice > CreateForTeardownTest (const VulkanApi *api, uint64_t instanceHandle, uint64_t deviceHandle, uint64_t commandPoolHandle, void(*onAdmission)(void *)=nullptr, void *admissionContext=nullptr, std::shared_ptr< DeviceLostState > lostState=nullptr)
 Builds an otherwise-empty device owner around fake native handles for teardown tests.
static bool CreateNativeObjectsForPresentationTest (const VulkanApi &api, bool enablePresentation, std::span< const char *const > requiredInstanceExtensions={}, uint64_t surfaceHandle=0)
 Exercises native instance/device creation through a fake API and immediately destroys them.

Protected Member Functions

Status onCreateBuffer (uint32_t slotIndex, const BufferDescriptor &descriptor) override
 Backend hook: a buffer passed validation and occupies slotIndex.
Status onCreateTexture (uint32_t slotIndex, const TextureDescriptor &descriptor) override
 Backend hook: a texture passed validation and occupies slotIndex.
bool onOwnsTextureBacking (uint32_t slotIndex) const override
 Backend hook: whether slotIndex holds backing this device allocated.
BackendDeviceIdentity backendDeviceIdentity () const override
 Backend hook: which backend family this device belongs to and which native device it records against, for matching an export against a registering device.
Result< BackendTextureExport > onExportTexture (uint32_t slotIndex) override
 Backend hook: export the texture in slotIndex, which the runtime has already validated as a live texture this device allocated and no surface has out.
Status onRegisterTexture (uint32_t slotIndex, const ExportedTextureBacking &backing) override
 Backend hook: name another device's exported texture in slotIndex.
Status onCreateTextureView (uint32_t slotIndex, uint32_t textureSlotIndex, const TextureViewDescriptor &descriptor) override
 Backend hook: a texture view passed validation and occupies slotIndex.
Status onCreateSampler (uint32_t slotIndex, const SamplerDescriptor &descriptor) override
 Backend hook: a sampler passed validation and occupies slotIndex.
Status onCreateBindGroupLayout (uint32_t slotIndex, const BindGroupLayoutDescriptor &descriptor) override
 Backend hook: a bind group layout passed validation and occupies slotIndex.
Status onCreateBindGroup (uint32_t slotIndex, const BindGroupDescriptor &descriptor) override
 Backend hook: a bind group passed validation and occupies slotIndex.
Status onCreatePipelineLayout (uint32_t slotIndex, const PipelineLayoutDescriptor &descriptor) override
 Backend hook: a pipeline layout passed validation and occupies slotIndex.
Status onCreateShaderModule (uint32_t slotIndex, const ShaderModuleDescriptor &descriptor) override
 Backend hook: a shader module passed validation and occupies slotIndex.
Status onCreateRenderPipeline (uint32_t slotIndex, const RenderPipelineDescriptor &descriptor) override
 Backend hook: a render pipeline passed validation and occupies slotIndex.
Status onCreateComputePipeline (uint32_t slotIndex, const ComputePipelineDescriptor &descriptor) override
 Backend hook: a compute pipeline passed validation and occupies slotIndex.
void onRetireBuffer (uint32_t slotIndex) override
 Backend hook: a buffer handle was retired. Discard unsubmitted work, but keep native resources alive until onDestroyResource.
void onDestroyResource (std::string_view resourceName, uint32_t slotIndex) override
 Backend hook: a retired resource is no longer used by submitted work and can be released.
Status onWriteBuffer (uint32_t slotIndex, uint64_t offsetBytes, std::span< const uint8_t > data) override
 Backend hook: a validated buffer write.
Status onWriteTexture (uint32_t slotIndex, std::span< const uint8_t > data, const TexelCopyBufferLayout &dataLayout, const Extent2d &writeSize, const Origin2d &destinationOrigin) override
 Backend hook: a validated texture write. The written rectangle is writeSize texels wide and tall with its top-left texel at destinationOrigin; texels outside it keep their contents.
Status onSubmit (uint64_t submissionSerial, std::span< const SubmittedCommandBuffer > commandBuffers) override
 Backend hook: validated command buffers were submitted as one submission.
Status onCreateSurface (uint32_t slotIndex, const SurfaceDescriptor &descriptor) override
 Backend hook: create a surface for a platform object.
Result< SurfaceCapabilities > onSurfaceCapabilities (uint32_t slotIndex) const override
 Backend hook: what a surface supports.
Status onConfigureSurface (uint32_t slotIndex, const SurfaceConfiguration &configuration) override
 Backend hook: apply a configuration.
Result< SurfaceStatus > onAcquireCurrentTexture (uint32_t slotIndex, uint32_t textureSlotIndex) override
 Backend hook: acquire the next frame's texture and report the surface's state.
Result< SurfaceStatus > onPresentSurface (uint32_t slotIndex) override
 Backend hook: present the acquired texture.
void onAbandonCurrentTexture (uint32_t slotIndex) override
 Backend hook: drop the acquired texture without presenting.
void onDestroySurface (uint32_t slotIndex) override
 Backend hook: release the platform state of a surface that is going away.
Status onMapBufferAsync (uint32_t mappingSlotIndex, uint32_t bufferSlotIndex, MapMode mode, uint64_t offsetBytes, uint64_t byteCount) override
 Backend hook: begin mapping a buffer range.
MapSliceReport onWaitMappingSlice (uint32_t mappingSlotIndex, double sliceSeconds) override
 Backend hook: wait up to sliceSeconds for a pending mapping, and report what it found and how it spent the slice.
bool onWaitForSerial (uint64_t serial, double timeoutSeconds) override
 Blocks on the pending submission's fence with vkWaitForFences, so the wait is woken by the submission completing rather than by rechecking.
SerialWaitResult onWaitForSerialUnlessStalled (uint64_t serial, std::chrono::milliseconds stallBound) override
 Waits for the fence of the submission covering serial while the queue shared by every device over this root keeps making progress (see VulkanQueueProgress): the work ahead of the serial includes other devices' work, so their command buffers finishing counts too.
std::optional< std::chrono::steady_clock::time_point > onLastProgress () override
 When the queue shared by every device over this root was last seen to make progress: a command buffer finishing, or work submitted while no tracked work was outstanding. Progress is timed when it is first seen, which this call also looks for; see VulkanQueueProgress.
Result< std::span< const uint8_t > > onMappedBytes (uint32_t mappingSlotIndex) const override
 Backend hook: bytes of a completed mapping.
void onUnmapBuffer (uint32_t mappingSlotIndex) override
 Backend hook: release a mapping.
Protected Member Functions inherited from donner::gpu::Device
 Device ()
 Constructor for backends; assigns the process-unique device identity.
virtual void onPollBackend ()
 One nonblocking backend event iteration before a pending-destroy scan. Native devices report completion directly; callback-driven adapters override this hook.
void adoptLostState (std::shared_ptr< DeviceLostState > state)
 Adopts the sticky loss condition of a backend root this device shares with another device.
uint64_t bufferLastUseSerial (uint32_t slotIndex) const
 Last accepted submission referencing a buffer slot already validated by the caller.
uint64_t textureLastUseSerial (uint32_t slotIndex) const
 Last accepted submission referencing a texture slot already validated by the caller.
virtual void onRetireTexture (uint32_t slotIndex)
 Backend hook: a texture handle was retired. Discard unsubmitted work, but keep native resources alive until onDestroyResource.
virtual void onDestroyBufferBacking (uint32_t slotIndex)
 Backend hook: destroyBufferBacking validated slotIndex and is about to destroy its handle; release the allocation now rather than when the slot is recycled.
virtual void onDestroyTextureBacking (uint32_t slotIndex)
 Backend hook: the texture counterpart of onDestroyBufferBacking, with the same default. A slot whose backing this device does not own keeps its allocation.
virtual bool onTextureWritePending (uint32_t slotIndex) const
 Backend hook: whether the write writeTexture just accepted for slotIndex is waiting for this device's next submission, rather than complete or ordered on the queue already.
Status validateBufferHandleForBackend (const Buffer &buffer) const
 Validates a buffer handle for backend-provided auxiliary entry points (test readback helpers and similar), running the same null/device-identity/generation checks the template-method public API performs before its hooks.
Status validateTextureHandleForBackend (const Texture &texture) const
 Validates a texture handle for backend-provided auxiliary entry points, running the same null/device-identity/generation checks the template-method public API performs.
Status validateTextureViewHandleForBackend (const TextureView &textureView) const
 Validates a texture view handle for backend-provided auxiliary entry points: the view itself plus a re-resolution of its viewed texture, so a view of a destroyed (or slot-recycled) texture fails closed exactly like it does on the normal Device paths.
Status validateBufferMappingHandleForBackend (const BufferMapping &mapping) const
 Validates a buffer-mapping handle for backend-provided auxiliary entry points, running the same null/device-identity/generation checks the template-method public API performs, so a stale handle cannot read state belonging to the slot's new occupant.
uint64_t lastTextureUseSerial (uint32_t textureSlotIndex) const
 Serial of the last submission that referenced the texture at textureSlotIndex, or 0 when nothing has submitted work naming it.
virtual Status onSubmitAfterSources (uint64_t submissionSerial, std::span< const SubmittedCommandBuffer > commandBuffers, std::span< const SourceWait > waits)
 Backend hook: onSubmit for a submission that must also wait on the device, before any of its work runs, for producer work it names through registrations ordered on the device (SourceOrdering::WaitOnDevice).
virtual uint64_t onTextureWriteByteCount (std::span< const uint8_t > data) const
 Backend hook: the bytes the write onWriteTexture just accepted handed the backend's queue, which DeviceObserver::onTextureWritten reports.
void notifyObserverOfBackendSubmission () const
 Reports a queue submission the backend made on its own, outside submit, to the installed observer as a submission of no command buffers and no draws.

Friends

class VulkanSwapchainTestAccess

Additional Inherited Members

Static Public Attributes inherited from donner::gpu::Device
static constexpr size_t kMaxCommandBuffersPerSubmission = 256
 Most command buffers one submission may carry.
static constexpr double kMaxWaitSeconds = 1.0e6
 Longest a single waitForSerial may block, in seconds. A budget above this is clamped to it; the value is far past any deadline a caller has, and keeps the conversion to the clock's own duration from overflowing on a caller that means "wait indefinitely" and says so with a very large number.

Detailed Description

Vulkan backend of the Donner GPU runtime.

Inherits every fail-closed validation check from donner::gpu::Device; the on* hooks receive only validated input and translate it to Vulkan objects. Every Vulkan call's VkResult is checked and any failure fails closed with a donner::gpu::GpuError; the backend never crashes on such failures.

Scope: buffers and 2D single-sample textures, SPIR-V shader modules, render pipelines with vertex buffer layouts, render passes with color attachments, scissors and viewports, non-indexed and indexed draws, compute pipelines and passes, texture-to-buffer and texture-to-texture copies, queue writes, host buffer mapping, and surface presentation. Bind group index N maps directly to Vulkan descriptor set N; binding numbers map directly to SPIR-V binding decorations.

Targets Vulkan 1.1 core only: classic VkRenderPass + VkFramebuffer (no dynamic rendering), per-submission VkFence completion tracking, and the core negative-viewport-height feature (VK_KHR_maintenance1, promoted to 1.1) to present WebGPU clip-space semantics - identical SPIR-V positions land on the same pixels as in WebGPU clip space. Presentation additionally requires swapchain maintenance1 and its matching instance extension dependencies. The headless path needs no device extension; CreateWithTimelineSemaphoreForTest optionally requests VK_KHR_timeline_semaphore so a test can hold a submission open.

Every buffer lives in HOST_VISIBLE | HOST_COHERENT memory and stays persistently mapped. Idle queue writes copy directly. Four-byte-aligned writes to busy buffers copy their payload into a bounded queue, flushed in order before the next ordinary submission, including empty command streams. Unaligned writes wait for that buffer's prior submission until the queue has made no progress for five seconds, which refuses the write without changing its bytes. Pending and in-flight write payloads share a 1 GiB budget, and at most 16,384 distinct ranges may be pending. Identical ranges coalesce at the newest write's position, preserving overlap order.

Readback waits for the buffer's last use before reading mapped memory; a stalled queue or a device error returns an error without copying any bytes. Queued writes become visible after the subsequent submission completes. Staging and destination allocations remain alive until its fence signals, including destinations absent from the public command stream. Terminal queue submission loss is latched before cleanup, and the device is drained before submitted objects are freed. Vulkan requires this lost-device idle wait to return finitely, but the wait has no caller-configured deadline. Later host accesses and submissions return the latched error.

A device takes part in the loss condition of the root it opens over (see Create). A device-lost result from the driver declares that condition, as a backend-reported loss, before the error is latched; serial waits, texture uploads and mappings end as soon as any device over the root has declared it.

Serial waits, host access to busy buffers and teardown of tracked submissions judge a stall by observed ordinary command-buffer events on the shared queue (see VulkanQueueProgress). Events from other devices over the root also renew the bound, so an ordinary command backlog is not cut off while those events keep completing.

Texture uploads submit no progress event. Their waits use the last observed tracked event, or the upload's submission time when no tracked work is outstanding: 60 seconds for an upload call and five seconds for teardown. Tracked events can extend that deadline; an upload fence signalling cannot. Sequential upload-fence waits share that clock, so a later wait can already have exhausted its bound when an earlier upload completes. A swapchain's present-completion wait and teardown after a submission whose completion is unknown instead use a fixed budget for the whole wait.

Several runtime devices can open over one VulkanSharedRoot (CreateOverSharedRoot). An owned texture exported from one registers on another as a read-only alias of the same VkImage, ordered by the shared queue. An image of another root is refused, and so is an acquired swapchain frame, which presentation can recycle.

Which allocation a buffer is bound into is the allocator's decision, behind the seam in VulkanBufferAllocator.h: one dedicated allocation per buffer today, with a suballocating implementation replaceable there rather than at every call site, once measurement says the driver's allocation-count cap is the constraint worth spending complexity on. Such a memory type is guaranteed by the Vulkan specification ("Device Memory": at least one memory type has both HOST_VISIBLE and HOST_COHERENT), and both the CI software rasterizer and desktop GPUs expose it. Textures are DEVICE_LOCAL (when available) with staged uploads through a transient host-visible buffer and explicit image layout transitions.

Synchronization is tracked per image: barriers before and after render passes, dispatches, and copies come from VulkanResourceState.h. Render-pass attachment layouts stay fixed, so explicit image barriers provide the dependencies without varying render-pass compatibility. Unknown usage falls back to an ALL_COMMANDS barrier. Readback copies also end in a HOST-domain buffer barrier.

Barrier elision - dropping a barrier the model says is needed - is still not attempted; that would need counter and timing evidence naming the bottleneck it removes.

Presentation is opt in through CreateWithPresentationSupport, because a swapchain has to be requested before any surface exists. Frames come from a VK_KHR_swapchain swapchain over a surface the embedder's platform object names, or over a headless surface where there is no window; a frame is acquired with a semaphore the first submission writing it waits on, and is handed to the presentation engine by a barrier submitted after that work. A frame that is discarded rather than presented cannot be given back, so the swapchain is recreated to reclaim it. Everything above is inert on a device created by Create, which refuses every surface.

Threading: each runtime device is single-threaded, matching donner::gpu::Device's affinity; devices over one root serialize their shared queue submissions and presentations. Completion is tracked by polling per-submission fences from the owning thread; there are no cross-thread callbacks. Creation is serialized against failed shutdown: if a bounded completion wait cannot prove native work finished, the complete device graph is retained until process exit and every later Vulkan device creation returns nullptr. Restart the process to retry Vulkan.

The header is pure C++ (Vulkan state lives behind a pimpl) so it is includable without the Vulkan headers on any platform; the implementation compiles against the hermetic Vulkan-Headers module everywhere but can only link and execute where a Vulkan loader exists (Linux in CI).


Class Documentation

◆ donner::gpu::vulkan::VulkanDevice::SystemCapabilities

struct donner::gpu::vulkan::VulkanDevice::SystemCapabilities

What the physical device Create selects supports, which every device it opens shares.

Class Members
uint32_t maxTextureDimension2D = 0 Largest width or height of a 2D texture the physical device allocates, from its maxImageDimension2D limit and capped at kMaxTextureDimension, the largest extent the runtime accepts.

◆ donner::gpu::vulkan::VulkanDevice::RecordedImageBarrierForTest

struct donner::gpu::vulkan::VulkanDevice::RecordedImageBarrierForTest

One image barrier the backend recorded, reported as plain numbers so this header stays free of Vulkan types. Test accessor: which barriers are emitted is the whole contract of the resource-state model, and it is not observable in the pixels a test reads back.

Class Members
uint32_t dstAccess = 0 Access made visible.
uint32_t dstStage = 0 Destination pipeline stage mask.
int32_t newLayout = 0 Layout the image moved to.
int32_t oldLayout = 0 Layout the image was in.
uint32_t srcAccess = 0 Access made available.
uint32_t srcStage = 0 Source pipeline stage mask.
uint32_t textureSlot = 0 Slot of the texture the barrier applies to.

◆ donner::gpu::vulkan::VulkanDevice::NativeContextForTest

struct donner::gpu::vulkan::VulkanDevice::NativeContextForTest

Borrowed native objects for tests that submit their own synchronization gate. Valid only until this device is destroyed; callers must use the owning thread, release every gate, and finish their native work before destroying any of these objects or the device.

Class Members
const VulkanApi * api Device entry points, owned by this device.
void * device Borrowed VkDevice.
void * instance Borrowed VkInstance, for a test that stands in for an embedder.
void * queue Borrowed VkQueue.
uint32_t queueFamilyIndex Family of the borrowed queue.

◆ donner::gpu::vulkan::VulkanDevice::BufferWriteStats

struct donner::gpu::vulkan::VulkanDevice::BufferWriteStats

Snapshot of queued buffer-write ownership, without polling the queue.

Class Members
uint64_t inFlightBytes = 0 Packed staging bytes retained until fence completion.
uint64_t lostDeviceDrains = 0 Lost-device submission drains completed before cleanup.
uint64_t pendingBytes = 0 Owned payload bytes awaiting submission.
size_t pendingWrites = 0 Coalesced writes awaiting an ordinary submission.
size_t retainedDestinations = 0 Retired destinations retained by outstanding uploads.
uint64_t stagingAllocations = 0 Successful staging allocations, including failed submits.
uint64_t submittedBatches = 0 Accepted submissions containing queued writes.

◆ donner::gpu::vulkan::VulkanDevice::SurfaceAcquisitionForTest

struct donner::gpu::vulkan::VulkanDevice::SurfaceAcquisitionForTest

What a surface's acquisition bookkeeping looks like from outside, for the contracts whose only other symptom is timing dependent.

Class Members
size_t frameRingSlot = 0 Ring slot the frame it holds was acquired on.
optional< size_t > lastFencedRingSlot Ring slot its last handover fenced.
bool live = false Whether that slot holds a surface at all.
bool owesAcquireWait = false Whether it still owes its frame's acquisition wait.
size_t ringSize = 0 Slots in its acquisition ring.

Member Enumeration Documentation

◆ TrackedTextureLayout

The image layout a texture is tracked in, as the backend's own bookkeeping records it.

Reported through a backend-neutral enum so the header stays free of Vulkan types. This is a test accessor: a texture the backend never transitioned to the layout its descriptors declare is invalid use that a permissive driver executes anyway, so the mistake is not observable in the pixels a test reads back.

Enumerator
Undefined 

Never transitioned; contents undefined.

General 

Readable and writable, the layout a storage-texture binding declares.

ShaderReadOnly 

The layout a sampled-texture binding declares.

TransferSrc 

Source of a copy.

TransferDst 

Destination of a copy or upload.

ColorAttachment 

Bound as a render pass color attachment.

Other 

Any layout this enum does not name.

◆ UploadFailureModeForTest

Where an injected upload failure happens, which is what decides whether the transitions it recorded describe anything the GPU will run.

Enumerator
BeforeSubmit 

The upload fails before anything reaches the queue, so its recorded work never runs.

AfterSubmit 

The submission reaches the queue and the wait for it reports a timeout, so its recorded work is still pending and will run.

Constructor & Destructor Documentation

◆ ~VulkanDevice()

donner::gpu::vulkan::VulkanDevice::~VulkanDevice ( )
override

Destructor.

Proves this device's own work complete before releasing any of its objects: it waits on outstanding tracked submission fences while ordinary command-buffer events renew the shared queue's five-second stall bound. Upload fences use the same last-progress clock, but upload completions do not renew it; a later upload-fence wait can therefore already have exhausted the bound when an earlier upload completes. It also prepares each of its surfaces, including any whose explicit destruction failed. After a submission whose completion is unknown, each submission and upload fence wait is bounded to five seconds in all instead. A loss declared over the root does not end these waits: only a signalled fence, or a wait the driver reports as device loss, proves the work complete. It then destroys its Vulkan objects in dependency order and releases its reference to the shared root. The root's instance, logical device and queue go when the root's last holder releases it, so other devices over the same root are not torn down and their fences are not waited on. If completion cannot be proved, this device's complete native graph is retained until process exit and later Vulkan device creation is refused.

Member Function Documentation

◆ attachWorkForTeardownTest()

void donner::gpu::vulkan::VulkanDevice::attachWorkForTeardownTest ( bool upload,
uint64_t fenceHandle,
uint64_t commandBufferHandle )

Adds fake pending native work to the real ownership graph, without submitting to a GPU.

Parameters
uploadWhether this is an internal texture upload instead of an ordinary submission.
fenceHandleNonzero fake fence.
commandBufferHandleNonzero fake command buffer.

◆ backendDeviceIdentity()

BackendDeviceIdentity donner::gpu::vulkan::VulkanDevice::backendDeviceIdentity ( ) const
nodiscardoverrideprotectedvirtual

Backend hook: which backend family this device belongs to and which native device it records against, for matching an export against a registering device.

The default names nothing, which is the answer for a backend whose runtime devices never share a native device.

Reimplemented from donner::gpu::Device.

◆ completedSerial()

uint64_t donner::gpu::vulkan::VulkanDevice::completedSerial ( ) const
overridevirtual

Serial of the most recent submission whose fence has signaled (0 if none). Polls pending fences with vkGetFenceStatus and advances a monotonic counter.

Implements donner::gpu::Device.

◆ CompletePresentationRoot()

std::shared_ptr< VulkanSharedRoot > donner::gpu::vulkan::VulkanDevice::CompletePresentationRoot ( VulkanPresentationProbe & probe,
uint64_t surfaceHandle )
static

Selects a presenting physical device and graphics queue for the probe's actual surface. No logical device is created when the surface has no compatible candidate.

Parameters
probeLive provisional instance used to create the surface.
surfaceHandleNative VkSurfaceKHR bits owned by the embedder.

◆ Create()

std::unique_ptr< VulkanDevice > donner::gpu::vulkan::VulkanDevice::Create ( std::shared_ptr< DeviceLostState > lostState = nullptr)
static

Creates a headless device: a VkInstance without surface extensions (enabling VK_LAYER_KHRONOS_validation only when the loader enumerates it), the first physical device exposing a graphics queue family, and a single VkDevice + VkQueue.

Returns nullptr if no Vulkan 1.1 instance or graphics-capable physical device is available.

Parameters
lostStateLoss condition of the backend root this device opens over, shared with every other device over that root. A device given none keeps a private condition.

◆ CreateForTeardownTest()

std::unique_ptr< VulkanDevice > donner::gpu::vulkan::VulkanDevice::CreateForTeardownTest ( const VulkanApi * api,
uint64_t instanceHandle,
uint64_t deviceHandle,
uint64_t commandPoolHandle,
void(* onAdmission )(void *) = nullptr,
void * admissionContext = nullptr,
std::shared_ptr< DeviceLostState > lostState = nullptr )
static

Builds an otherwise-empty device owner around fake native handles for teardown tests.

Parameters
apiCopied native callbacks.
instanceHandleFake instance.
deviceHandleFake device.
commandPoolHandleFake command pool.
onAdmissionOptional callback invoked while holding the creation gate.
admissionContextOpaque argument for the admission callback.
lostStateLoss condition of the root the device opens over, as for Create.

◆ CreateNativeObjectsForPresentationTest()

bool donner::gpu::vulkan::VulkanDevice::CreateNativeObjectsForPresentationTest ( const VulkanApi & api,
bool enablePresentation,
std::span< const char *const > requiredInstanceExtensions = {},
uint64_t surfaceHandle = 0 )
static

Exercises native instance/device creation through a fake API and immediately destroys them.

Parameters
apiFake Vulkan callbacks.
enablePresentationWhether to enable presentation.
requiredInstanceExtensionsEmbedder-required extension names.
surfaceHandleFake external surface to require presentation support for, or zero.

◆ CreateOverSharedRoot()

std::unique_ptr< VulkanDevice > donner::gpu::vulkan::VulkanDevice::CreateOverSharedRoot ( const std::shared_ptr< VulkanSharedRoot > & root)
static

Opens a runtime device with independent resources and serials over root.

Parameters
rootNative owner every device over this root retains.
Returns
Runtime device, or null when creation is refused or the root is null.

◆ CreatePresentationProbe()

std::unique_ptr< VulkanPresentationProbe > donner::gpu::vulkan::VulkanDevice::CreatePresentationProbe ( std::span< const char *const > requiredInstanceExtensions,
std::shared_ptr< DeviceLostState > lostState = nullptr )
static

Opens only a presentation-capable instance so an embedder can make its native surface.

Parameters
requiredInstanceExtensionsSurface extensions required by the embedder.
lostStateLoss condition shared by the completed root and its runtime devices.

◆ CreateSharedRoot()

std::shared_ptr< VulkanSharedRoot > donner::gpu::vulkan::VulkanDevice::CreateSharedRoot ( std::shared_ptr< DeviceLostState > lostState = nullptr)
static

Opens one headless native Vulkan root for several runtime devices.

Parameters
lostStateShared loss condition, or null for a private new condition.
Returns
Root with one instance, logical device and queue, or null on selection failure.

◆ CreateSharedRootWithPresentationSupport()

std::shared_ptr< VulkanSharedRoot > donner::gpu::vulkan::VulkanDevice::CreateSharedRootWithPresentationSupport ( std::span< const char *const > requiredInstanceExtensions,
std::shared_ptr< DeviceLostState > lostState = nullptr )
static

Opens one shared root with VK_KHR_swapchain and the instance extensions the embedder needs to make a window-system surface. The extension names are borrowed until this call returns; unsupported names fail selection instead of falling back to a headless root.

Parameters
requiredInstanceExtensionsNUL-terminated extension names the embedder requires.
lostStateShared loss condition, or null for a private new condition.

◆ CreateWithPresentationSupport()

std::unique_ptr< VulkanDevice > donner::gpu::vulkan::VulkanDevice::CreateWithPresentationSupport ( std::span< const char *const > requiredInstanceExtensions = {},
std::shared_ptr< DeviceLostState > lostState = nullptr )
static

Creates a device that can present: an instance with the surface extensions the loader offers and a device with VK_KHR_swapchain enabled.

Returns nullptr when the loader offers no surface extension or the device no swapchain support.

Presentation is opt in because a swapchain has to be asked for before any surface exists: the device has to already carry swapchain support by the time createSurface is called, and a device created by Create refuses every surface rather than appearing to support one. Whether the queue can present to a particular surface is checked when that surface is created, since that is the first point at which the question can be asked.

Parameters
requiredInstanceExtensionsPlatform surface extensions the embedder needs enabled on the returned instance. The span and each non-null, NUL-terminated name it contains are borrowed synchronously and must remain readable until this call returns. Creation fails when the count does not fit Vulkan's uint32_t field or the loader does not offer a name.
lostStateLoss condition of the root the device opens over, as for Create.

◆ CreateWithTimelineSemaphoreForTest()

std::unique_ptr< VulkanDevice > donner::gpu::vulkan::VulkanDevice::CreateWithTimelineSemaphoreForTest ( std::shared_ptr< DeviceLostState > lostState = nullptr)
static

Creates a device with VK_KHR_timeline_semaphore enabled solely for test-owned host gates. Returns nullptr if the test extension/feature is unavailable; ordinary Create needs neither.

Parameters
lostStateLoss condition of the root the device opens over, as for Create.

◆ deferTextureUploadPollingForTest()

void donner::gpu::vulkan::VulkanDevice::deferTextureUploadPollingForTest ( bool defer)

Defers upload fence polling to exercise ownership before device teardown.

Parameters
deferWhether to postpone upload completion observations.

◆ failNextSubmissionForTest()

void donner::gpu::vulkan::VulkanDevice::failNextSubmissionForTest ( bool deviceLost = false)

Makes the next native submission fail before it reaches the queue, after encoding finishes.

Parameters
deviceLostWhether to inject terminal device loss instead of recoverable host OOM.

◆ failNextTextureUploadForTest()

void donner::gpu::vulkan::VulkanDevice::failNextTextureUploadForTest ( UploadFailureModeForTest mode)

Makes the next internal texture upload report failure at mode, so a test can prove what the tracker is left holding in each case. Test seam; the upload's Vulkan work is recorded either way, only its reported result is replaced.

Parameters
modeWhere the injected failure happens.

◆ forceMinimumImageCountOnceForTest()

void donner::gpu::vulkan::VulkanDevice::forceMinimumImageCountOnceForTest ( uint32_t surfaceSlotIndex)

Makes the next swapchain creation for the surface at surfaceSlotIndex ask for the fewest images allowed, so a rebuild shrinks its acquisition ring. Test seam.

Parameters
surfaceSlotIndexSlot of a live surface of this device.

◆ forceNextAcquireOutOfDateForTest()

void donner::gpu::vulkan::VulkanDevice::forceNextAcquireOutOfDateForTest ( uint32_t surfaceSlotIndex)

Makes the next acquisition on the surface at surfaceSlotIndex report the swapchain as out of date, so its rebuild-and-retry path runs. Test seam; see the swapchain's own note for why a headless surface needs one.

Parameters
surfaceSlotIndexSlot of a live surface of this device.

◆ hasNativeViewForTest()

Result< bool > donner::gpu::vulkan::VulkanDevice::hasNativeViewForTest ( const TextureView & view) const

Whether view has a native image view.

Test accessor: a view of a texture that can be neither sampled, stored to nor rendered to has none, and nothing a test reads back shows whether one was made. Fails closed on a handle that does not name a live view of this device.

Parameters
viewView to query.

◆ nativeInstance()

void * donner::gpu::vulkan::VulkanDevice::nativeInstance ( ) const
nodiscard

The Vulkan instance this device was created on, for an embedder that creates its own surface.

A window-system surface is scoped to the instance it was created against, so an embedder whose windowing library already knows how to make one (GLFW and SDL both do) needs this instance to make it against; that is what keeps this build free of Xlib and Wayland headers. Pass the resulting handle back as donner::gpu::NativeSurfaceKind::EmbedderSurface.

Returned as an opaque pointer so this header stays free of Vulkan types; it is a VkInstance. The shared root this device retains owns it, so it stays valid for the device's lifetime. Ownership of a surface made against it stays with the embedder: destroy the runtime's surface first, then the embedder's, then this device. Null when the device was created without presentation support, since without the surface extensions there is nothing an embedder could create against it.

◆ onAbandonCurrentTexture()

void donner::gpu::vulkan::VulkanDevice::onAbandonCurrentTexture ( uint32_t slotIndex)
overrideprotectedvirtual

Backend hook: drop the acquired texture without presenting.

Parameters
slotIndexSlot of the surface.

Reimplemented from donner::gpu::Device.

◆ onAcquireCurrentTexture()

Result< SurfaceStatus > donner::gpu::vulkan::VulkanDevice::onAcquireCurrentTexture ( uint32_t slotIndex,
uint32_t textureSlotIndex )
overrideprotectedvirtual

Backend hook: acquire the next frame's texture and report the surface's state.

Parameters
slotIndexSlot of the surface.
textureSlotIndexSlot the runtime allocated for the acquired texture.

Reimplemented from donner::gpu::Device.

◆ onConfigureSurface()

Status donner::gpu::vulkan::VulkanDevice::onConfigureSurface ( uint32_t slotIndex,
const SurfaceConfiguration & configuration )
overrideprotectedvirtual

Backend hook: apply a configuration.

Parameters
slotIndexSlot of the surface.
configurationConfiguration to apply.

Reimplemented from donner::gpu::Device.

◆ onCreateBindGroup()

Status donner::gpu::vulkan::VulkanDevice::onCreateBindGroup ( uint32_t slotIndex,
const BindGroupDescriptor & descriptor )
overrideprotectedvirtual

Backend hook: a bind group passed validation and occupies slotIndex.

Parameters
slotIndexSlot index of the new resource.
descriptorValidated descriptor.

Implements donner::gpu::Device.

◆ onCreateBindGroupLayout()

Status donner::gpu::vulkan::VulkanDevice::onCreateBindGroupLayout ( uint32_t slotIndex,
const BindGroupLayoutDescriptor & descriptor )
overrideprotectedvirtual

Backend hook: a bind group layout passed validation and occupies slotIndex.

Parameters
slotIndexSlot index of the new resource.
descriptorValidated descriptor.

Implements donner::gpu::Device.

◆ onCreateBuffer()

Status donner::gpu::vulkan::VulkanDevice::onCreateBuffer ( uint32_t slotIndex,
const BufferDescriptor & descriptor )
overrideprotectedvirtual

Backend hook: a buffer passed validation and occupies slotIndex.

Parameters
slotIndexSlot index of the new resource.
descriptorValidated descriptor.

Implements donner::gpu::Device.

◆ onCreateComputePipeline()

Status donner::gpu::vulkan::VulkanDevice::onCreateComputePipeline ( uint32_t slotIndex,
const ComputePipelineDescriptor & descriptor )
overrideprotectedvirtual

Backend hook: a compute pipeline passed validation and occupies slotIndex.

Parameters
slotIndexSlot index of the new resource.
descriptorValidated descriptor.

Implements donner::gpu::Device.

◆ onCreatePipelineLayout()

Status donner::gpu::vulkan::VulkanDevice::onCreatePipelineLayout ( uint32_t slotIndex,
const PipelineLayoutDescriptor & descriptor )
overrideprotectedvirtual

Backend hook: a pipeline layout passed validation and occupies slotIndex.

Parameters
slotIndexSlot index of the new resource.
descriptorValidated descriptor.

Implements donner::gpu::Device.

◆ onCreateRenderPipeline()

Status donner::gpu::vulkan::VulkanDevice::onCreateRenderPipeline ( uint32_t slotIndex,
const RenderPipelineDescriptor & descriptor )
overrideprotectedvirtual

Backend hook: a render pipeline passed validation and occupies slotIndex.

Parameters
slotIndexSlot index of the new resource.
descriptorValidated descriptor.

Implements donner::gpu::Device.

◆ onCreateSampler()

Status donner::gpu::vulkan::VulkanDevice::onCreateSampler ( uint32_t slotIndex,
const SamplerDescriptor & descriptor )
overrideprotectedvirtual

Backend hook: a sampler passed validation and occupies slotIndex.

Parameters
slotIndexSlot index of the new resource.
descriptorValidated descriptor.

Implements donner::gpu::Device.

◆ onCreateShaderModule()

Status donner::gpu::vulkan::VulkanDevice::onCreateShaderModule ( uint32_t slotIndex,
const ShaderModuleDescriptor & descriptor )
overrideprotectedvirtual

Backend hook: a shader module passed validation and occupies slotIndex.

Parameters
slotIndexSlot index of the new resource.
descriptorValidated descriptor.

Implements donner::gpu::Device.

◆ onCreateSurface()

Status donner::gpu::vulkan::VulkanDevice::onCreateSurface ( uint32_t slotIndex,
const SurfaceDescriptor & descriptor )
overrideprotectedvirtual

Backend hook: create a surface for a platform object.

Defaults to reporting presentation as unsupported, so a backend that cannot present needs no implementation.

Parameters
slotIndexSlot the surface occupies.
descriptorLabel and platform object.

Reimplemented from donner::gpu::Device.

◆ onCreateTexture()

Status donner::gpu::vulkan::VulkanDevice::onCreateTexture ( uint32_t slotIndex,
const TextureDescriptor & descriptor )
overrideprotectedvirtual

Backend hook: a texture passed validation and occupies slotIndex.

Parameters
slotIndexSlot index of the new resource.
descriptorValidated descriptor.

Implements donner::gpu::Device.

◆ onCreateTextureView()

Status donner::gpu::vulkan::VulkanDevice::onCreateTextureView ( uint32_t slotIndex,
uint32_t textureSlotIndex,
const TextureViewDescriptor & descriptor )
overrideprotectedvirtual

Backend hook: a texture view passed validation and occupies slotIndex.

Parameters
slotIndexSlot index of the new resource.
textureSlotIndexSlot index of the viewed texture.
descriptorValidated descriptor.

Implements donner::gpu::Device.

◆ onDestroyResource()

void donner::gpu::vulkan::VulkanDevice::onDestroyResource ( std::string_view resourceName,
uint32_t slotIndex )
overrideprotectedvirtual

Backend hook: a retired resource is no longer used by submitted work and can be released.

Parameters
resourceNameResource type name, e.g. "buffer".
slotIndexSlot index of the destroyed resource.

Implements donner::gpu::Device.

◆ onDestroySurface()

void donner::gpu::vulkan::VulkanDevice::onDestroySurface ( uint32_t slotIndex)
overrideprotectedvirtual

Backend hook: release the platform state of a surface that is going away.

Runs once per surface, when it is destroyed or when its last handle is dropped, after any frame it still held has been handed back through onAbandonCurrentTexture. The slot is reused by the next surface, so a backend that keeps per-surface state clears it here rather than leaving the next surface to find its predecessor's.

Parameters
slotIndexSlot of the surface.

Reimplemented from donner::gpu::Device.

◆ onExportTexture()

Result< BackendTextureExport > donner::gpu::vulkan::VulkanDevice::onExportTexture ( uint32_t slotIndex)
overrideprotectedvirtual

Backend hook: export the texture in slotIndex, which the runtime has already validated as a live texture this device allocated and no surface has out.

The default refuses with GpuErrorType::Unsupported: a backend that reaches each native device through exactly one runtime device has no other device that could name the texture.

Parameters
slotIndexValidated live texture slot.

Reimplemented from donner::gpu::Device.

◆ onLastProgress()

std::optional< std::chrono::steady_clock::time_point > donner::gpu::vulkan::VulkanDevice::onLastProgress ( )
overrideprotectedvirtual

When the queue shared by every device over this root was last seen to make progress: a command buffer finishing, or work submitted while no tracked work was outstanding. Progress is timed when it is first seen, which this call also looks for; see VulkanQueueProgress.

Reimplemented from donner::gpu::Device.

◆ onMapBufferAsync()

Status donner::gpu::vulkan::VulkanDevice::onMapBufferAsync ( uint32_t mappingSlotIndex,
uint32_t bufferSlotIndex,
MapMode mode,
uint64_t offsetBytes,
uint64_t byteCount )
overrideprotectedvirtual

Backend hook: begin mapping a buffer range.

Defaults to reporting the capability as unsupported, so a backend without host mapping needs no implementation and callers get a clean unsupported result rather than a missing symbol.

Parameters
mappingSlotIndexSlot the mapping occupies.
bufferSlotIndexSlot of the buffer being mapped.
modeHow the host will access the range.
offsetBytesByte offset of the mapped range.
byteCountLength of the mapped range.

Reimplemented from donner::gpu::Device.

◆ onMappedBytes()

Result< std::span< const uint8_t > > donner::gpu::vulkan::VulkanDevice::onMappedBytes ( uint32_t mappingSlotIndex) const
overrideprotectedvirtual

Backend hook: bytes of a completed mapping.

Parameters
mappingSlotIndexSlot of the mapping.

Reimplemented from donner::gpu::Device.

◆ onOwnsTextureBacking()

bool donner::gpu::vulkan::VulkanDevice::onOwnsTextureBacking ( uint32_t slotIndex) const
nodiscardoverrideprotectedvirtual

Backend hook: whether slotIndex holds backing this device allocated.

Asked for a validated slot that is not a surface's acquired frame, from two places: the public ownsTextureBacking, and createTexture immediately after onCreateTexture accepted the slot, to decide whether the creation is an allocation an observer counts, both when it is created and when it is released. The answer must therefore already hold when onCreateTexture returns. The default is true: every texture a backend holds is one it created. A backend that can also name memory belonging to someone else - a registration of a host-owned object, say - overrides this and says which is which.

Parameters
slotIndexValidated live texture slot.

Reimplemented from donner::gpu::Device.

◆ onPresentSurface()

Result< SurfaceStatus > donner::gpu::vulkan::VulkanDevice::onPresentSurface ( uint32_t slotIndex)
overrideprotectedvirtual

Backend hook: present the acquired texture.

Parameters
slotIndexSlot of the surface.

Reimplemented from donner::gpu::Device.

◆ onRegisterTexture()

Status donner::gpu::vulkan::VulkanDevice::onRegisterTexture ( uint32_t slotIndex,
const ExportedTextureBacking & backing )
overrideprotectedvirtual

Backend hook: name another device's exported texture in slotIndex.

Called only after the runtime has matched backing's device identity against backendDeviceIdentity, so a backend may treat backing as its own export type. The backend must hold the native object until onDestroyResource for the slot, and must not report it as an allocation of this device.

Parameters
slotIndexSlot the registration occupies.
backingThe producer backend's export.

Reimplemented from donner::gpu::Device.

◆ onRetireBuffer()

void donner::gpu::vulkan::VulkanDevice::onRetireBuffer ( uint32_t slotIndex)
overrideprotectedvirtual

Backend hook: a buffer handle was retired. Discard unsubmitted work, but keep native resources alive until onDestroyResource.

Parameters
slotIndexRetired buffer slot.

Reimplemented from donner::gpu::Device.

◆ onSubmit()

Status donner::gpu::vulkan::VulkanDevice::onSubmit ( uint64_t submissionSerial,
std::span< const SubmittedCommandBuffer > commandBuffers )
overrideprotectedvirtual

Backend hook: validated command buffers were submitted as one submission.

The span holds at least one buffer and they execute in the order given. The backend owes the caller one completion for the whole span: whatever native objects it splits the work across, completedSerial reaches submissionSerial only once all of them have finished, and a backend that reports the submission accepted has accepted all of it.

Parameters
submissionSerialSerial assigned to this submission.
commandBuffersCommand buffers of this submission, in execution order.

Implements donner::gpu::Device.

◆ onSurfaceCapabilities()

Result< SurfaceCapabilities > donner::gpu::vulkan::VulkanDevice::onSurfaceCapabilities ( uint32_t slotIndex) const
overrideprotectedvirtual

Backend hook: what a surface supports.

Parameters
slotIndexSlot of the surface.

Reimplemented from donner::gpu::Device.

◆ onUnmapBuffer()

void donner::gpu::vulkan::VulkanDevice::onUnmapBuffer ( uint32_t mappingSlotIndex)
overrideprotectedvirtual

Backend hook: release a mapping.

Parameters
mappingSlotIndexSlot of the mapping.

Reimplemented from donner::gpu::Device.

◆ onWaitForSerial()

bool donner::gpu::vulkan::VulkanDevice::onWaitForSerial ( uint64_t serial,
double timeoutSeconds )
overrideprotectedvirtual

Blocks on the pending submission's fence with vkWaitForFences, so the wait is woken by the submission completing rather than by rechecking.

Returns false on timeout, if the serial was never submitted, or if a Vulkan call fails (see lastErrorForTest).

Parameters
serialSubmission serial to wait for.
timeoutSecondsLongest to wait, in seconds.

Reimplemented from donner::gpu::Device.

◆ onWaitForSerialUnlessStalled()

SerialWaitResult donner::gpu::vulkan::VulkanDevice::onWaitForSerialUnlessStalled ( uint64_t serial,
std::chrono::milliseconds stallBound )
overrideprotectedvirtual

Waits for the fence of the submission covering serial while the queue shared by every device over this root keeps making progress (see VulkanQueueProgress): the work ahead of the serial includes other devices' work, so their command buffers finishing counts too.

Parameters
serialSubmission serial to wait for.
stallBoundLongest the queue may go without progress.

Reimplemented from donner::gpu::Device.

◆ onWaitMappingSlice()

MapSliceReport donner::gpu::vulkan::VulkanDevice::onWaitMappingSlice ( uint32_t mappingSlotIndex,
double sliceSeconds )
overrideprotectedvirtual

Backend hook: wait up to sliceSeconds for a pending mapping, and report what it found and how it spent the slice.

The runtime owns the deadline and the caller's cancellation; this reports only the mapping.

Parameters
mappingSlotIndexSlot of the pending mapping.
sliceSecondsLongest this call may block.

Reimplemented from donner::gpu::Device.

◆ onWriteBuffer()

Status donner::gpu::vulkan::VulkanDevice::onWriteBuffer ( uint32_t slotIndex,
uint64_t offsetBytes,
std::span< const uint8_t > data )
overrideprotectedvirtual

Backend hook: a validated buffer write.

Parameters
slotIndexDestination buffer slot.
offsetBytesDestination byte offset.
dataPayload bytes.

Implements donner::gpu::Device.

◆ onWriteTexture()

Status donner::gpu::vulkan::VulkanDevice::onWriteTexture ( uint32_t slotIndex,
std::span< const uint8_t > data,
const TexelCopyBufferLayout & dataLayout,
const Extent2d & writeSize,
const Origin2d & destinationOrigin )
overrideprotectedvirtual

Backend hook: a validated texture write. The written rectangle is writeSize texels wide and tall with its top-left texel at destinationOrigin; texels outside it keep their contents.

Parameters
slotIndexDestination texture slot.
dataPayload bytes.
dataLayoutRow layout of data.
writeSizeExtent written in texels.
destinationOriginTop-left texel of the written rectangle.

Implements donner::gpu::Device.

◆ QuerySystemCapabilities()

std::optional< SystemCapabilities > donner::gpu::vulkan::VulkanDevice::QuerySystemCapabilities ( )
static

Asks the physical device Create selects what it supports, without creating a logical device on it: a transient instance is created, the same physical device is chosen, and its limits are read before the instance is destroyed.

A backend root is selected before any device over it exists, and its limits have to be the device's own rather than a portable fallback.

Returns
The capabilities, or empty when no Vulkan device is available or device creation is closed after a failed shutdown.

◆ readBackBuffer()

Result< std::vector< uint8_t > > donner::gpu::vulkan::VulkanDevice::readBackBuffer ( const Buffer & buffer)

Copies the full contents of buffer back to the host and returns the bytes.

Synchronous test and diagnostic readback, outside the asynchronous mapping API (donner::gpu::Device::mapBufferAsync): validates the handle (null, device identity, and generation) through the base class, then reads the persistently mapped host-visible allocation once this buffer's last submission completes. That wait lasts as long as the queue keeps completing work, and gives up once it has made no progress for five seconds. Unrelated work does not delay an idle buffer. A stalled queue, a device failure or a loss declared over the root returns an error without reading memory; fence completion makes device writes visible to the host for HOST_COHERENT memory.

Parameters
bufferBuffer to read back; must be a live buffer of this device.

◆ releasePausedCommandBuffersForTest()

void donner::gpu::vulkan::VulkanDevice::releasePausedCommandBuffersForTest ( uint64_t count)

Lets the first count command buffers submitted since pauseSubmissionsForTest run and keeps the rest held. Callable from any thread while the device's own thread waits.

Parameters
countCommand buffers to let run, counted from the first one submitted while paused.

◆ setBeforeExternalSurfaceQueryHookForTest()

void donner::gpu::vulkan::VulkanDevice::setBeforeExternalSurfaceQueryHookForTest ( std::function< void()> hook)

Test seam run after accepting an external surface but before its first Vulkan query.

Parameters
hookOne-shot callback that may synchronize a concurrent platform close.

◆ setBufferWriteByteBudgetForTest()

void donner::gpu::vulkan::VulkanDevice::setBufferWriteByteBudgetForTest ( uint64_t byteBudget)

Lowers the combined pending/in-flight payload limit for deterministic budget tests.

Parameters
byteBudgetMaximum payload bytes, clamped to the production limit.

◆ setFenceWaitStepHookForTest()

void donner::gpu::vulkan::VulkanDevice::setFenceWaitStepHookForTest ( std::function< void()> hook)

Calls hook each time a step of a fence wait times out, in a serial wait or a texture upload, before the wait checks the root's loss condition, so a test can declare a loss while a wait is known to be blocked. Test accessor; an empty function removes the hook.

Parameters
hookCalled on the waiting thread.

◆ setImageBarrierRecordingForTest()

void donner::gpu::vulkan::VulkanDevice::setImageBarrierRecordingForTest ( bool enabled)

Enables an empty barrier history or disables recording and releases the history. Recording is disabled by default.

Parameters
enabledWhether subsequent image barriers should be retained for inspection.

◆ shaderSourceKind()

ShaderSourceKind donner::gpu::vulkan::VulkanDevice::shaderSourceKind ( ) const
inlineoverridevirtual

Native shader representation accepted by this device.

Reimplemented from donner::gpu::Device.

◆ supportsFullIndexRange()

bool donner::gpu::vulkan::VulkanDevice::supportsFullIndexRange ( IndexFormat format) const
overridevirtual

True for Uint16 always; for Uint32 only when the physical device offered fullDrawIndexUint32 and Create enabled it, since without that feature index values above maxDrawIndexedIndexValue are undefined.

Reimplemented from donner::gpu::Device.

◆ surfaceAcquisitionForTest()

SurfaceAcquisitionForTest donner::gpu::vulkan::VulkanDevice::surfaceAcquisitionForTest ( uint32_t surfaceSlotIndex) const
nodiscard

Reads the acquisition bookkeeping of the surface at surfaceSlotIndex. Test accessor.

Parameters
surfaceSlotIndexSlot of a surface of this device.

◆ trackedTextureLayoutForTest()

Result< TrackedTextureLayout > donner::gpu::vulkan::VulkanDevice::trackedTextureLayoutForTest ( const Texture & texture) const

Returns the layout texture is tracked in.

Test accessor; fails closed on a handle that does not name a live texture of this device.

Parameters
textureTexture to query.

The documentation for this class was generated from the following file: