Skip to content

Allow deriving VectorOrScalar #410

Description

@nazar-pc

The trait is unsafe and currently says:

Implementing this trait on non-scalar or non-vector types may break assumptions about other unsafe code, and should not be done.

Fair enough, but not particularly useful for someone who would like to implement it.

It'd be great if there was a way to derive its implementation with a derive macro. Very helpful for new types, structs with two numeric fields, etc. Without this capability things like subgroup_shuffle() currently require substantial boilerplate.

Activity

  1. self-assigned this
    on Sep 24, 2025
  2. Firestar99 commented on Sep 24, 2025

    @Firestar99
    Member

    Luckily, #380 get us 90% there already. Just need to wrap that in a derive attribute macro that also implements spirv_std::vector::Vector and spirv_std::vector::VectorOrScalar.

    See #411

  3. nazar-pc commented on Oct 10, 2025

    @nazar-pc
    ContributorAuthor

    BTW, would it be difficult to implement this trait on things like [u32; 2] or more generally <const N: usize> [T; N] where T: Scalar?
    It'd simplify some of the code I'm writing a lot.

  4. Firestar99 commented on Oct 13, 2025

    @Firestar99
    Member

    [u32; 2] is an OpTypeArray %u32 2, not an OpTypeVector %u32 2, so it wouldn't work unless we change arrays to vectors for small array sizes.

    I've been thinking about maybe a trait + derive macro specifically for subgroup intrinsics that would allow decomposing arbitrary types into the plain primitives and then apply the operation for each of those. That should be relatively easy to implement, next to what #411 offers. That would also solve the array case, since it's just a bunch of primitives.

  5. Firestar99 commented on Oct 14, 2025

    @Firestar99
    Member

    @nazar-pc Made you #441 with a new trait ScalarOrVectorComposite:

    #[derive(Copy, Clone, ScalarOrVectorComposite)]
    pub struct MyStruct {
    a: f32,
    b: UVec3,
    c: Nested,
    d: Zst,
    }
    #[derive(Copy, Clone, ScalarOrVectorComposite)]
    pub struct Nested(i32);
    #[derive(Copy, Clone, ScalarOrVectorComposite)]
    pub struct Zst;
    #[spirv(compute(threads(32)))]
    pub fn main(
    #[spirv(local_invocation_index)] inv_id: UVec3,
    #[spirv(descriptor_set = 0, binding = 0, storage_buffer)] output: &mut UVec3,
    ) {
    unsafe {
    let my_struct = MyStruct {
    a: 1.,
    b: inv_id,
    c: Nested(-42),
    d: Zst,
    };
    let mut out = UVec3::ZERO;
    out += subgroup_broadcast(my_struct, 19).b;
    out += subgroup_broadcast_first(my_struct).b;
    out += subgroup_shuffle(my_struct, 2).b;
    out += subgroup_shuffle_xor(my_struct, 4).b;
    out += subgroup_shuffle_up(my_struct, 5).b;
    out += subgroup_shuffle_down(my_struct, 7).b;
    *output = out;
    }
    }

    Just be careful of the breaking changes in #380 and #440

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions