HLSL: Fix automatic location assignment in block IO.
authorHans-Kristian Arntzen <post@arntzen-software.no>
Tue, 20 Apr 2021 11:03:58 +0000 (13:03 +0200)
committerHans-Kristian Arntzen <post@arntzen-software.no>
Tue, 20 Apr 2021 11:04:26 +0000 (13:04 +0200)
reference/shaders-hlsl-no-opt/vert/block-io-auto-location-assignment.vert [new file with mode: 0644]
shaders-hlsl-no-opt/vert/block-io-auto-location-assignment.vert [new file with mode: 0644]
spirv_glsl.cpp
spirv_glsl.hpp
spirv_hlsl.cpp
spirv_msl.cpp
spirv_msl.hpp

diff --git a/reference/shaders-hlsl-no-opt/vert/block-io-auto-location-assignment.vert b/reference/shaders-hlsl-no-opt/vert/block-io-auto-location-assignment.vert
new file mode 100644 (file)
index 0000000..d6d6481
--- /dev/null
@@ -0,0 +1,37 @@
+struct Bar
+{
+    float v[2];
+    float w;
+};
+
+struct V
+{
+    float a : TEXCOORD0;
+    float b[2] : TEXCOORD1;
+    Bar c[2] : TEXCOORD3;
+    Bar d : TEXCOORD9;
+};
+
+static V _14;
+
+void vert_main()
+{
+    _14.a = 1.0f;
+    _14.b[0] = 2.0f;
+    _14.b[1] = 3.0f;
+    _14.c[0].v[0] = 4.0f;
+    _14.c[0].v[1] = 5.0f;
+    _14.c[0].w = 6.0f;
+    _14.c[1].v[0] = 7.0f;
+    _14.c[1].v[1] = 8.0f;
+    _14.c[1].w = 9.0f;
+    _14.d.v[0] = 10.0f;
+    _14.d.v[1] = 11.0f;
+    _14.d.w = 12.0f;
+}
+
+void main(out V stage_output_14)
+{
+    vert_main();
+    stage_output_14 = _14;
+}
diff --git a/shaders-hlsl-no-opt/vert/block-io-auto-location-assignment.vert b/shaders-hlsl-no-opt/vert/block-io-auto-location-assignment.vert
new file mode 100644 (file)
index 0000000..98c39bd
--- /dev/null
@@ -0,0 +1,31 @@
+#version 450
+
+struct Bar
+{
+       float v[2];
+       float w;
+};
+
+layout(location = 0) out V
+{
+       float a;
+       float b[2];
+       Bar c[2];
+       Bar d;
+};
+
+void main()
+{
+       a = 1.0;
+       b[0] = 2.0;
+       b[1] = 3.0;
+       c[0].v[0] = 4.0;
+       c[0].v[1] = 5.0;
+       c[0].w = 6.0;
+       c[1].v[0] = 7.0;
+       c[1].v[1] = 8.0;
+       c[1].w = 9.0;
+       d.v[0] = 10.0;
+       d.v[1] = 11.0;
+       d.w = 12.0;
+}
index 5acbf84..944104b 100644 (file)
@@ -15905,15 +15905,7 @@ uint32_t CompilerGLSL::get_accumulated_member_location(const SPIRVariable &var,
                if (has_member_decoration(type.self, mbr_idx, DecorationLocation))
                        location = get_member_decoration(type.self, mbr_idx, DecorationLocation);
 
-               uint32_t location_count = 1;
-
-               if (mbr_type.columns > 1)
-                       location_count = mbr_type.columns;
-
-               if (!mbr_type.array.empty())
-                       for (uint32_t j = 0; j < uint32_t(mbr_type.array.size()); j++)
-                               location_count *= to_array_size_literal(mbr_type, j);
-
+               uint32_t location_count = type_to_location_count(mbr_type);
                location += location_count;
        }
 
@@ -15949,3 +15941,25 @@ StorageClass CompilerGLSL::get_expression_effective_storage_class(uint32_t ptr)
        else
                return expression_type(ptr).storage;
 }
