pub struct VulkanContext { /* private fields */ }Expand description
A Vulkan device, its queue, and what it can do.
Implementations§
Source§impl VulkanContext
impl VulkanContext
Sourcepub fn new(preference: DevicePreference) -> Result<Self>
pub fn new(preference: DevicePreference) -> Result<Self>
Create a context, selecting a physical device by preference.
Sourcepub fn with_config(config: ContextConfig) -> Result<Self>
pub fn with_config(config: ContextConfig) -> Result<Self>
Create a context with explicit configuration.
pub fn capabilities(&self) -> &Capabilities
Sourcepub fn register_program(&mut self, program: &RuntimeProgram) -> Result<u32>
pub fn register_program(&mut self, program: &RuntimeProgram) -> Result<u32>
The descriptor set layout every pipeline is built against. The layout for the set carrying a draw’s paint.
Lazy like the sampling layout beside it, and for the same reason: a context that never records a batch should build nothing. Register a caller’s fragment program and return the name for it.
Nothing is built here. A pipeline needs a render pass, a blend mode and a sample count that only a draw knows, so the payload is kept and the pipelines appear as the combinations actually used do.
Sourcepub fn sync_validation_active(&self) -> bool
pub fn sync_validation_active(&self) -> bool
Whether the validation layer is actually installed and reporting.
Requesting validation on a machine without the layer yields false here rather than an error, so tests can skip instead of failing on a machine that simply lacks the SDK. Whether the layer was asked to check synchronization as well as calls.
Core validation checks that each call is well formed. Synchronization validation checks that one access is ordered against the next, which is a separate feature the layer does not enable by default – and it is the one that matters most to a renderer that synchronizes explicitly, since a missing barrier renders correctly on the device it was written on.
A caller asserting a clean log wants to know this: without it the log being empty says only that every call was well formed.
pub fn validation_active(&self) -> bool
Sourcepub fn validation_messages(&self) -> Vec<ValidationMessage>
pub fn validation_messages(&self) -> Vec<ValidationMessage>
Everything the layer has reported for this context so far.
Sourcepub fn validation_clean(&self) -> bool
pub fn validation_clean(&self) -> bool
Whether the layer has reported no errors.
Sourcepub fn validation_log(&self) -> Arc<ValidationLog> ⓘ
pub fn validation_log(&self) -> Arc<ValidationLog> ⓘ
A handle on the log that outlives this context.
Every other accessor here reads the log through the context, which
cannot see the last thing the layer has to say. A child object that
outlives its device is reported at vkDestroyDevice, which happens
inside this context’s own drop, and by then there is nothing left to
ask – so a whole class of fault was structurally invisible to every
test rather than merely untested. Holding this across the drop is what
makes teardown assertable.
The messenger is destroyed after the device, deliberately, so the callback is still installed while those reports are made.
pub fn queue_family_index(&self) -> u32
Sourcepub fn has_extension(&self, name: &str) -> bool
pub fn has_extension(&self, name: &str) -> bool
Whether a device extension was enabled at device creation.
pub fn raw_device(&self) -> &Device
Sourcepub fn raw_entry(&self) -> &Entry
pub fn raw_entry(&self) -> &Entry
The loader, for a presentation target that needs an instance extension this crate does not itself use.
pub fn raw_instance(&self) -> &Instance
pub fn raw_physical_device(&self) -> PhysicalDevice
pub fn raw_queue(&self) -> Queue
Source§impl VulkanContext
impl VulkanContext
Sourcepub fn create_exportable_texture(
&mut self,
extent: Extent2D,
format: PixelFormat,
modifiers: &[Modifier],
) -> Result<VulkanTexture>
pub fn create_exportable_texture( &mut self, extent: Extent2D, format: PixelFormat, modifiers: &[Modifier], ) -> Result<VulkanTexture>
Allocate an image that can be exported as a dma-buf.
modifiers are the layouts the other side will accept, in preference
order; the driver picks one it can also use. Passing the negotiated set
rather than a single modifier is what lets the driver choose the best
layout both sides share.
Sourcepub fn texture_modifier(&self, texture: &VulkanTexture) -> Result<Modifier>
pub fn texture_modifier(&self, texture: &VulkanTexture) -> Result<Modifier>
The layout the driver actually chose for an exportable image.
Sourcepub fn export_texture(
&self,
texture: &VulkanTexture,
) -> Result<ExternalImageDesc>
pub fn export_texture( &self, texture: &VulkanTexture, ) -> Result<ExternalImageDesc>
Export an image’s memory as a dma-buf.
The returned descriptor carries everything the display side needs to build a framebuffer: the file descriptor, the format, the layout the driver chose, and the plane’s offset and stride.
Source§impl VulkanContext
impl VulkanContext
Sourcepub fn draw_indexed(
&mut self,
target: &mut VulkanTexture,
vertices: &[[f32; 2]],
indices: &[u32],
material: Material,
blend: BlendMode,
clear: Option<[f32; 4]>,
) -> Result<()>
pub fn draw_indexed( &mut self, target: &mut VulkanTexture, vertices: &[[f32; 2]], indices: &[u32], material: Material, blend: BlendMode, clear: Option<[f32; 4]>, ) -> Result<()>
Draw a single set of triangles. A convenience over Batch.
The material is in linear space with straight alpha; it is premultiplied on the way to the target, which holds premultiplied color.
Sourcepub fn submit_batch(
&mut self,
target: &mut VulkanTexture,
batch: &Batch,
pass: PassDescriptor,
) -> Result<()>
pub fn submit_batch( &mut self, target: &mut VulkanTexture, batch: &Batch, pass: PassDescriptor, ) -> Result<()>
Record and submit a whole batch as one render pass.
Sourcepub fn submit_batch_textured(
&mut self,
target: &mut VulkanTexture,
batch: &Batch,
pass: PassDescriptor,
textures: &[&VulkanTexture],
) -> Result<()>
pub fn submit_batch_textured( &mut self, target: &mut VulkanTexture, batch: &Batch, pass: PassDescriptor, textures: &[&VulkanTexture], ) -> Result<()>
Record and submit a whole batch as one render pass, with a texture table its image paints index.
Sourcepub fn submit_batch_deferred(
&mut self,
target: &mut VulkanTexture,
batch: &Batch,
pass: PassDescriptor,
) -> Result<VulkanFence>
pub fn submit_batch_deferred( &mut self, target: &mut VulkanTexture, batch: &Batch, pass: PassDescriptor, ) -> Result<VulkanFence>
Submit a batch without waiting, returning a fence that signals when the GPU is finished.
The waiting form is right for tests and setup. A frame loop needs this one: it hands the caller something to attach to a page flip, or to wait on while the next frame is already being recorded. Everything the submission still needs — the command buffer and the pass’s transient framebuffer objects — travels with the fence, because none of it can be released until the work completes.
The returned fence must be handed back to Self::retire_fence.
Sourcepub fn submit_batch_deferred_synchronized(
&mut self,
target: &mut VulkanTexture,
batch: &Batch,
pass: PassDescriptor,
textures: &[&VulkanTexture],
sync: FrameSync<'_>,
) -> Result<VulkanFence>
pub fn submit_batch_deferred_synchronized( &mut self, target: &mut VulkanTexture, batch: &Batch, pass: PassDescriptor, textures: &[&VulkanTexture], sync: FrameSync<'_>, ) -> Result<VulkanFence>
Submit without waiting, gating the work on semaphores the caller owns.
What a swapchain needs: the render must not touch the image before
acquisition has signalled, and presentation must not read it before the
render has. Neither is expressible with a fence, because both are
device-side orderings that no one should be blocking a thread to
enforce.
textures is the table a impeller_hal::Material::Image slot indexes, exactly as
the waiting form takes it. A frame that composites a layer needs it:
the pass that lands in a presentable image is the one that samples the
layer, so a deferred submission that could not sample anything meant a
frame with layers could be rendered offscreen and never presented.
Sourcepub fn retire_fence(&mut self, fence: VulkanFence)
pub fn retire_fence(&mut self, fence: VulkanFence)
Release a deferred submission once its work has completed.
Source§impl VulkanContext
impl VulkanContext
Sourcepub fn create_texture(
&mut self,
desc: &TextureDescriptor,
) -> Result<VulkanTexture>
pub fn create_texture( &mut self, desc: &TextureDescriptor, ) -> Result<VulkanTexture>
Allocate a texture.
External images are not handled yet: importing a dma-buf needs the external-memory plumbing, and accepting the descriptor while ignoring its external half would hand back a blank image that silently is not the caller’s buffer.
Sourcepub fn destroy_texture(&mut self, texture: VulkanTexture)
pub fn destroy_texture(&mut self, texture: VulkanTexture)
Release a texture and its memory.
Sourcepub fn transition_for_present(&mut self, texture: &VulkanTexture) -> Result<()>
pub fn transition_for_present(&mut self, texture: &VulkanTexture) -> Result<()>
Put a texture into the layout the presentation engine reads from.
A presented image is read by something outside this device’s command stream, so it has to be transitioned rather than left in whatever the last pass wanted. Doing it here keeps the layout bookkeeping with everything else that knows about layouts, instead of in a presentation target that would have to reach into a texture’s internals.
Sourcepub fn clear_texture(
&mut self,
texture: &mut VulkanTexture,
color: [f32; 4],
) -> Result<()>
pub fn clear_texture( &mut self, texture: &mut VulkanTexture, color: [f32; 4], ) -> Result<()>
Clear a texture to a solid color.
Records, submits, and waits. Batching belongs to the renderer, which does not exist yet; doing it here would be an abstraction guessing at its caller.
Sourcepub fn write_texture(
&mut self,
texture: &mut VulkanTexture,
pixels: &[u8],
) -> Result<()>
pub fn write_texture( &mut self, texture: &mut VulkanTexture, pixels: &[u8], ) -> Result<()>
Copy a texture back to host memory, tightly packed. Fill a texture from host memory, tightly packed and top row first.
The mirror of Self::read_texture, and stated in the same layout, so
a round trip through the pair is the identity. That is what makes it
testable without a decoder: write known bytes, read them back, compare.
Image decoding is out of scope for this project, but getting decoded pixels onto the device is not — without this an image shader would have nothing to sample but what the renderer itself drew.