Skip to main content

GraphicsCommandRef

Struct GraphicsCommandRef 

Source
pub struct GraphicsCommandRef<'a> { /* private fields */ }
Expand description

Recording interface for drawing commands.

This structure provides a strongly-typed set of methods which allow raster graphics shader code to be executed. An instance is provided to the closure argument of PipelineCommand::record_cmd which may be accessed by binding a GraphicsPipeline to a command.

§Examples

Basic usage:

my_graph
    .begin_cmd()
    .debug_name("my draw command")
    .bind_pipeline(&my_graphic_pipeline)
    .color_attachment_image(0, swapchain_image, LoadOp::DontCare, StoreOp::Store)
    .record_cmd(move |cmd| {
        // During this closure we have access to the drawing functions!
        cmd.draw(3, 1, 0, 0);
    });

Implementations§

Source§

impl GraphicsCommandRef<'_>

Source

pub fn bind_index_buffer( &self, buffer: impl Into<AnyBufferNode>, offset: DeviceSize, index_ty: IndexType, ) -> &Self

Bind an index buffer to the current command.

offset is the starting offset in bytes within buffer used in index buffer address calculations.

§Examples

Basic usage:

my_graph
    .begin_cmd()
    .debug_name("my indexed geometry draw command")
    .bind_pipeline(&my_graphic_pipeline)
    .color_attachment_image(0, swapchain_image, LoadOp::DontCare, StoreOp::Store)
    .resource_access(my_idx_buf, AccessType::IndexBuffer)
    .resource_access(my_vtx_buf, AccessType::VertexBuffer)
    .record_cmd(move |cmd| {
        cmd
            .bind_index_buffer(my_idx_buf, 0, vk::IndexType::UINT16)
            .bind_vertex_buffer(0, my_vtx_buf, 0)
            .draw_indexed(42, 1, 0, 0, 0);
    });
Source

pub fn bind_vertex_buffer( &self, binding: u32, buffer: impl Into<AnyBufferNode>, offset: DeviceSize, ) -> &Self

Binds a vertex buffer for the current graphics command.

The vertex input binding is updated to start at offset from the start of buffer.

§Examples

Basic usage:

my_graph
    .begin_cmd()
    .debug_name("my unindexed geometry draw command")
    .bind_pipeline(&my_graphic_pipeline)
    .color_attachment_image(0, swapchain_image, LoadOp::DontCare, StoreOp::Store)
    .resource_access(my_vtx_buf, AccessType::VertexBuffer)
    .record_cmd(move |cmd| {
        cmd
            .bind_vertex_buffer(0, my_vtx_buf, 0)
            .draw(42, 1, 0, 0);
    });
Source

pub fn bind_vertex_buffers<N>( &self, first_binding: u32, buffer_offsets: impl IntoIterator<Item = (N, DeviceSize)>, ) -> &Self
where N: Into<AnyBufferNode>,

Binds multiple vertex buffers for the current graphics command, starting at the given first_binding.

Each vertex input binding in buffers specifies an offset from the start of the corresponding buffer.

The vertex input attributes that use each of these bindings will use these updated addresses in their address calculations for subsequent drawing commands.

Source

pub fn draw( &self, vertex_count: u32, instance_count: u32, first_vertex: u32, first_instance: u32, ) -> &Self

Draw unindexed primitives.

When the command is executed, primitives are assembled using the current primitive topology and vertex_count consecutive vertex indices with the first vertex_index value equal to first_vertex. The primitives are drawn instance_count times with instance_index starting with first_instance and increasing sequentially for each instance.

Source

pub fn draw_indexed( &self, index_count: u32, instance_count: u32, first_index: u32, vertex_offset: i32, first_instance: u32, ) -> &Self

Draw indexed primitives.

When the command is executed, primitives are assembled using the current primitive topology and index_count vertices whose indices are retrieved from the index buffer. The index buffer is treated as an array of tightly packed unsigned integers of size defined by the index_ty parameter with which the buffer was bound.