+
+uint32_t CompilerGLSL::type_to_location_count(const SPIRType &type) const
+{
+       uint32_t count;
+       if (type.basetype == SPIRType::Struct)
+       {
+               uint32_t mbr_count = uint32_t(type.member_types.size());
+               count = 0;
+               for (uint32_t i = 0; i < mbr_count; i++)
+                       count += type_to_location_count(get<SPIRType>(type.member_types[i]));
+       }
+       else
+       {
+               count = type.columns > 1 ? type.columns : 1;
+       }
+
+       uint32_t dim_count = uint32_t(type.array.size());
+       for (uint32_t i = 0; i < dim_count; i++)
+               count *= to_array_size_literal(type, i);
+
+       return count;
+}
index ae01f5c..bbd229a 100644 (file)
@@ -756,6 +756,7 @@ protected:
        uint32_t type_to_packed_alignment(const SPIRType &type, const Bitset &flags, BufferPackingStandard packing);
        uint32_t type_to_packed_array_stride(const SPIRType &type, const Bitset &flags, BufferPackingStandard packing);
        uint32_t type_to_packed_size(const SPIRType &type, const Bitset &flags, BufferPackingStandard packing);
+       uint32_t type_to_location_count(const SPIRType &type) const;
 
        std::string bitcast_glsl(const SPIRType &result_type, uint32_t arg);
        virtual std::string bitcast_glsl_op(const SPIRType &result_type, const SPIRType &argument_type);
index c0b6d1d..52c0a16 100644 (file)
@@ -865,24 +865,10 @@ void CompilerHLSL::emit_io_block(const SPIRVariable &var)
        begin_scope();
        type.member_name_cache.clear();
 
-       uint32_t base_location = get_decoration(var.self, DecorationLocation);
-
        for (uint32_t i = 0; i < uint32_t(type.member_types.size()); i++)
        {
-               string semantic;
-               if (has_member_decoration(type.self, i, DecorationLocation))
-               {
-                       uint32_t location = get_member_decoration(type.self, i, DecorationLocation);
-                       semantic = join(" : ", to_semantic(location, execution.model, var.storage));
-               }
-               else
-               {
-                       // If the block itself has a location, but not its members, use the implicit location.
-                       // There could be a conflict if the block members partially specialize the locations.
-                       // It is unclear how SPIR-V deals with this. Assume this does not happen for now.
-                       uint32_t location = base_location + i;
-                       semantic = join(" : ", to_semantic(location, execution.model, var.storage));
-               }
+               uint32_t location = get_accumulated_member_location(var, i, false);
+               string semantic = join(" : ", to_semantic(location, execution.model, var.storage));
 
                add_member_name(type, i);
 
index f904319..2d6308a 100644 (file)
@@ -1914,28 +1914,6 @@ void CompilerMSL::mark_as_packable(SPIRType &type)
        }
 }
 
-uint32_t CompilerMSL::type_to_location_count(const SPIRType &type) const
-{
-       uint32_t count;
-       if (type.basetype == SPIRType::Struct)
-       {
-               uint32_t mbr_count = uint32_t(type.member_types.size());
-               count = 0;
-               for (uint32_t i = 0; i < mbr_count; i++)
-                       count += type_to_location_count(get<SPIRType>(type.member_types[i]));
-       }
-       else
-       {
-               count = type.columns > 1 ? type.columns : 1;
-       }
-
-       uint32_t dim_count = uint32_t(type.array.size());
-       for (uint32_t i = 0; i < dim_count; i++)
-               count *= to_array_size_literal(type, i);
-
-       return count;
-}
-
 // If a shader input exists at the location, it is marked as being used by this shader
 void CompilerMSL::mark_location_as_used_by_shader(uint32_t location, const SPIRType &type,
                                                   StorageClass storage, bool fallback)
index 97800ab..a777dc7 100644 (file)
@@ -981,7 +981,6 @@ protected:
 
        std::unordered_map<StageSetBinding, std::pair<MSLResourceBinding, bool>, InternalHasher> resource_bindings;
        std::unordered_map<StageSetBinding, uint32_t, InternalHasher> resource_arg_buff_idx_to_binding_number;
-       uint32_t type_to_location_count(const SPIRType &type) const;
 
        uint32_t next_metal_resource_index_buffer = 0;
        uint32_t next_metal_resource_index_texture = 0;