rspirv icon indicating copy to clipboard operation
rspirv copied to clipboard

OpDecorate with Block/BufferBlock isn't working properly

Open ccleavinger opened this issue 8 months ago • 2 comments

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!

ccleavinger avatar Apr 25 '25 04:04 ccleavinger

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

msiglreith avatar Apr 25 '25 17:04 msiglreith

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

ccleavinger avatar Apr 28 '25 18:04 ccleavinger