Source

pub fn draw_indexed_indirect( &self, buffer: impl Into<AnyBufferNode>, offset: DeviceSize, draw_count: u32, stride: u32, ) -> &Self

Draw primitives with indirect parameters and indexed vertices.

draw_indexed_indirect behaves similarly to draw_indexed except that the parameters are read by the device from buffer during execution. draw_count draws are executed by the command, with parameters taken from buffer starting at offset and increasing by stride bytes for each successive draw. The parameters of each draw are encoded in an array of vk::DrawIndexedIndirectCommand structures.

If draw_count is less than or equal to one, stride is ignored.

§Examples

Basic usage:

const CMD_SIZE: usize = size_of::<vk::DrawIndexedIndirectCommand>();

let cmd = vk::DrawIndexedIndirectCommand {
    index_count: 3,
    instance_count: 1,
    first_index: 0,
    vertex_offset: 0,
    first_instance: 0,
};
let cmd_data = unsafe {
    std::slice::from_raw_parts(&cmd as *const _ as *const _, CMD_SIZE)
};

let buf_flags = vk::BufferUsageFlags::STORAGE_BUFFER;
let buf = Buffer::create_from_slice(&device, buf_flags, cmd_data)?;
let buf_node = my_graph.bind_resource(buf);

my_graph
    .begin_cmd()
    .debug_name("draw a single triangle")
    .bind_pipeline(&my_graphic_pipeline)
    .color_attachment_image(0, swapchain_image, LoadOp::DontCare, StoreOp::Store)
    .resource_access(my_idx_buf, AccessType::IndexBuffer)
    .resource_access(my_vtx_buf, AccessType::VertexBuffer)
    .resource_access(buf_node, AccessType::IndirectBuffer)
    .record_cmd(move |cmd| {
        cmd
            .bind_index_buffer(my_idx_buf, 0, vk::IndexType::UINT16)
            .bind_vertex_buffer(0, my_vtx_buf, 0)
            .draw_indexed_indirect(buf_node, 0, 1, 0);
    });
Source

pub fn draw_indexed_indirect_count( &self, buffer: impl Into<AnyBufferNode>, offset: DeviceSize, count_buf: impl Into<AnyBufferNode>, count_buf_offset: DeviceSize, max_draw_count: u32, stride: u32, ) -> &Self

Draw primitives with indirect parameters, indexed vertices, and draw count.

draw_indexed_indirect_count behaves similarly to draw_indexed_indirect except that the draw count is read by the device from buffer during execution. The command will read an unsigned 32-bit integer from count_buf located at count_buf_offset and use this as the draw count.

max_draw_count specifies the maximum number of draws that will be executed. The actual number of executed draw calls is the minimum of the count specified in count_buf and max_draw_count.

stride is the byte stride between successive sets of draw parameters.

Source

pub fn draw_indirect( &self, buffer: impl Into<AnyBufferNode>, offset: DeviceSize, draw_count: u32, stride: u32, ) -> &Self

Draw primitives with indirect parameters and unindexed vertices.

Behaves otherwise similar to Self::draw_indexed_indirect.

Source

pub fn draw_indirect_count( &self, buffer: impl Into<AnyBufferNode>, offset: DeviceSize, count_buf: impl Into<AnyBufferNode>, count_buf_offset: DeviceSize, max_draw_count: u32, stride: u32, ) -> &Self

Draw primitives with indirect parameters, unindexed vertices, and draw count.

Behaves otherwise similar to Self::draw_indexed_indirect_count.

Source

pub fn push_constants(&self, offset: u32, data: &[u8]) -> &Self

Updates push constants.

Push constants represent a high-speed path to modify constant data in pipelines that is expected to outperform memory-backed resource updates.

Push constant values can be updated incrementally, causing shader stages to read the new data for push constants modified by this command, while still reading the previous data for push constants not modified by this command.

§Device limitations

