Skip to main content

Validated

Struct Validated 

Source
pub struct Validated(/* private fields */);
Expand description

A context that asserts the layer reported nothing when it goes out of scope.

The other half of what this module is for. Capturing the messenger makes validation assertable; this makes it asserted, which is not the same thing: a test that turns the layer on and never reads what it said is indistinguishable from one that left it off, and a check written out in every test is one some test will be missing. That is not hypothetical – the layer was on for this crate’s own tests and off for the whole shared harness, which is the largest body of rendering in the suite.

Dropping is the one moment that happens exactly once per context however the test around it is written, so that is where the check goes.

Derefs to the context, so code that takes a crate::VulkanContext is unchanged.

Implementations§

Source§

impl Validated

Source

pub fn new(device: DevicePreference) -> Result<Self>

A context with the layer requested, or whatever went wrong instead.

Methods from Deref<Target = VulkanContext>§

Source

pub fn capabilities(&self) -> &Capabilities

Source

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.

Source

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.

Source

pub fn validation_active(&self) -> bool

Source

pub fn validation_messages(&self) -> Vec<ValidationMessage>

Everything the layer has reported for this context so far.

Source

pub fn validation_clean(&self) -> bool

Whether the layer has reported no errors.

Source

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.

Source

pub fn queue_family_index(&self) -> u32

Source

pub fn has_extension(&self, name: &str) -> bool

Whether a device extension was enabled at device creation.

Source

pub fn raw_device(&self) -> &Device

Source

pub fn raw_entry(&self) -> &Entry

The loader, for a presentation target that needs an instance extension this crate does not itself use.

Source

pub fn raw_instance(&self) -> &Instance

Source

pub fn raw_physical_device(&self) -> PhysicalDevice

Source

pub fn raw_queue(&self) -> Queue

Source

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.

Source

pub fn texture_modifier(&self, texture: &VulkanTexture) -> Result<Modifier>

The layout the driver actually chose for an exportable image.

Source

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

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.

Source

pub fn submit_batch( &mut self, target: &mut VulkanTexture, batch: &Batch, pass: PassDescriptor, ) -> Result<()>

Record and submit a whole batch as one render pass.

Source

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.

Source

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.

Source

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.

Source

pub fn retire_fence(&mut self, fence: VulkanFence)

Release a deferred submission once its work has completed.

Source

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.

Source

pub fn destroy_texture(&mut self, texture: VulkanTexture)

Release a texture and its memory.

Source

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.

Source

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.

Source

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.

Source

pub fn read_texture(&mut self, texture: &mut VulkanTexture) -> Result<Vec<u8>>

Trait Implementations§

Source§

impl Deref for Validated

Source§

type Target = VulkanContext

The resulting type after dereferencing.
Source§

fn deref(&self) -> &VulkanContext

Dereferences the value.
Source§

impl DerefMut for Validated

Source§

fn deref_mut(&mut self) -> &mut VulkanContext

Mutably dereferences the value.
Source§

impl Drop for Validated

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

fn pin_drop(self: Pin<&mut Self>)

🔬This is a nightly-only experimental API. (pin_ergonomics)
Execute the destructor for this type, but different to Drop::drop, it requires self to be pinned. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<P, T> Receiver for P
where P: Deref<Target = T> + ?Sized, T: ?Sized,

Source§

type Target = T

🔬This is a nightly-only experimental API. (arbitrary_self_types)
The target type on which the method may be called.
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.