Repository: gfx-rs/wgpu
Pull request #5587 (2024-04-23 04:13:47)

[hlsl-out] Fix accesses on zero value expressions
 So that subsequent member access is resolved correctly.

**Connections**
https://matrix.to/#/!fjjkgHFcwtkREywzfk:matrix.org/$gMvEqmPg59z_xMR6WkUzik82z-UnGezovoXQ4ImVKmM

**Description**

I was getting HLSL output like:

```hlsl
float4 _expr2703 = float4(_expr2697.x, (float4)0.y, (float4)0.z, (float4)0.w);
```
Which produced this error:
```
error X3000: syntax error: unexpected token 'y'
```
This PR adjusts the output to:
```hlsl
float4 _expr2703 = float4(_expr2697.x, ((float4)0).y, ((float4)0).z, ((float4)0).w);
```

This is derived from some SPIRV input that I haven't looked through, I tried to reproduce the issue with some simple wgsl like `vec2<f32>().x` but naga outputs `(float)0` for that.

**Testing**
I compiled my application with this change and stopped getting errors from the hlsl shader compiler.

<!-- 
Thanks for filing! The codeowners file will automatically request reviews from the appropriate teams.

After you get a review and have addressed any comments, please explicitly re-request a review from the
person(s) who reviewed your changes. This will make sure it gets re-added to their review queue - you're no bothering us!
-->

**Checklist**

- [x] Run `cargo fmt`.
- [x] Run `cargo clippy`. If applicable, add:
  - [ ] ~~`--target wasm32-unknown-unknown`~~
  - [ ] ~~`--target wasm32-unknown-emscripten`~~
- [x] Run `cargo xtask test` to run tests.
- [x] Add change to `CHANGELOG.md`. See simple instructions inside file.


Imberflur: :slightly_frowning_face: 