See VkPhysicalDeviceLimits::maxPushConstantsSize for the limit of the current device. You may also check [gpuinfo.org] for a listing of reported limits on other devices.

§Examples

Basic usage:

#version 450
#pragma shader_stage(fragment)

layout(push_constant) uniform PushConstants {
    layout(offset = 0) uint the_answer;
} push_constants;

void main() {
    uint value = push_constants.the_answer;
}
my_graph
    .begin_cmd()
    .debug_name("draw a quad")
    .bind_pipeline(&my_graphic_pipeline)
    .color_attachment_image(0, swapchain_image, LoadOp::DontCare, StoreOp::Store)
    .record_cmd(move |cmd| {
        cmd
            .push_constants(0, &[42])
            .draw(6, 1, 0, 0);
    });

See vkCmdPushConstants.

Source

pub fn set_scissor(&self, first_scissor: u32, scissors: &[Rect2D]) -> &Self

Sets scissor rectangles dynamically for the current command.

The default scissor state is no-clip.

See vkCmdSetScissor.

Source

pub fn set_viewport(&self, first_viewport: u32, viewports: &[Viewport]) -> &Self

Sets viewports dynamically for the current command.

The default viewport state is the entire render target as defined by all combined image attachments.

See vkCmdSetViewport.

Methods from Deref<Target = CommandRef<'a>>§

Source

pub fn build_accel_struct( &self, infos: &[BuildAccelerationStructureInfo], ) -> &Self

Build acceleration structures.

There is no ordering or synchronization implied between any of the individual acceleration structure builds.

Requires a scratch buffer which was created with the following requirements:

  • Flags must include vk::BufferUsageFlags::SHADER_DEVICE_ADDRESS
  • Size must be equal to or greater than the build_size value returned by AccelerationStructure::size_of, aligned to min_accel_struct_scratch_offset_alignment of PhysicalDevice::vk_khr_acceleration_structure.
§Examples

Basic usage:

my_graph.begin_cmd()
        .resource_access(index_buf, AccessType::IndexBuffer)
        .resource_access(vertex_buf, AccessType::VertexBuffer)
        .resource_access(scratch_buf, AccessType::AccelerationStructureBufferWrite)
        .resource_access(blas_node, AccessType::AccelerationStructureBuildWrite)
        .record_cmd(move |cmd| {
            let scratch_addr = cmd.resource(scratch_buf).device_address();
            let geom = AccelerationStructureGeometry {
                max_primitive_count: 64,
                flags: vk::GeometryFlagsKHR::OPAQUE,
                geometry: AccelerationStructureGeometryData::Triangles {
                    index_addr: DeviceOrHostAddress::DeviceAddress(
                        cmd.resource(index_buf).device_address()
                    ),
                    index_type: vk::IndexType::UINT32,
                    max_vertex: 42,
                    transform_addr: None,
                    vertex_addr: DeviceOrHostAddress::DeviceAddress(
                        cmd.resource(vertex_buf).device_address(),
                    ),
                    vertex_format: vk::Format::R32G32B32_SFLOAT,
                    vertex_stride: 12,
                },
            };
            let build_range = vk::AccelerationStructureBuildRangeInfoKHR {
                first_vertex: 0,
                primitive_count: 1,
                primitive_offset: 0,
                transform_offset: 0,
            };
            let info = AccelerationStructureGeometryInfo::blas([(geom, build_range)]);

            cmd.build_accel_struct(&[
                BuildAccelerationStructureInfo::new(blas_node, scratch_addr, info)
            ]);
        });

See also:

Source

pub fn build_accel_struct_indirect( &self, infos: &[BuildAccelerationStructureIndirectInfo], ) -> &Self

Builds acceleration structures with some parameters provided on the device.

There is no ordering or synchronization implied between any of the individual acceleration structure builds.

Each BuildAccelerationStructureIndirectInfo::range_base is a buffer device address which points to an array of vk::AccelerationStructureBuildRangeInfoKHR structures defining dynamic offsets to the addresses where geometry data is stored.

Source

