Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add vulkan indirect command structs #34

Merged
merged 4 commits into from
Oct 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions crates/spirv-std/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ unexpected_cfgs = { level = "allow", check-cfg = ['cfg(target_arch, values("spir
spirv-std-types.workspace = true
spirv-std-macros.workspace = true
bitflags = "1.2.1"
bytemuck = { version = "1.18.0", features = ["derive"], optional = true }

[target.'cfg(target_arch = "spirv")'.dependencies]
num-traits = { workspace = true, features = ["libm"] }
Expand All @@ -25,3 +26,4 @@ glam = { workspace = true, default-features = true }

[features]
default = []
bytemuck = ["dep:bytemuck", "glam/bytemuck"]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added bytemuck as an optional dependency to mark all the *IndirectCommand structs as Pod, as most graphics APIs will require this. Should we make the bytemuck dependency required, eg. not hidden behind a feature?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think keeping bytemuck optional is good. It's true that most graphics projects will have it somewhere in the tree, but I don't think we should be deciding how folks marshal data to the GPU.

2 changes: 2 additions & 0 deletions crates/spirv-std/src/arch/subgroup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ const SUBGROUP: u32 = Scope::Subgroup as u32;

/// `SubgroupMask` is a [`glam::UVec4`] representing a bitmask of all invocations within a subgroup.
/// Mostly used in group ballot operations.
#[repr(transparent)]
#[derive(Copy, Clone, Default, Eq, PartialEq)]
#[cfg_attr(feature = "bytemuck", derive(bytemuck::Zeroable, bytemuck::Pod))]
pub struct SubgroupMask(pub glam::UVec4);

/// Defines the class of group operation.
Expand Down
187 changes: 187 additions & 0 deletions crates/spirv-std/src/indirect_command.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
//! Indirect command structs from vulkan

use glam::UVec3;

/// <https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkDeviceSize.html>
pub type DeviceSize = u64;

/// <https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkDeviceAddress.html>
pub type DeviceAddress = u64;

/// Structure specifying an indirect drawing command
///
/// <https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkDrawIndirectCommand.html>
#[repr(C)]
#[derive(Copy, Clone, Debug, Default)]
#[cfg_attr(feature = "bytemuck", derive(bytemuck::Zeroable, bytemuck::Pod))]
pub struct DrawIndirectCommand {
/// vertexCount is the number of vertices to draw.
pub vertex_count: u32,
/// instanceCount is the number of instances to draw.
pub instance_count: u32,
/// firstVertex is the index of the first vertex to draw.
pub first_vertex: u32,
/// firstInstance is the instance ID of the first instance to draw.
pub first_instance: u32,
}

/// Structure specifying an indexed indirect drawing command
///
/// <https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkDrawIndexedIndirectCommand.html>
#[repr(C)]
#[derive(Copy, Clone, Debug, Default)]
#[cfg_attr(feature = "bytemuck", derive(bytemuck::Zeroable, bytemuck::Pod))]
pub struct DrawIndexedIndirectCommand {
/// indexCount is the number of vertices to draw.
pub index_count: u32,
/// instanceCount is the number of instances to draw.
pub instance_count: u32,
/// firstIndex is the base index within the index buffer.
pub first_index: u32,
/// vertexOffset is the value added to the vertex index before indexing into the vertex buffer.
pub vertex_offset: i32,
/// firstInstance is the instance ID of the first instance to draw.
pub first_instance: u32,
}

/// Structure specifying an indirect dispatching command
///
/// <https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkDispatchIndirectCommand.html>
#[repr(C)]
#[derive(Copy, Clone, Debug, Default)]
#[cfg_attr(feature = "bytemuck", derive(bytemuck::Zeroable, bytemuck::Pod))]
pub struct DispatchIndirectCommand {
/// x is the number of local workgroups to dispatch in the X dimension.
pub x: u32,
/// y is the number of local workgroups to dispatch in the Y dimension.
pub y: u32,
/// z is the number of local workgroups to dispatch in the Z dimension.
pub z: u32,
}

impl From<UVec3> for DispatchIndirectCommand {
fn from(v: UVec3) -> Self {
Self {
x: v.x,
y: v.y,
z: v.z,
}
}
}

impl From<DispatchIndirectCommand> for UVec3 {
fn from(v: DispatchIndirectCommand) -> Self {
Self {
x: v.x,
y: v.y,
z: v.z,
}
}
}

/// Structure specifying a mesh tasks draw indirect command
///
/// <https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkDrawMeshTasksIndirectCommandEXT.html>
#[repr(C)]
#[derive(Copy, Clone, Debug, Default)]
#[cfg_attr(feature = "bytemuck", derive(bytemuck::Zeroable, bytemuck::Pod))]
pub struct DrawMeshTasksIndirectCommandEXT {
/// groupCountX is the number of local workgroups to dispatch in the X dimension.
pub group_count_x: u32,
/// groupCountY is the number of local workgroups to dispatch in the Y dimension.
pub group_count_y: u32,
/// groupCountZ is the number of local workgroups to dispatch in the Z dimension.
pub group_count_z: u32,
}

impl From<UVec3> for DrawMeshTasksIndirectCommandEXT {
fn from(v: UVec3) -> Self {
Self {
group_count_x: v.x,
group_count_y: v.y,
group_count_z: v.z,
}
}
}

impl From<DrawMeshTasksIndirectCommandEXT> for UVec3 {
fn from(v: DrawMeshTasksIndirectCommandEXT) -> Self {
Self {
x: v.group_count_x,
y: v.group_count_y,
z: v.group_count_z,
}
}
}

/// Structure specifying the parameters of an indirect ray tracing command
///
/// <https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkTraceRaysIndirectCommandKHR.html>
#[repr(C)]
#[derive(Copy, Clone, Debug, Default)]
#[cfg_attr(feature = "bytemuck", derive(bytemuck::Zeroable, bytemuck::Pod))]
pub struct TraceRaysIndirectCommandKHR {
/// width is the width of the ray trace query dimensions.
pub width: u32,
/// height is height of the ray trace query dimensions.
pub height: u32,
/// depth is depth of the ray trace query dimensions.
pub depth: u32,
}

impl From<UVec3> for TraceRaysIndirectCommandKHR {
fn from(v: UVec3) -> Self {
Self {
width: v.x,
height: v.y,
depth: v.z,
}
}
}

impl From<TraceRaysIndirectCommandKHR> for UVec3 {
fn from(v: TraceRaysIndirectCommandKHR) -> Self {
Self {
x: v.width,
y: v.height,
z: v.depth,
}
}
}

/// Structure specifying the parameters of an indirect trace ray command with indirect shader binding tables
///
/// <https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkTraceRaysIndirectCommand2KHR.html>
#[repr(C)]
#[derive(Copy, Clone, Debug, Default)]
#[cfg_attr(feature = "bytemuck", derive(bytemuck::AnyBitPattern))]
pub struct TraceRaysIndirectCommand2KHR {
/// raygenShaderRecordAddress is a `VkDeviceAddress` of the ray generation shader binding table record used by this command.
pub raygen_shader_record_address: DeviceAddress,
/// raygenShaderRecordSize is a `VkDeviceSize` number of bytes corresponding to the ray generation shader binding table record at base address raygenShaderRecordAddress.
pub raygen_shader_record_size: DeviceSize,
/// missShaderBindingTableAddress is a `VkDeviceAddress` of the first record in the miss shader binding table used by this command.
pub miss_shader_binding_table_address: DeviceAddress,
/// missShaderBindingTableSize is a `VkDeviceSize` number of bytes corresponding to the total size of the miss shader binding table at missShaderBindingTableAddress that may be accessed by this command.
pub miss_shader_binding_table_size: DeviceSize,
/// missShaderBindingTableStride is a `VkDeviceSize` number of bytes between records of the miss shader binding table.
pub miss_shader_binding_table_stride: DeviceSize,
/// hitShaderBindingTableAddress is a `VkDeviceAddress` of the first record in the hit shader binding table used by this command.
pub hit_shader_binding_table_address: DeviceAddress,
/// hitShaderBindingTableSize is a `VkDeviceSize` number of bytes corresponding to the total size of the hit shader binding table at hitShaderBindingTableAddress that may be accessed by this command.
pub hit_shader_binding_table_size: DeviceSize,
/// hitShaderBindingTableStride is a `VkDeviceSize` number of bytes between records of the hit shader binding table.
pub hit_shader_binding_table_stride: DeviceSize,
/// callableShaderBindingTableAddress is a `VkDeviceAddress` of the first record in the callable shader binding table used by this command.
pub callable_shader_binding_table_address: DeviceAddress,
/// callableShaderBindingTableSize is a `VkDeviceSize` number of bytes corresponding to the total size of the callable shader binding table at callableShaderBindingTableAddress that may be accessed by this command.
pub callable_shader_binding_table_size: DeviceSize,
/// callableShaderBindingTableStride is a `VkDeviceSize` number of bytes between records of the callable shader binding table.
pub callable_shader_binding_table_stride: DeviceSize,
/// width is the width of the ray trace query dimensions.
pub width: u32,
/// height is height of the ray trace query dimensions.
pub height: u32,
/// depth is depth of the ray trace query dimensions.
pub depth: u32,
}
1 change: 1 addition & 0 deletions crates/spirv-std/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ pub mod arch;
pub mod byte_addressable_buffer;
pub mod float;
pub mod image;
pub mod indirect_command;
pub mod integer;
pub mod memory;
pub mod number;
Expand Down
2 changes: 2 additions & 0 deletions crates/spirv-std/src/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ pub enum Scope {
bitflags::bitflags! {
/// Memory semantics to determine how some operations should function - used when calling such
/// configurable operations.
#[repr(transparent)]
#[cfg_attr(feature = "bytemuck", derive(bytemuck::Zeroable, bytemuck::Pod))]
pub struct Semantics: u32 {
/// No memory semantics.
const NONE = 0;
Expand Down
2 changes: 2 additions & 0 deletions crates/spirv-std/src/ray_tracing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,8 @@ bitflags::bitflags! {
/// `NO_OPAQUE`, `CULL_OPAQUE`, `CULL_NO_OPAQUE`, only one of
/// `CULL_BACK_FACING_TRIANGLES` and `CULL_FRONT_FACING_TRIANGLES` may
/// be set.
#[repr(transparent)]
#[cfg_attr(feature = "bytemuck", derive(bytemuck::Zeroable, bytemuck::Pod))]
pub struct RayFlags: u32 {
/// No flags specified.
const NONE = 0;
Expand Down
2 changes: 1 addition & 1 deletion examples/shaders/shared/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ repository.workspace = true

[dependencies]
spirv-std = { workspace = true }
bytemuck = { version = "1.6.3", features = ["derive"] }
bytemuck = { version = "1.18.0", features = ["derive"] }
20 changes: 10 additions & 10 deletions tests/ui/arch/debug_printf_type_checking.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,9 @@ help: the return type of this call is `u32` due to the type of the argument pass
| |
| this argument influences the return type of `spirv_std`
note: function defined here
--> $SPIRV_STD_SRC/lib.rs:138:8
--> $SPIRV_STD_SRC/lib.rs:139:8
|
138 | pub fn debug_printf_assert_is_type<T>(ty: T) -> T {
139 | pub fn debug_printf_assert_is_type<T>(ty: T) -> T {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: this error originates in the macro `debug_printf` (in Nightly builds, run with -Z macro-backtrace for more info)
help: change the type of the numeric literal from `u32` to `f32`
Expand All @@ -102,9 +102,9 @@ help: the return type of this call is `f32` due to the type of the argument pass
| |
| this argument influences the return type of `spirv_std`
note: function defined here
--> $SPIRV_STD_SRC/lib.rs:138:8
--> $SPIRV_STD_SRC/lib.rs:139:8
|
138 | pub fn debug_printf_assert_is_type<T>(ty: T) -> T {
139 | pub fn debug_printf_assert_is_type<T>(ty: T) -> T {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: this error originates in the macro `debug_printf` (in Nightly builds, run with -Z macro-backtrace for more info)
help: change the type of the numeric literal from `f32` to `u32`
Expand All @@ -129,12 +129,12 @@ error[E0277]: the trait bound `{float}: Vector<f32, 2>` is not satisfied
<UVec3 as Vector<u32, 3>>
and 5 others
note: required by a bound in `debug_printf_assert_is_vector`
--> $SPIRV_STD_SRC/lib.rs:145:8
--> $SPIRV_STD_SRC/lib.rs:146:8
|
143 | pub fn debug_printf_assert_is_vector<
144 | pub fn debug_printf_assert_is_vector<
| ----------------------------- required by a bound in this function
144 | TY: crate::scalar::Scalar,
145 | V: crate::vector::Vector<TY, SIZE>,
145 | TY: crate::scalar::Scalar,
146 | V: crate::vector::Vector<TY, SIZE>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `debug_printf_assert_is_vector`
= note: this error originates in the macro `debug_printf` (in Nightly builds, run with -Z macro-backtrace for more info)

Expand All @@ -155,9 +155,9 @@ help: the return type of this call is `Vec2` due to the type of the argument pas
| |
| this argument influences the return type of `spirv_std`
note: function defined here
--> $SPIRV_STD_SRC/lib.rs:138:8
--> $SPIRV_STD_SRC/lib.rs:139:8
|
138 | pub fn debug_printf_assert_is_type<T>(ty: T) -> T {
139 | pub fn debug_printf_assert_is_type<T>(ty: T) -> T {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: this error originates in the macro `debug_printf` (in Nightly builds, run with -Z macro-backtrace for more info)

Expand Down
4 changes: 2 additions & 2 deletions tests/ui/arch/subgroup/subgroup_ballot.stderr
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
%1 = OpFunction %2 None %3
%4 = OpFunctionParameter %2
%5 = OpLabel
OpLine %6 379 8
OpLine %6 381 8
%7 = OpGroupNonUniformBallot %8 %9 %4
OpLine %6 415 8
OpLine %6 417 8
%10 = OpGroupNonUniformInverseBallot %2 %9 %7
OpNoLine
OpReturnValue %10
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/arch/subgroup/subgroup_ballot_bit_count.stderr
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
%1 = OpFunction %2 None %3
%4 = OpFunctionParameter %5
%6 = OpLabel
OpLine %7 491 8
OpLine %7 493 8
%8 = OpGroupNonUniformBallotBitCount %2 %9 Reduce %4
OpNoLine
OpReturnValue %8
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/arch/subgroup/subgroup_broadcast_first.stderr
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
%1 = OpFunction %2 None %3
%4 = OpFunctionParameter %2
%5 = OpLabel
OpLine %6 346 8
OpLine %6 348 8
%7 = OpGroupNonUniformBroadcastFirst %2 %8 %4
OpNoLine
OpReturnValue %7
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/arch/subgroup/subgroup_elect.stderr
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
%1 = OpFunction %2 None %3
%4 = OpLabel
OpLine %5 181 8
OpLine %5 183 8
%6 = OpGroupNonUniformElect %2 %7
OpNoLine
OpReturnValue %6
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/arch/subgroup/subgroup_i_add_clustered.stderr
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
%1 = OpFunction %2 None %3
%4 = OpFunctionParameter %2
%5 = OpLabel
OpLine %6 782 8
OpLine %6 784 8
%7 = OpGroupNonUniformIAdd %2 %8 ClusteredReduce %4 %9
OpNoLine
OpReturnValue %7
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
%1 = OpFunction %2 None %3
%4 = OpFunctionParameter %2
%5 = OpLabel
OpLine %6 741 8
OpLine %6 743 8
%7 = OpGroupNonUniformIAdd %2 %8 ExclusiveScan %4
OpNoLine
OpReturnValue %7
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
%1 = OpFunction %2 None %3
%4 = OpFunctionParameter %2
%5 = OpLabel
OpLine %6 741 8
OpLine %6 743 8
%7 = OpGroupNonUniformIAdd %2 %8 InclusiveScan %4
OpNoLine
OpReturnValue %7
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/arch/subgroup/subgroup_i_add_reduce.stderr
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
%1 = OpFunction %2 None %3
%4 = OpFunctionParameter %2
%5 = OpLabel
OpLine %6 741 8
OpLine %6 743 8
%7 = OpGroupNonUniformIAdd %2 %8 Reduce %4
OpNoLine
OpReturnValue %7
Expand Down