I'm getting this from the CI:
```
[ERROR xtask::validate] failed to validate entry point "foo_vert" with profile "vs_5_1": `dxc 'tests\out\hlsl\access.hlsl' -T vs_5_1 -E foo_vert -Wno-parentheses-equality -Zi -Qembed_debug -Od -HV 2018` failed to run; exit code: Some(-2147467259)
stdout:

stderr:
warning: Promoting older shader model profile to 6.0 version.
tests\out\hlsl\access.hlsl:183:41: error: cannot compile this l-value expression yet
    t_1.am = (__mat4x2[2])((float4x2[2])0);
                                        ^
```
teoxoy: That's unfortunate, we might need to generate helper functions for `Expression::ZeroValue`.

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7b9fdf778..11688c35a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -164,6 +164,8 @@ Bottom level categories:
 - GLSL 410 does not support layout(binding = ...), enable only for GLSL 420. By @bes in [#5357](https://github.com/gfx-rs/wgpu/pull/5357)
 - In spv-out, check for acceleration and ray-query types when enabling ray-query extension to prevent validation error. By @Vecvec in [#5463](https://github.com/gfx-rs/wgpu/pull/5463)
 - Add a limit for curly brace nesting in WGSL parsing, plus a note about stack size requirements. By @ErichDonGubler in [#5447](https://github.com/gfx-rs/wgpu/pull/5447).
+- In hlsl-out, parenthesize output for `Expression::ZeroValue` (e.g. `(float4)0` -> `((float)0)`). This allows subsequent member access to parse correctly. By @Imberflur in [#5587](https://github.com/gfx-rs/wgpu/pull/5587).
+
 
 #### Tests
 
diff --git a/naga/src/back/hlsl/help.rs b/naga/src/back/hlsl/help.rs
index 4dd9ea598..d3bb1ce7f 100644
--- a/naga/src/back/hlsl/help.rs
+++ b/naga/src/back/hlsl/help.rs
@@ -70,6 +70,11 @@ pub(super) struct WrappedMath {
     pub(super) components: Option<u32>,
 }
 
+#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
+pub(super) struct WrappedZeroValue {
+    pub(super) ty: Handle<crate::Type>,
+}
+
 /// HLSL backend requires its own `ImageQuery` enum.
 ///
 /// It is used inside `WrappedImageQuery` and should be unique per ImageQuery function.
@@ -359,7 +364,7 @@ impl<'a, W: Write> super::Writer<'a, W> {
     }
 
     /// Helper function that write wrapped function for `Expression::Compose` for structures.
-    pub(super) fn write_wrapped_constructor_function(
+    fn write_wrapped_constructor_function(
         &mut self,
         module: &crate::Module,
         constructor: WrappedConstructor,
@@ -862,6 +867,25 @@ impl<'a, W: Write> super::Writer<'a, W> {
         Ok(())
     }
 
+    // TODO: we could merge this with iteration in write_wrapped_compose_functions...
+    //
+    /// Helper function that writes zero value wrapped functions
+    pub(super) fn write_wrapped_zero_value_functions(
+        &mut self,
+        module: &crate::Module,
+        expressions: &crate::Arena<crate::Expression>,
+    ) -> BackendResult {
+        for (handle, _) in expressions.iter() {
+            if let crate::Expression::ZeroValue(ty) = expressions[handle] {
+                let zero_value = WrappedZeroValue { ty };
+                if self.wrapped.zero_values.insert(zero_value) {
+                    self.write_wrapped_zero_value_function(module, zero_value)?;
+                }
+            }
+        }
+        Ok(())
+    }
+
     pub(super) fn write_wrapped_math_functions(
         &mut self,
         module: &crate::Module,
@@ -1006,6 +1030,7 @@ impl<'a, W: Write> super::Writer<'a, W> {
     ) -> BackendResult {
         self.write_wrapped_math_functions(module, func_ctx)?;
         self.write_wrapped_compose_functions(module, func_ctx.expressions)?;
+        self.write_wrapped_zero_value_functions(module, func_ctx.expressions)?;
 
         for (handle, _) in func_ctx.expressions.iter() {
             match func_ctx.expressions[handle] {
@@ -1283,4 +1308,71 @@ impl<'a, W: Write> super::Writer<'a, W> {
 
         Ok(())
     }
+
+    pub(super) fn write_wrapped_zero_value_function_name(
+        &mut self,
+        module: &crate::Module,
+        zero_value: WrappedZeroValue,
+    ) -> BackendResult {
+        let name = crate::TypeInner::hlsl_type_id(zero_value.ty, module.to_ctx(), &self.names)?;
+        write!(self.out, "ZeroValue{name}")?;
+        Ok(())
+    }
+
+    /// Helper function that write wrapped function for `Expression::ZeroValue`
+    ///
+    /// This is necessary since we might have a member access after the zero value expression, e.g.
+    /// `.y` (in practice this can come up when consuming SPIRV that's been produced by glslc).
+    ///
+    /// So we can't just write `(float4)0` since `(float4)0.y` won't parse correctly.
+    ///
+    /// Parenthesizing the expression like `((float4)0).y` would work... except DXC can't handle
+    /// cases like:
+    ///
+    /// ```ignore
+    /// tests\out\hlsl\access.hlsl:183:41: error: cannot compile this l-value expression yet
+    ///     t_1.am = (__mat4x2[2])((float4x2[2])0);
+    ///                                         ^
+    /// ```
+    fn write_wrapped_zero_value_function(
+        &mut self,
+        module: &crate::Module,
+        zero_value: WrappedZeroValue,
+    ) -> BackendResult {
+        use crate::back::INDENT;
+
+        const RETURN_VARIABLE_NAME: &str = "ret";
+
+        // Write function return type and name
+        if let crate::TypeInner::Array { base, size, .. } = module.types[zero_value.ty].inner {
+            write!(self.out, "typedef ")?;
+            self.write_type(module, zero_value.ty)?;
+            write!(self.out, " ret_")?;
+            self.write_wrapped_zero_value_function_name(module, zero_value)?;
+            self.write_array_size(module, base, size)?;
+            writeln!(self.out, ";")?;
+
+            write!(self.out, "ret_")?;
+            self.write_wrapped_zero_value_function_name(module, zero_value)?;
+        } else {
+            self.write_type(module, zero_value.ty)?;
+        }
+        write!(self.out, " ")?;
+        self.write_wrapped_zero_value_function_name(module, zero_value)?;
+
+        // Write function parameters (none) and start function body
+        writeln!(self.out, "() {{")?;
+
+        // Write `ZeroValue` function.
+        write!(self.out, "{INDENT}return ")?;
+        self.write_default_init(module, zero_value.ty)?;
+        writeln!(self.out, ";")?;
+
+        // End of function body
+        writeln!(self.out, "}}")?;
+        // Write extra new line
+        writeln!(self.out)?;
+
+        Ok(())
+    }
 }
diff --git a/naga/src/back/hlsl/mod.rs b/naga/src/back/hlsl/mod.rs
index fe9740a2f..28edbf70e 100644
--- a/naga/src/back/hlsl/mod.rs
+++ b/naga/src/back/hlsl/mod.rs
@@ -267,6 +267,7 @@ pub enum Error {
 
 #[derive(Default)]
 struct Wrapped {
+    zero_values: crate::FastHashSet<help::WrappedZeroValue>,
     array_lengths: crate::FastHashSet<help::WrappedArrayLength>,
     image_queries: crate::FastHashSet<help::WrappedImageQuery>,
     constructors: crate::FastHashSet<help::WrappedConstructor>,
diff --git a/naga/src/back/hlsl/writer.rs b/naga/src/back/hlsl/writer.rs
index afbfe6076..86d8f8903 100644
--- a/naga/src/back/hlsl/writer.rs
+++ b/naga/src/back/hlsl/writer.rs
@@ -1,5 +1,8 @@
 use super::{
-    help::{WrappedArrayLength, WrappedConstructor, WrappedImageQuery, WrappedStructMatrixAccess},
+    help::{
+        WrappedArrayLength, WrappedConstructor, WrappedImageQuery, WrappedStructMatrixAccess,
+        WrappedZeroValue,
+    },
     storage::StoreValue,
     BackendResult, Error, Options,
 };
@@ -264,6 +267,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
         self.write_special_functions(module)?;
 
         self.write_wrapped_compose_functions(module, &module.global_expressions)?;
+        self.write_wrapped_zero_value_functions(module, &module.global_expressions)?;
 
         // Write all named constants
         let mut constants = module
@@ -2251,7 +2255,10 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
                     self.write_const_expression(module, constant.init)?;
                 }
             }
-            Expression::ZeroValue(ty) => self.write_default_init(module, ty)?,
+            Expression::ZeroValue(ty) => {
+                self.write_wrapped_zero_value_function_name(module, WrappedZeroValue { ty })?;
+                write!(self.out, "()")?;
+            }
             Expression::Compose { ty, ref components } => {
                 match module.types[ty].inner {
                     TypeInner::Struct { .. } | TypeInner::Array { .. } => {
@@ -3394,7 +3401,11 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
     }
 
     /// Helper function that write default zero initialization
-    fn write_default_init(&mut self, module: &Module, ty: Handle<crate::Type>) -> BackendResult {
+    pub(super) fn write_default_init(
+        &mut self,
+        module: &Module,
+        ty: Handle<crate::Type>,
+    ) -> BackendResult {
         write!(self.out, "(")?;
         self.write_type(module, ty)?;
         if let TypeInner::Array { base, size, .. } = module.types[ty].inner {


Test patch:
diff --git a/naga/tests/out/hlsl/access.hlsl b/naga/tests/out/hlsl/access.hlsl
index 47d9cc24f..4f0cb4b83 100644
--- a/naga/tests/out/hlsl/access.hlsl
+++ b/naga/tests/out/hlsl/access.hlsl
@@ -158,10 +158,15 @@ MatCx2InArray ConstructMatCx2InArray(float4x2 arg0[2]) {
     return ret;
 }
 
+typedef float4x2 ret_ZeroValuearray2_float4x2_[2];
+ret_ZeroValuearray2_float4x2_ ZeroValuearray2_float4x2_() {
+    return (float4x2[2])0;
+}
+
 void test_matrix_within_array_within_struct_accesses()
 {
     int idx_1 = 1;
-    MatCx2InArray t_1 = ConstructMatCx2InArray((float4x2[2])0);
+    MatCx2InArray t_1 = ConstructMatCx2InArray(ZeroValuearray2_float4x2_());
 
     int _expr3 = idx_1;
     idx_1 = (_expr3 - 1);
@@ -180,7 +185,7 @@ void test_matrix_within_array_within_struct_accesses()
     float l7_ = __get_col_of_mat4x2(nested_mat_cx2_.am[0], _expr46)[_expr48];
     int _expr55 = idx_1;
     idx_1 = (_expr55 + 1);
-    t_1.am = (__mat4x2[2])(float4x2[2])0;
+    t_1.am = (__mat4x2[2])ZeroValuearray2_float4x2_();
     t_1.am[0] = (__mat4x2)float4x2((8.0).xx, (7.0).xx, (6.0).xx, (5.0).xx);
     t_1.am[0]._0 = (9.0).xx;
     int _expr77 = idx_1;
@@ -231,6 +236,11 @@ ret_Constructarray5_int_ Constructarray5_int_(int arg0, int arg1, int arg2, int
     return ret;
 }
 
+typedef float ret_ZeroValuearray5_array10_float__[5][10];
+ret_ZeroValuearray5_array10_float__ ZeroValuearray5_array10_float__() {
+    return (float[5][10])0;
+}
+
 typedef uint2 ret_Constructarray2_uint2_[2];
 ret_Constructarray2_uint2_ Constructarray2_uint2_(uint2 arg0, uint2 arg1) {
     uint2 ret[2] = { arg0, arg1 };
@@ -262,10 +272,14 @@ float4 foo_vert(uint vi : SV_VertexID) : SV_Position
     c2_ = Constructarray5_int_(a_1, int(b), 3, 4, 5);
     c2_[(vi + 1u)] = 42;
     int value = c2_[vi];
-    const float _e47 = test_arr_as_arg((float[5][10])0);
+    const float _e47 = test_arr_as_arg(ZeroValuearray5_array10_float__());
     return float4(mul(float4((value).xxxx), _matrix), 2.0);
 }
 
+int2 ZeroValueint2() {
+    return (int2)0;
+}
+
 float4 foo_frag() : SV_Target0
 {
     bar.Store(8+16+0, asuint(1.0));
@@ -282,7 +296,7 @@ float4 foo_frag() : SV_Target0
         bar.Store2(144+8, asuint(_value2[1]));
     }
     bar.Store(0+8+160, asuint(1));
-    qux.Store2(0, asuint((int2)0));
+    qux.Store2(0, asuint(ZeroValueint2()));
     return (0.0).xxxx;
 }
 
diff --git a/naga/tests/out/hlsl/constructors.hlsl b/naga/tests/out/hlsl/constructors.hlsl
index 39f313760..90d8db9a3 100644
--- a/naga/tests/out/hlsl/constructors.hlsl
+++ b/naga/tests/out/hlsl/constructors.hlsl
@@ -18,17 +18,50 @@ ret_Constructarray4_int_ Constructarray4_int_(int arg0, int arg1, int arg2, int
     return ret;
 }
 
+bool ZeroValuebool() {
+    return (bool)0;
+}
+
+int ZeroValueint() {
+    return (int)0;
+}
+
+uint ZeroValueuint() {
+    return (uint)0;
+}
+
+float ZeroValuefloat() {
+    return (float)0;
+}
+
+uint2 ZeroValueuint2() {
+    return (uint2)0;
+}
+
+float2x2 ZeroValuefloat2x2() {
+    return (float2x2)0;
+}
+
+typedef Foo ret_ZeroValuearray3_Foo_[3];
+ret_ZeroValuearray3_Foo_ ZeroValuearray3_Foo_() {
+    return (Foo[3])0;
+}
+
+Foo ZeroValueFoo() {
+    return (Foo)0;
+}
+
 static const float3 const2_ = float3(0.0, 1.0, 2.0);
 static const float2x2 const3_ = float2x2(float2(0.0, 1.0), float2(2.0, 3.0));
 static const float2x2 const4_[1] = Constructarray1_float2x2_(float2x2(float2(0.0, 1.0), float2(2.0, 3.0)));
-static const bool cz0_ = (bool)0;
-static const int cz1_ = (int)0;
-static const uint cz2_ = (uint)0;
-static const float cz3_ = (float)0;
-static const uint2 cz4_ = (uint2)0;
-static const float2x2 cz5_ = (float2x2)0;
-static const Foo cz6_[3] = (Foo[3])0;
-static const Foo cz7_ = (Foo)0;
+static const bool cz0_ = ZeroValuebool();
+static const int cz1_ = ZeroValueint();
+static const uint cz2_ = ZeroValueuint();
+static const float cz3_ = ZeroValuefloat();
+static const uint2 cz4_ = ZeroValueuint2();
+static const float2x2 cz5_ = ZeroValuefloat2x2();
+static const Foo cz6_[3] = ZeroValuearray3_Foo_();
+static const Foo cz7_ = ZeroValueFoo();
 static const int cp3_[4] = Constructarray4_int_(0, 1, 2, 3);
 
 Foo ConstructFoo(float4 arg0, int arg1) {
@@ -38,6 +71,10 @@ Foo ConstructFoo(float4 arg0, int arg1) {
     return ret;
 }
 
+float2x3 ZeroValuefloat2x3() {
+    return (float2x3)0;
+}
+
 [numthreads(1, 1, 1)]
 void main()
 {
diff --git a/naga/tests/out/hlsl/globals.hlsl b/naga/tests/out/hlsl/globals.hlsl
index 55faf060d..adf0b28b8 100644
--- a/naga/tests/out/hlsl/globals.hlsl
+++ b/naga/tests/out/hlsl/globals.hlsl
@@ -71,6 +71,10 @@ void test_msl_packed_vec3_as_arg(float3 arg)
     return;
 }
 
+float3x3 ZeroValuefloat3x3() {
+    return (float3x3)0;
+}
+
 FooStruct ConstructFooStruct(float3 arg0, float arg1) {
     FooStruct ret = (FooStruct)0;
     ret.v3_ = arg0;
@@ -91,8 +95,8 @@ void test_msl_packed_vec3_()
     float3 l0_ = data.v3_;
     float2 l1_ = data.v3_.zx;
     test_msl_packed_vec3_as_arg(data.v3_);
-    float3 mvm0_ = mul((float3x3)0, data.v3_);
-    float3 mvm1_ = mul(data.v3_, (float3x3)0);
+    float3 mvm0_ = mul(ZeroValuefloat3x3(), data.v3_);
+    float3 mvm1_ = mul(data.v3_, ZeroValuefloat3x3());
     float3 svm0_ = (data.v3_ * 2.0);
     float3 svm1_ = (2.0 * data.v3_);
 }
diff --git a/naga/tests/out/hlsl/math-functions.hlsl b/naga/tests/out/hlsl/math-functions.hlsl
index 61c59f00c..c1a771c25 100644
--- a/naga/tests/out/hlsl/math-functions.hlsl
+++ b/naga/tests/out/hlsl/math-functions.hlsl
@@ -63,6 +63,10 @@ _frexp_result_vec4_f32_ naga_frexp(float4 arg) {
     return result;
 }
 
+int2 ZeroValueint2() {
+    return (int2)0;
+}
+
 void main()
 {
     float4 v = (0.0).xxxx;
@@ -74,7 +78,7 @@ void main()
     float4 g = refract(v, v, 1.0);
     int4 sign_b = int4(-1, -1, -1, -1);
     float4 sign_d = float4(-1.0, -1.0, -1.0, -1.0);
-    int const_dot = dot((int2)0, (int2)0);
+    int const_dot = dot(ZeroValueint2(), ZeroValueint2());
     uint first_leading_bit_abs = firstbithigh(0u);
     int flb_a = asint(firstbithigh(-1));
     int2 flb_b = asint(firstbithigh((-1).xx));
diff --git a/naga/tests/out/hlsl/operators.hlsl b/naga/tests/out/hlsl/operators.hlsl
index 58ec5a170..eab1a8d9f 100644
--- a/naga/tests/out/hlsl/operators.hlsl
+++ b/naga/tests/out/hlsl/operators.hlsl
@@ -55,6 +55,18 @@ void logical()
     bool4 bitwise_and1_ = ((true).xxxx & (false).xxxx);
 }
 
+float3x3 ZeroValuefloat3x3() {
+    return (float3x3)0;
+}
+
+float4x3 ZeroValuefloat4x3() {
+    return (float4x3)0;
+}
+
+float3x4 ZeroValuefloat3x4() {
+    return (float3x4)0;
+}
+
 void arithmetic()
 {
     float neg0_1 = -(1.0);
@@ -122,13 +134,13 @@ void arithmetic()
         float2 rem4_1 = fmod((2.0).xx, (1.0).xx);
         float2 rem5_1 = fmod((2.0).xx, (1.0).xx);
     }
-    float3x3 add = ((float3x3)0 + (float3x3)0);
-    float3x3 sub = ((float3x3)0 - (float3x3)0);
-    float3x3 mul_scalar0_ = mul(1.0, (float3x3)0);
-    float3x3 mul_scalar1_ = mul((float3x3)0, 2.0);
-    float3 mul_vector0_ = mul((1.0).xxxx, (float4x3)0);
-    float4 mul_vector1_ = mul((float4x3)0, (2.0).xxx);
-    float3x3 mul_ = mul((float3x4)0, (float4x3)0);
+    float3x3 add = (ZeroValuefloat3x3() + ZeroValuefloat3x3());
+    float3x3 sub = (ZeroValuefloat3x3() - ZeroValuefloat3x3());
+    float3x3 mul_scalar0_ = mul(1.0, ZeroValuefloat3x3());
+    float3x3 mul_scalar1_ = mul(ZeroValuefloat3x3(), 2.0);
+    float3 mul_vector0_ = mul((1.0).xxxx, ZeroValuefloat4x3());
+    float4 mul_vector1_ = mul(ZeroValuefloat4x3(), (2.0).xxx);
+    float3x3 mul_ = mul(ZeroValuefloat3x4(), ZeroValuefloat4x3());
 }
 
 void bit()
@@ -199,10 +211,14 @@ void comparison()
     bool4 gte5_ = ((2.0).xxxx >= (1.0).xxxx);
 }
 
+int3 ZeroValueint3() {
+    return (int3)0;
+}
+
 void assignment()
 {
     int a_1 = (int)0;
-    int3 vec0_ = (int3)0;
+    int3 vec0_ = ZeroValueint3();
 
     a_1 = 1;
     int _expr5 = a_1;
diff --git a/naga/tests/out/hlsl/quad-vert.hlsl b/naga/tests/out/hlsl/quad-vert.hlsl
index 4505858a4..5c4eeb7ec 100644
--- a/naga/tests/out/hlsl/quad-vert.hlsl
+++ b/naga/tests/out/hlsl/quad-vert.hlsl
@@ -20,9 +20,14 @@ gl_PerVertex Constructgl_PerVertex(float4 arg0, float arg1, float arg2[1], float
     return ret;
 }
 
+typedef float ret_ZeroValuearray1_float_[1];
+ret_ZeroValuearray1_float_ ZeroValuearray1_float_() {
+    return (float[1])0;
+}
+
 static float2 v_uv = (float2)0;
 static float2 a_uv_1 = (float2)0;
-static gl_PerVertex unnamed = Constructgl_PerVertex(float4(0.0, 0.0, 0.0, 1.0), 1.0, (float[1])0, (float[1])0);
+static gl_PerVertex unnamed = Constructgl_PerVertex(float4(0.0, 0.0, 0.0, 1.0), 1.0, ZeroValuearray1_float_(), ZeroValuearray1_float_());
 static float2 a_pos_1 = (float2)0;
 
 struct VertexOutput_main {
diff --git a/naga/tests/out/hlsl/unnamed-gl-per-vertex.hlsl b/naga/tests/out/hlsl/unnamed-gl-per-vertex.hlsl
index 8270ad4e5..f0f330e7c 100644
--- a/naga/tests/out/hlsl/unnamed-gl-per-vertex.hlsl
+++ b/naga/tests/out/hlsl/unnamed-gl-per-vertex.hlsl
@@ -15,7 +15,12 @@ type_4 Constructtype_4(float4 arg0, float arg1, float arg2[1], float arg3[1]) {
     return ret;
 }
 
-static type_4 global = Constructtype_4(float4(0.0, 0.0, 0.0, 1.0), 1.0, (float[1])0, (float[1])0);
+typedef float ret_ZeroValuearray1_float_[1];
+ret_ZeroValuearray1_float_ ZeroValuearray1_float_() {
+    return (float[1])0;
+}
+
+static type_4 global = Constructtype_4(float4(0.0, 0.0, 0.0, 1.0), 1.0, ZeroValuearray1_float_(), ZeroValuearray1_float_());
 static int global_1 = (int)0;
 
 void function()