1 //
2 // Copyright 2021 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // spirv_types.h:
7 // Strong types for SPIR-V Ids to prevent mistakes when using the builder and parser APIs.
8 //
9
10 #ifndef COMMON_SPIRV_TYPES_H_
11 #define COMMON_SPIRV_TYPES_H_
12
13 #include "common/FastVector.h"
14
15 #include <vector>
16
17 namespace angle
18 {
19 namespace spirv
20 {
21 template <typename Helper>
22 class BoxedUint32
23 {
24 public:
BoxedUint32()25 BoxedUint32() : mValue{0} {}
BoxedUint32(uint32_t value)26 explicit constexpr BoxedUint32(uint32_t value) : mValue{value} {}
27 template <typename T>
as()28 constexpr T as() const
29 {
30 return static_cast<T>(mValue.value);
31 }
32 constexpr BoxedUint32(const BoxedUint32 &other) = default;
33 constexpr BoxedUint32 &operator=(const BoxedUint32 &other) = default;
uint32_t()34 constexpr operator uint32_t() const { return mValue.value; }
35 constexpr bool operator==(const BoxedUint32 &other) const
36 {
37 return mValue.value == other.mValue.value;
38 }
39 // Applicable to ids, which cannot be 0.
valid()40 constexpr bool valid() const { return static_cast<bool>(mValue.value); }
41
42 private:
43 Helper mValue;
44 };
45
46 struct IdRefHelper
47 {
48 uint32_t value;
49 };
50 struct LiteralIntegerHelper
51 {
52 uint32_t value;
53 };
54
55 using IdRef = BoxedUint32<IdRefHelper>;
56
57 template <>
uint32_t()58 inline constexpr BoxedUint32<IdRefHelper>::operator uint32_t() const
59 {
60 ASSERT(valid());
61 return mValue.value;
62 }
63
64 // IdResult, IdResultType, IdMemorySemantics and IdScope are all translated as IdRef. This makes
65 // the type verification weaker, but stops the API from becoming tediously verbose.
66 using IdResult = IdRef;
67 using IdResultType = IdRef;
68 using IdMemorySemantics = IdRef;
69 using IdScope = IdRef;
70 using LiteralInteger = BoxedUint32<LiteralIntegerHelper>;
71 using LiteralString = const char *;
72 // Note: In ANGLE's use cases, all literals fit in 32 bits.
73 using LiteralContextDependentNumber = LiteralInteger;
74 // TODO(syoussefi): To be made stronger when generating SPIR-V from the translator.
75 // http://anglebug.com/4889
76 using LiteralExtInstInteger = LiteralInteger;
77
78 struct PairLiteralIntegerIdRef
79 {
80 LiteralInteger literal;
81 IdRef id;
82 };
83
84 struct PairIdRefLiteralInteger
85 {
86 IdRef id;
87 LiteralInteger literal;
88 };
89
90 struct PairIdRefIdRef
91 {
92 IdRef id1;
93 IdRef id2;
94 };
95
96 // Some instructions need 4 components. The drivers uniform struct in ANGLE has 8 fields. A value
97 // of 8 means almost no instruction would end up making dynamic allocations. Notable exceptions are
98 // user-defined structs/blocks and OpEntryPoint.
99 constexpr size_t kFastVectorSize = 8;
100
101 template <typename T>
102 using FastVectorHelper = angle::FastVector<T, kFastVectorSize>;
103
104 using IdRefList = FastVectorHelper<IdRef>;
105 using LiteralIntegerList = FastVectorHelper<LiteralInteger>;
106 using PairLiteralIntegerIdRefList = FastVectorHelper<PairLiteralIntegerIdRef>;
107 using PairIdRefLiteralIntegerList = FastVectorHelper<PairIdRefLiteralInteger>;
108 using PairIdRefIdRefList = FastVectorHelper<PairIdRefIdRef>;
109
110 // Id 0 is invalid in SPIR-V.
111 constexpr uint32_t kMinValidId = 1;
112
113 // The SPIR-V blob is a sequence of uint32_t's
114 using Blob = std::vector<uint32_t>;
115
116 // Format of the SPIR-V header.
117 // SPIR-V 1.0 Table 1: First Words of Physical Layout
118 enum HeaderIndex
119 {
120 kHeaderIndexMagic = 0,
121 kHeaderIndexVersion = 1,
122 kHeaderIndexGenerator = 2,
123 kHeaderIndexIndexBound = 3,
124 kHeaderIndexSchema = 4,
125 kHeaderIndexInstructions = 5,
126 };
127
128 // Returns whether SPIR-V is valid. Useful for ASSERTs. Automatically generates a warning if
129 // SPIR-V is not valid.
130 bool Validate(const Blob &blob);
131 void Print(const Blob &blob);
132
133 } // namespace spirv
134 } // namespace angle
135
136 #endif // COMMON_SPIRV_TYPES_H_
137