xref: /llvm-project/mlir/include/mlir/Dialect/SPIRV/Utils/LayoutUtils.h (revision 31c35285d27ed507ae758aefdca0d9cd05c7f21d)
1 //===-- LayoutUtils.h - Vulkan Layout Util functions ------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines utilities used to get alignment and layout information for
10 // types in SPIR-V dialect.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef MLIR_DIALECT_SPIRV_UTILS_LAYOUTUTILS_H_
15 #define MLIR_DIALECT_SPIRV_UTILS_LAYOUTUTILS_H_
16 
17 #include <cstdint>
18 
19 namespace mlir {
20 class Type;
21 class VectorType;
22 
23 namespace spirv {
24 class ArrayType;
25 class RuntimeArrayType;
26 class StructType;
27 } // namespace spirv
28 
29 /// According to the Vulkan spec "15.6.4. Offset and Stride Assignment":
30 /// "There are different alignment requirements depending on the specific
31 /// resources and on the features enabled on the device."
32 ///
33 /// There are 3 types of alignment: scalar, base, extended.
34 /// See the spec for details.
35 ///
36 /// Note: Even if scalar alignment is supported, it is generally more
37 /// performant to use the base alignment. So here the calculation is based on
38 /// base alignment.
39 ///
40 /// The memory layout must obey the following rules:
41 /// 1. The Offset decoration of any member must be a multiple of its alignment.
42 /// 2. Any ArrayStride or MatrixStride decoration must be a multiple of the
43 /// alignment of the array or matrix as defined above.
44 ///
45 /// According to the SPIR-V spec:
46 /// "The ArrayStride, MatrixStride, and Offset decorations must be large
47 /// enough to hold the size of the objects they affect (that is, specifying
48 /// overlap is invalid)."
49 class VulkanLayoutUtils {
50 public:
51   using Size = uint64_t;
52 
53   /// Returns a new StructType with layout decoration.
54   static spirv::StructType decorateType(spirv::StructType structType);
55 
56   /// Checks whether a type is legal in terms of Vulkan layout info
57   /// decoration. A type is dynamically illegal if it's a composite type in the
58   /// StorageBuffer, PhysicalStorageBuffer, Uniform, and PushConstant Storage
59   /// Classes without layout information.
60   static bool isLegalType(Type type);
61 
62 private:
63   /// Returns a new type with layout decoration. Assigns the type size in bytes
64   /// to the `size`. Assigns the type alignment in bytes to the `alignment`.
65   static Type decorateType(Type type, Size &size, Size &alignment);
66 
67   static Type decorateType(VectorType vectorType, Size &size, Size &alignment);
68   static Type decorateType(spirv::ArrayType arrayType, Size &size,
69                            Size &alignment);
70   static Type decorateType(spirv::RuntimeArrayType arrayType, Size &alignment);
71   static spirv::StructType decorateType(spirv::StructType structType,
72                                         Size &size, Size &alignment);
73 
74   /// Calculates the alignment for the given scalar type.
75   static Size getScalarTypeAlignment(Type scalarType);
76 };
77 
78 } // namespace mlir
79 
80 #endif // MLIR_DIALECT_SPIRV_UTILS_LAYOUTUTILS_H_
81