Skip to content

OpDecorate with Block/BufferBlock isn't working properly #261

Open

Description

@ccleavinger

Context

I'm working on a basic compiler for converting Rust functions to SPIR-V using proc macros and rspirv (to achieve similar functionality as CUDA)

Error

When compiling buffers to parameters I'm having an issue where the correlating OpTypeStruct (this: %_struct_5 = OpTypeStruct %_runtimearr_float) doesn't actually get decorated with Block despite marking aforementioned type with Block using rspirv.

Code Snippet

This is from withing a struct that uses a handful of hashmaps to store and access variable ids and type ids:

                    // get word of the type of the elements in the runtime arr
                    let base_word = self.types.get(arr_ty).ok_or(anyhow!(
                        "failed to retrieve base type of runtime arr: {:?}",
                        arr_ty
                    ))?;

                    // create runtime arr type (pretty simple)
                    let runtime_ty = self.spirv_builder.type_runtime_array(*base_word);

                    // create a struct type
                    let struct_ty = self.spirv_builder.type_struct(vec![runtime_ty]);

                    self.spirv_builder.decorate(
                        struct_ty,
                        rspirv::spirv::Decoration::Block,
                        vec![], 
                    );

                    let lit_0 = self.literals
                        .get(&MimirLit::Int32(0))
                        .ok_or(anyhow!("Failed to find literal 0 for struct decoration"))?;
                    self.spirv_builder.member_decorate(
                        struct_ty, 
                        *lit_0,
                        rspirv::spirv::Decoration::Offset,
                        vec![rspirv::dr::Operand::LiteralBit32(0)]
                    );

SPIR-V

Outputted SPIR-V for my compiler:
saxpy.spirv.txt
Because the SPIR-V contains %_runtimearr_float = OpTypeRuntimeArray %float and
%_struct_5 = OpTypeStruct %_runtimearr_float the code for generating buffers is being called but the types are not being decorated properly.

Thank you in advance for any help, thank you!