pub fn update_accel_struct( &self, infos: &[UpdateAccelerationStructureInfo], ) -> &Self

Update acceleration structures.

There is no ordering or synchronization implied between any of the individual acceleration structure updates.

Requires a scratch buffer which was created with the following requirements:

  • Flags must include vk::BufferUsageFlags::SHADER_DEVICE_ADDRESS
  • Size must be equal to or greater than the update_size value returned by AccelerationStructure::size_of, aligned to min_accel_struct_scratch_offset_alignment of PhysicalDevice::vk_khr_acceleration_structure.
Source

pub fn update_accel_struct_indirect( &self, infos: &[UpdateAccelerationStructureIndirectInfo], ) -> &Self

Updates acceleration structures with some parameters provided on the device.

There is no ordering or synchronization implied between any of the individual acceleration structure updates.

Each UpdateAccelerationStructureIndirectInfo::range_base is a buffer device address which points to an array of vk::AccelerationStructureBuildRangeInfoKHR structures defining dynamic offsets to the addresses where geometry data is stored.

Source

pub fn resource<N>(&self, resource_node: N) -> &N::Resource
where N: Node,

Returns a borrow of the original Vulkan resource (buffer, image or acceleration structure) which the given bound resource node represents.

Methods from Deref<Target = CommandBuffer>§

Source

pub fn begin( &self, info: &CommandBufferBeginInfo<'_>, ) -> Result<(), DriverError>

Begins recording this command buffer.

This is a thin wrapper around ash::Device::begin_command_buffer that maps Vulkan errors to DriverError variants.

See vkBeginCommandBuffer.

Source

pub fn end(&self) -> Result<(), DriverError>

Ends recording this command buffer.

This is a thin wrapper around ash::Device::end_command_buffer that maps Vulkan errors to DriverError variants.

See vkEndCommandBuffer.

Source

pub fn end_render_pass(&self)

Ends recording a render pass.

Source

pub fn queue_submit( &self, queue: Queue, fence: &mut Fence, submits: &[SubmitInfo<'_>], ) -> Result<(), DriverError>

Submits command buffers to a queue using fence.

This method does not begin, end, or reset self or fence. Callers are expected to submit only executable command buffers and to manage fence waits and resets as needed.

Typical handling is:

  1. Begin recording with Self::begin.
  2. Record commands.
  3. End recording with Self::end.
  4. Submit this command buffer with queue_submit.
  5. Later, wait for completion with Fence::is_signaled or Fence::wait_signaled.
  6. Before re-submitting this same command buffer, reset the fence with Fence::reset, then begin recording again.

See vkQueueSubmit.

Source

pub fn queue_submit2( &self, queue: Queue, fence: &mut Fence, submits: &[SubmitInfo2<'_>], ) -> Result<(), DriverError>

Submits command buffers to a queue using vkQueueSubmit2 (Vulkan 1.3 core or VK_KHR_synchronization2).

See vkQueueSubmit2 and VK_KHR_synchronization2.

Source

pub fn set_debug_name(&self, name: impl AsRef<str>)

Sets the debugging name assigned to this command buffer.

Trait Implementations§

Source§

impl<'a> Deref for GraphicsCommandRef<'a>

Source§

type Target = CommandRef<'a>

The resulting type after dereferencing.
Source§

fn deref(&self) -> &Self::Target

Dereferences the value.

Auto Trait Implementations§

§

impl<'a> !RefUnwindSafe for GraphicsCommandRef<'a>

§

impl<'a> !Send for GraphicsCommandRef<'a>

§

impl<'a> !Sync for GraphicsCommandRef<'a>

§

impl<'a> !UnwindSafe for GraphicsCommandRef<'a>

§

impl<'a> Freeze for GraphicsCommandRef<'a>

§

impl<'a> Unpin for GraphicsCommandRef<'a>

§

impl<'a> UnsafeUnpin for GraphicsCommandRef<'a>

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<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

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<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

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 = Infallible

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

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

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.