MaikKlein / rlsl

Rust to SPIR-V compiler
Apache License 2.0
557 stars 14 forks source link

Optimize references away and allow mutable references inside functions #35

Closed MaikKlein closed 6 years ago

MaikKlein commented 6 years ago
layout(location = 0) in vec2 a_Pos;

void test(inout vec2 v) {
    v = vec2(1,1);
}

void main() {
    vec2 v = a_Pos;
    test(v);
    gl_Position = vec4(v, 0.0, 1.0);
}

glslang always creates a new variable for a param, and then directly passes that variable.

        %v_0 = OpVariable %_ptr_Function_v2float Function
      %param = OpVariable %_ptr_Function_v2float Function
         %29 = OpLoad %v2float %a_Pos
               OpStore %v_0 %29
         %30 = OpLoad %v2float %v_0
               OpStore %param %30
         %31 = OpFunctionCall %void %test_vf2_ %param
         %32 = OpLoad %v2float %param
               OpStore %v_0 %32

This is because variables are always mutable, and changes inside a function would affect the value of the params.

I assume if one param was marked as inout glslang just stores the value of the param in the variable that was marked inout

         %32 = OpLoad %v2float %param
               OpStore %v_0 %32

In rlsl I don't pass variables directly, I only pass the load.

         %23 = OpVariable %_ptr_Function__ptr_Function_float Function
      %coord = OpVariable %_ptr_Function_v3float Function
         %26 = OpVariable %_ptr_Function_float Function
         %27 = OpVariable %_ptr_Function_v3float Function
         %30 = OpVariable %_ptr_Function__ZN4core6marker11PhantomData Function
               OpBranch %16
         %16 = OpLabel
               OpStore %f %float_1
               OpStore %23 %f
         %32 = OpLoad %_ptr_Function_float %23
         %33 = OpFunctionCall %void %_ZN6shader8test_mut %32

If something is marked &mut, I'll just pass the variable directly instead of passing the loaded value.

MaikKlein commented 6 years ago

OpFunctionParameter has to be a pointer type, otherwise it can't be used with OpAccessChain which essentially makes it quite useless. :(

The workaround is to store all function parameters that are not of type pointer inside function local variables.