Activity

  1. msiglreith commented on Apr 25, 2025

    @msiglreith
    Contributor

    Hi,

    which version you are using? Unfortunately I'm unable to open the file, reports an error when trying to download. I put together a small program with rspirv:0.12.0 which outputs the decoration just fine:

    use rspirv::binary::{Assemble, Disassemble};
    use rspirv::spirv;
    
    fn main() {
        let mut b = rspirv::dr::Builder::new();
        b.set_version(1, 0);
        b.capability(spirv::Capability::Shader);
        b.memory_model(spirv::AddressingModel::Logical, spirv::MemoryModel::GLSL450);
    
        let ty_f32 = b.type_float(32);
        let runtime_ty = b.type_runtime_array(ty_f32);
        let struct_ty = b.type_struct(vec![runtime_ty]);
    
        b.decorate(struct_ty, rspirv::spirv::Decoration::Block, vec![]);
    
        b.member_decorate(
            struct_ty,
            0, // note: this should be an immediate value not an id
            rspirv::spirv::Decoration::Offset,
            vec![rspirv::dr::Operand::LiteralBit32(0)],
        );
    
        let module = b.module();
        let code = module.assemble();
    
        let mut loader = rspirv::dr::Loader::new();
        rspirv::binary::parse_words(&code, &mut loader).unwrap();
        let module = loader.module();
    
        println!("{}", module.disassemble());
    }
    ; SPIR-V
    ; Version: 1.0
    ; Generator: rspirv
    ; Bound: 4
    OpCapability Shader
    OpMemoryModel Logical GLSL450
    OpDecorate %3 Block
    OpMemberDecorate %3 0 Offset 0
    %1 = OpTypeFloat 32
    %2 = OpTypeRuntimeArray %1
    %3 = OpTypeStruct %2
    
  2. ccleavinger commented on Apr 28, 2025

    @ccleavinger
    Author

    I'm using rspirv: 0.12.0 as well, the outputted SPIR-V is as below, I'm unsure what could be causing this. I might have to line by line debug my compiler once I'm out of school.

    Outputted SPIR_V:

    ; SPIR-V
    ; Version: 1.2
    ; Generator: Google rspirv; 0
    ; Bound: 64
    ; Schema: 0
                   OpCapability Shader
              %1 = OpExtInstImport "GLSL.std.450"
                   OpMemoryModel Logical GLSL450
                   OpEntryPoint GLCompute %35 "main" %gl_WorkGroupID %gl_LocalInvocationID
                   OpSource Unknown 1
                   OpName %x "x"
                   OpName %y "y"
                   OpName %idx "idx"
                   OpName %idx "idx"
                   OpDecorate %20 SpecId 0
                   OpDecorate %21 SpecId 1
                   OpDecorate %22 SpecId 2
                   OpDecorate %gl_WorkGroupID BuiltIn WorkgroupId
                   OpDecorate %gl_WorkGroupSize BuiltIn WorkgroupSize
                   OpDecorate %gl_LocalInvocationID BuiltIn LocalInvocationId
                   OpDecorate %x Binding 0
                   OpDecorate %x DescriptorSet 0
                   OpDecorate %y Binding 1
                   OpDecorate %y DescriptorSet 0
           %void = OpTypeVoid
           %uint = OpTypeInt 32 0
         %v3uint = OpTypeVector %uint 3
          %float = OpTypeFloat 32
            %int = OpTypeInt 32 1
    %_runtimearr_float = OpTypeRuntimeArray %float
      %_struct_8 = OpTypeStruct %_runtimearr_float
    %_ptr_Function_float = OpTypePointer Function %float
    %_ptr_Function_int = OpTypePointer Function %int
    %_ptr_PushConstant_int = OpTypePointer PushConstant %int
    %_ptr_PushConstant_float = OpTypePointer PushConstant %float
    %_ptr_Input_v3uint = OpTypePointer Input %v3uint
    %_ptr_Function_uint = OpTypePointer Function %uint
    %_ptr_Uniform_float = OpTypePointer Uniform %float
    %_ptr_Uniform__struct_8 = OpTypePointer Uniform %_struct_8
           %bool = OpTypeBool
    %_ptr_Function_bool = OpTypePointer Function %bool
             %19 = OpTypeFunction %void
             %20 = OpSpecConstant %uint 1
             %21 = OpSpecConstant %uint 1
             %22 = OpSpecConstant %uint 1
    %_ptr_Input_uint = OpTypePointer Input %uint
    %gl_WorkGroupID = OpVariable %_ptr_Input_v3uint Input
    %gl_WorkGroupSize = OpSpecConstantComposite %v3uint %20 %21 %22
    %gl_LocalInvocationID = OpVariable %_ptr_Input_v3uint Input
          %int_2 = OpConstant %int 2
          %int_1 = OpConstant %int 1
          %int_0 = OpConstant %int 0
              %x = OpVariable %_ptr_Uniform__struct_8 Uniform
              %y = OpVariable %_ptr_Uniform__struct_8 Uniform
     %_struct_32 = OpTypeStruct %int %float
    %_ptr_PushConstant__struct_32 = OpTypePointer PushConstant %_struct_32
             %34 = OpVariable %_ptr_PushConstant__struct_32 PushConstant
        %int_1_0 = OpConstant %int 1
             %35 = OpFunction %void None %19
             %36 = OpLabel
            %idx = OpVariable %_ptr_Function_uint Function
             %39 = OpAccessChain %_ptr_Input_uint %gl_WorkGroupID %int_0
             %40 = OpLoad %uint %39
             %41 = OpCompositeExtract %uint %gl_WorkGroupSize 0
             %42 = OpIMul %uint %40 %41
             %43 = OpAccessChain %_ptr_Input_uint %gl_LocalInvocationID %int_0
             %44 = OpLoad %uint %43
             %45 = OpIAdd %uint %42 %44
                   OpStore %idx %45
             %46 = OpLoad %uint %idx
             %47 = OpAccessChain %_ptr_PushConstant_int %34 %int_0
             %48 = OpLoad %int %47
             %49 = OpULessThan %bool %46 %48
                   OpSelectionMerge %50 None
                   OpBranchConditional %49 %51 %50
             %51 = OpLabel
             %52 = OpLoad %uint %idx
             %53 = OpAccessChain %_ptr_Uniform_float %y %int_0 %52
             %54 = OpAccessChain %_ptr_PushConstant_float %34 %int_1_0
             %55 = OpLoad %float %54
             %56 = OpLoad %uint %idx
             %57 = OpAccessChain %_ptr_Uniform_float %x %int_0 %56
             %58 = OpLoad %float %57
             %59 = OpFMul %float %55 %58
             %60 = OpLoad %uint %idx
             %61 = OpAccessChain %_ptr_Uniform_float %y %int_0 %60
             %62 = OpLoad %float %61
             %63 = OpFAdd %float %59 %62
                   OpStore %53 %63
                   OpBranch %50
             %50 = OpLabel
                   OpReturn
                   OpFunctionEnd
    
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions