Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/angle
Path: blob/main_old/src/compiler/translator/BuildSPIRV.h
1693 views
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
// BuildSPIRV: Helper for OutputSPIRV to build SPIR-V.
7
//
8
9
#ifndef COMPILER_TRANSLATOR_BUILDSPIRV_H_
10
#define COMPILER_TRANSLATOR_BUILDSPIRV_H_
11
12
#include "common/FixedVector.h"
13
#include "common/PackedEnums.h"
14
#include "common/bitset_utils.h"
15
#include "common/hash_utils.h"
16
#include "common/spirv/spirv_instruction_builder_autogen.h"
17
#include "compiler/translator/Compiler.h"
18
19
namespace spirv = angle::spirv;
20
21
namespace sh
22
{
23
// Helper classes to map types to ids
24
25
// The same GLSL type may map to multiple SPIR-V types when said GLSL type is used differently in
26
// the shader source, for example used with |invariant| and without, used in an interface block etc.
27
// This type contains the pieces of information that differentiate SPIR-V types derived from the
28
// same GLSL type. This is referred to as "SPIR-V type specialization" henceforth.
29
struct SpirvType;
30
class SpirvTypeSpec
31
{
32
public:
33
// Some of the properties that specialize SPIR-V types apply to structs or arrays, but not to
34
// their fields or basic types. When extracting fields, array elements, columns or basic types
35
// from a type, the following helpers are used to remove any ineffective (and thus incorrect)
36
// specialization.
37
void inferDefaults(const TType &type, TCompiler *compiler);
38
void onArrayElementSelection(bool isElementTypeBlock, bool isElementTypeArray);
39
void onBlockFieldSelection(const TType &fieldType);
40
void onMatrixColumnSelection();
41
void onVectorComponentSelection();
42
43
// If a structure is used in two interface blocks with different layouts, it would have
44
// to generate two SPIR-V types, as its fields' Offset decorations could be different.
45
// For non-block types, when used in an interface block as an array, they could generate
46
// different ArrayStride decorations. As such, the block storage is part of the SPIR-V type
47
// except for non-block non-array types.
48
TLayoutBlockStorage blockStorage = EbsUnspecified;
49
50
// If a structure is used in two I/O blocks or output varyings with and without the invariant
51
// qualifier, it would also have to generate two SPIR-V types, as its fields' Invariant
52
// decorations would be different.
53
bool isInvariantBlock = false;
54
55
// Similarly, a structure containing matrices may be used both with the column_major and
56
// row_major layout qualifier, generating two SPIR-V types with different decorations on its
57
// fields.
58
bool isRowMajorQualifiedBlock = false;
59
60
// Arrays when used in an interface block produce a different type which is decorated with an
61
// ArrayStride. Row-major qualified arrays of matrices can potentially produce a different
62
// stride from column-major ones.
63
bool isRowMajorQualifiedArray = false;
64
65
// Bool is disallowed in interface blocks in SPIR-V. This type is emulated with uint. This
66
// property applies to both blocks with bools in them and the bool type inside the block itself.
67
bool isOrHasBoolInInterfaceBlock = false;
68
69
// When |patch| is specified on an I/O block, the members of the type itself are decorated with
70
// it. This is not recursively applied, and since each I/O block has a unique type, this
71
// doesn't actually result in duplicated types even if it's specializing the type.
72
bool isPatchIOBlock = false;
73
};
74
75
struct SpirvType
76
{
77
// If struct or interface block, the type is identified by the pointer. Note that both
78
// TStructure and TInterfaceBlock inherit from TFieldListCollection, and their difference is
79
// irrelevant as far as SPIR-V type is concerned.
80
const TFieldListCollection *block = nullptr;
81
82
// Otherwise, it's a basic type + column, row and array dimensions, or it's an image
83
// declaration.
84
//
85
// Notes:
86
//
87
// - `precision` turns into a RelaxedPrecision decoration on the variable and instructions.
88
// - `precise` turns into a NoContraction decoration on the instructions.
89
// - `readonly`, `writeonly`, `coherent`, `volatile` and `restrict` only apply to memory object
90
// declarations
91
// - `invariant` only applies to variable or members of a block
92
// - `matrixPacking` only applies to members of a struct
93
TBasicType type = EbtFloat;
94
95
uint8_t primarySize = 1;
96
uint8_t secondarySize = 1;
97
98
TSpan<const unsigned int> arraySizes;
99
100
// Only useful for image types.
101
TLayoutImageInternalFormat imageInternalFormat = EiifUnspecified;
102
103
// For sampled images (i.e. GLSL samplers), there are two type ids; one is the OpTypeImage that
104
// declares the image itself, and one OpTypeSampledImage. `isSamplerBaseImage` distinguishes
105
// between these two types. Note that for the former, the basic type is still Ebt*Sampler* to
106
// distinguish it from storage images (which have a basic type of Ebt*Image*).
107
bool isSamplerBaseImage = false;
108
109
// Anything that can cause the same GLSL type to produce different SPIR-V types.
110
SpirvTypeSpec typeSpec;
111
};
112
113
struct SpirvIdAndIdList
114
{
115
spirv::IdRef id;
116
spirv::IdRefList idList;
117
118
bool operator==(const SpirvIdAndIdList &other) const
119
{
120
return id == other.id && idList == other.idList;
121
}
122
};
123
124
struct SpirvIdAndStorageClass
125
{
126
spirv::IdRef id;
127
spv::StorageClass storageClass;
128
129
bool operator==(const SpirvIdAndStorageClass &other) const
130
{
131
return id == other.id && storageClass == other.storageClass;
132
}
133
};
134
135
struct SpirvTypeHash
136
{
137
size_t operator()(const sh::SpirvType &type) const
138
{
139
// Block storage must only affect the type if it's a block type or array type (in a block).
140
ASSERT(type.typeSpec.blockStorage == sh::EbsUnspecified || type.block != nullptr ||
141
!type.arraySizes.empty());
142
143
// Invariant must only affect the type if it's a block type.
144
ASSERT(!type.typeSpec.isInvariantBlock || type.block != nullptr);
145
146
// Row-major block must only affect the type if it's a block type.
147
ASSERT(!type.typeSpec.isRowMajorQualifiedBlock || type.block != nullptr);
148
149
// Patch must only affect the type if it's a block type.
150
ASSERT(!type.typeSpec.isPatchIOBlock || type.block != nullptr);
151
152
// Row-major array must only affect the type if it's an array of non-square matrices in
153
// an std140 or std430 block.
154
ASSERT(!type.typeSpec.isRowMajorQualifiedArray ||
155
(type.block == nullptr && !type.arraySizes.empty() && type.secondarySize > 1 &&
156
type.primarySize != type.secondarySize &&
157
type.typeSpec.blockStorage != sh::EbsUnspecified));
158
159
size_t result = 0;
160
161
if (!type.arraySizes.empty())
162
{
163
result = angle::ComputeGenericHash(type.arraySizes.data(),
164
type.arraySizes.size() * sizeof(type.arraySizes[0]));
165
}
166
167
if (type.block != nullptr)
168
{
169
return result ^ angle::ComputeGenericHash(&type.block, sizeof(type.block)) ^
170
static_cast<size_t>(type.typeSpec.isInvariantBlock) ^
171
(static_cast<size_t>(type.typeSpec.isRowMajorQualifiedBlock) << 1) ^
172
(static_cast<size_t>(type.typeSpec.isRowMajorQualifiedArray) << 2) ^
173
(static_cast<size_t>(type.typeSpec.isPatchIOBlock) << 3) ^
174
(type.typeSpec.blockStorage << 4);
175
}
176
177
static_assert(sh::EbtLast < 256, "Basic type doesn't fit in uint8_t");
178
static_assert(sh::EbsLast < 8, "Block storage doesn't fit in 3 bits");
179
static_assert(sh::EiifLast < 32, "Image format doesn't fit in 5 bits");
180
ASSERT(type.primarySize > 0 && type.primarySize <= 4);
181
ASSERT(type.secondarySize > 0 && type.secondarySize <= 4);
182
183
const uint8_t properties[4] = {
184
static_cast<uint8_t>(type.type),
185
static_cast<uint8_t>((type.primarySize - 1) | (type.secondarySize - 1) << 2 |
186
type.isSamplerBaseImage << 4),
187
static_cast<uint8_t>(type.typeSpec.blockStorage | type.imageInternalFormat << 3),
188
// Padding because ComputeGenericHash expects a key size divisible by 4
189
};
190
191
return result ^ angle::ComputeGenericHash(properties, sizeof(properties));
192
}
193
};
194
195
struct SpirvIdAndIdListHash
196
{
197
size_t operator()(const SpirvIdAndIdList &key) const
198
{
199
return angle::ComputeGenericHash(key.idList.data(),
200
key.idList.size() * sizeof(key.idList[0])) ^
201
key.id;
202
}
203
};
204
205
struct SpirvIdAndStorageClassHash
206
{
207
size_t operator()(const SpirvIdAndStorageClass &key) const
208
{
209
ASSERT(key.storageClass < 16);
210
return key.storageClass | key.id << 4;
211
}
212
};
213
214
// Data tracked per SPIR-V type (keyed by SpirvType).
215
struct SpirvTypeData
216
{
217
// The SPIR-V id corresponding to the type.
218
spirv::IdRef id;
219
};
220
221
// Decorations to be applied to variable or intermediate ids which are not part of the SPIR-V type
222
// and are not specific enough (like DescriptorSet) to be handled automatically. Currently, these
223
// are:
224
//
225
// RelaxedPrecision: used to implement |lowp| and |mediump|
226
// NoContraction: used to implement |precise|. TODO: support this. It requires the precise
227
// property to be promoted through the nodes in the AST, which currently isn't.
228
// http://anglebug.com/4889
229
// Invariant: used to implement |invariant|, which is applied to output variables.
230
//
231
// Note that Invariant applies to variables and NoContraction to arithmetic instructions, so they
232
// are mutually exclusive and a maximum of 2 decorations are possible. FixedVector::push_back will
233
// ASSERT if the given size is ever not enough.
234
using SpirvDecorations = angle::FixedVector<spv::Decoration, 2>;
235
236
// A block of code. SPIR-V produces forward references to blocks, such as OpBranchConditional
237
// specifying the id of the if and else blocks, each of those referencing the id of the block after
238
// the else. Additionally, local variable declarations are accumulated at the top of the first
239
// block in a function. For these reasons, each block of SPIR-V is generated separately and
240
// assembled at the end of the function, allowing prior blocks to be modified when necessary.
241
struct SpirvBlock
242
{
243
// Id of the block
244
spirv::IdRef labelId;
245
246
// Local variable declarations. Only the first block of a function is allowed to contain any
247
// instructions here.
248
spirv::Blob localVariables;
249
250
// Everything *after* OpLabel (which itself is not generated until blocks are assembled) and
251
// local variables.
252
spirv::Blob body;
253
254
// Whether the block is terminated. Useful for functions without return, asserting that code is
255
// not added after return/break/continue etc (i.e. dead code, which should really be removed
256
// earlier by a transformation, but could also be hacked by returning a bogus block to contain
257
// all the "garbage" to throw away), last switch case without a break, etc.
258
bool isTerminated = false;
259
};
260
261
// Conditional code, constituting ifs, switches and loops.
262
struct SpirvConditional
263
{
264
// The id of blocks that make up the conditional.
265
//
266
// - For if, there are three blocks: the then, else and merge blocks
267
// - For loops, there are four blocks: the condition, body, continue and merge blocks
268
// - For switch, there are a number of blocks based on the cases.
269
//
270
// In all cases, the merge block is the last block in this list. When the conditional is done
271
// with, that's the block that will be made "current" and future instructions written to. The
272
// merge block is also the branch target of "break" instructions.
273
//
274
// For loops, the continue target block is the one before last block in this list.
275
std::vector<spirv::IdRef> blockIds;
276
277
// Up to which block is already generated. Used by nextConditionalBlock() to generate a block
278
// and give it an id pre-determined in blockIds.
279
size_t nextBlockToWrite = 0;
280
281
// Used to determine if continue will affect this (i.e. it's a loop).
282
bool isContinuable = false;
283
// Used to determine if break will affect this (i.e. it's a loop or switch).
284
bool isBreakable = false;
285
};
286
287
// List of known extensions
288
enum class SPIRVExtensions
289
{
290
// GL_OVR_multiview / SPV_KHR_multiview
291
MultiviewOVR = 0,
292
293
InvalidEnum = 1,
294
EnumCount = 1,
295
};
296
297
// Helper class to construct SPIR-V
298
class SPIRVBuilder : angle::NonCopyable
299
{
300
public:
301
SPIRVBuilder(TCompiler *compiler,
302
ShCompileOptions compileOptions,
303
ShHashFunction64 hashFunction,
304
NameMap &nameMap);
305
306
spirv::IdRef getNewId(const SpirvDecorations &decorations);
307
SpirvType getSpirvType(const TType &type, const SpirvTypeSpec &typeSpec) const;
308
const SpirvTypeData &getTypeData(const TType &type, const SpirvTypeSpec &typeSpec);
309
const SpirvTypeData &getTypeDataOverrideTypeSpec(const TType &type,
310
const SpirvTypeSpec &typeSpec);
311
const SpirvTypeData &getSpirvTypeData(const SpirvType &type, const TSymbol *block);
312
spirv::IdRef getBasicTypeId(TBasicType basicType, size_t size);
313
spirv::IdRef getTypePointerId(spirv::IdRef typeId, spv::StorageClass storageClass);
314
spirv::IdRef getFunctionTypeId(spirv::IdRef returnTypeId, const spirv::IdRefList &paramTypeIds);
315
316
// Decorations that may apply to intermediate instructions (in addition to variables).
317
// |precise| is only applicable to arithmetic nodes.
318
SpirvDecorations getDecorations(const TType &type);
319
SpirvDecorations getArithmeticDecorations(const TType &type, bool isPrecise);
320
321
// Extended instructions
322
spirv::IdRef getExtInstImportIdStd();
323
324
spirv::Blob *getSpirvDebug() { return &mSpirvDebug; }
325
spirv::Blob *getSpirvDecorations() { return &mSpirvDecorations; }
326
spirv::Blob *getSpirvTypeAndConstantDecls() { return &mSpirvTypeAndConstantDecls; }
327
spirv::Blob *getSpirvTypePointerDecls() { return &mSpirvTypePointerDecls; }
328
spirv::Blob *getSpirvFunctionTypeDecls() { return &mSpirvFunctionTypeDecls; }
329
spirv::Blob *getSpirvVariableDecls() { return &mSpirvVariableDecls; }
330
spirv::Blob *getSpirvFunctions() { return &mSpirvFunctions; }
331
spirv::Blob *getSpirvCurrentFunctionBlock()
332
{
333
ASSERT(!mSpirvCurrentFunctionBlocks.empty() &&
334
!mSpirvCurrentFunctionBlocks.back().isTerminated);
335
return &mSpirvCurrentFunctionBlocks.back().body;
336
}
337
spirv::IdRef getSpirvCurrentFunctionBlockId()
338
{
339
ASSERT(!mSpirvCurrentFunctionBlocks.empty() &&
340
!mSpirvCurrentFunctionBlocks.back().isTerminated);
341
return mSpirvCurrentFunctionBlocks.back().labelId;
342
}
343
bool isCurrentFunctionBlockTerminated() const
344
{
345
ASSERT(!mSpirvCurrentFunctionBlocks.empty());
346
return mSpirvCurrentFunctionBlocks.back().isTerminated;
347
}
348
void terminateCurrentFunctionBlock()
349
{
350
ASSERT(!mSpirvCurrentFunctionBlocks.empty());
351
mSpirvCurrentFunctionBlocks.back().isTerminated = true;
352
}
353
const SpirvConditional *getCurrentConditional() { return &mConditionalStack.back(); }
354
355
bool isInvariantOutput(const TType &type) const;
356
357
void addCapability(spv::Capability capability);
358
void addExecutionMode(spv::ExecutionMode executionMode);
359
void addExtension(SPIRVExtensions extension);
360
void setEntryPointId(spirv::IdRef id);
361
void addEntryPointInterfaceVariableId(spirv::IdRef id);
362
void writePerVertexBuiltIns(const TType &type, spirv::IdRef typeId);
363
void writeInterfaceVariableDecorations(const TType &type, spirv::IdRef variableId);
364
void writeBranchConditional(spirv::IdRef conditionValue,
365
spirv::IdRef trueBlock,
366
spirv::IdRef falseBlock,
367
spirv::IdRef mergeBlock);
368
void writeBranchConditionalBlockEnd();
369
void writeLoopHeader(spirv::IdRef branchToBlock,
370
spirv::IdRef continueBlock,
371
spirv::IdRef mergeBlock);
372
void writeLoopConditionEnd(spirv::IdRef conditionValue,
373
spirv::IdRef branchToBlock,
374
spirv::IdRef mergeBlock);
375
void writeLoopContinueEnd(spirv::IdRef headerBlock);
376
void writeLoopBodyEnd(spirv::IdRef continueBlock);
377
void writeSwitch(spirv::IdRef conditionValue,
378
spirv::IdRef defaultBlock,
379
const spirv::PairLiteralIntegerIdRefList &targetPairList,
380
spirv::IdRef mergeBlock);
381
void writeSwitchCaseBlockEnd();
382
383
spirv::IdRef getBoolConstant(bool value);
384
spirv::IdRef getUintConstant(uint32_t value);
385
spirv::IdRef getIntConstant(int32_t value);
386
spirv::IdRef getFloatConstant(float value);
387
spirv::IdRef getUvecConstant(uint32_t value, int size);
388
spirv::IdRef getIvecConstant(int32_t value, int size);
389
spirv::IdRef getVecConstant(float value, int size);
390
spirv::IdRef getCompositeConstant(spirv::IdRef typeId, const spirv::IdRefList &values);
391
spirv::IdRef getNullConstant(spirv::IdRef typeId);
392
393
// Helpers to start and end a function.
394
void startNewFunction(spirv::IdRef functionId, const TFunction *func);
395
void assembleSpirvFunctionBlocks();
396
397
// Helper to declare a variable. Function-local variables must be placed in the first block of
398
// the current function.
399
spirv::IdRef declareVariable(spirv::IdRef typeId,
400
spv::StorageClass storageClass,
401
const SpirvDecorations &decorations,
402
spirv::IdRef *initializerId,
403
const char *name);
404
// Helper to declare specialization constants.
405
spirv::IdRef declareSpecConst(TBasicType type, int id, const char *name);
406
407
// Helpers for conditionals.
408
void startConditional(size_t blockCount, bool isContinuable, bool isBreakable);
409
void nextConditionalBlock();
410
void endConditional();
411
bool isInLoop() const;
412
spirv::IdRef getBreakTargetId() const;
413
spirv::IdRef getContinueTargetId() const;
414
415
// TODO: remove name hashing once translation through glslang is removed. That is necessary to
416
// avoid name collision between ANGLE's internal symbols and user-defined ones when compiling
417
// the generated GLSL, but is irrelevant when generating SPIR-V directly. Currently, the SPIR-V
418
// transformer relies on the "mapped" names, which should also be changed when this hashing is
419
// removed.
420
ImmutableString hashName(const TSymbol *symbol);
421
ImmutableString hashTypeName(const TType &type);
422
ImmutableString hashFieldName(const TField *field);
423
ImmutableString hashFunctionName(const TFunction *func);
424
425
spirv::Blob getSpirv();
426
427
private:
428
SpirvTypeData declareType(const SpirvType &type, const TSymbol *block);
429
430
uint32_t calculateBaseAlignmentAndSize(const SpirvType &type, uint32_t *sizeInStorageBlockOut);
431
uint32_t calculateSizeAndWriteOffsetDecorations(const SpirvType &type,
432
spirv::IdRef typeId,
433
uint32_t blockBaseAlignment);
434
void writeMemberDecorations(const SpirvType &type, spirv::IdRef typeId);
435
void writeInterpolationDecoration(TQualifier qualifier, spirv::IdRef id, uint32_t fieldIndex);
436
437
// Helpers for type declaration.
438
void getImageTypeParameters(TBasicType type,
439
spirv::IdRef *sampledTypeOut,
440
spv::Dim *dimOut,
441
spirv::LiteralInteger *depthOut,
442
spirv::LiteralInteger *arrayedOut,
443
spirv::LiteralInteger *multisampledOut,
444
spirv::LiteralInteger *sampledOut);
445
spv::ImageFormat getImageFormat(TLayoutImageInternalFormat imageInternalFormat);
446
447
spirv::IdRef getBasicConstantHelper(uint32_t value,
448
TBasicType type,
449
angle::HashMap<uint32_t, spirv::IdRef> *constants);
450
spirv::IdRef getNullVectorConstantHelper(TBasicType type, int size);
451
spirv::IdRef getVectorConstantHelper(spirv::IdRef valueId, TBasicType type, int size);
452
453
uint32_t nextUnusedBinding();
454
uint32_t nextUnusedInputLocation(uint32_t consumedCount);
455
uint32_t nextUnusedOutputLocation(uint32_t consumedCount);
456
457
void writeExecutionModes(spirv::Blob *blob);
458
void writeExtensions(spirv::Blob *blob);
459
void writeSourceExtensions(spirv::Blob *blob);
460
461
ANGLE_MAYBE_UNUSED TCompiler *mCompiler;
462
ShCompileOptions mCompileOptions;
463
gl::ShaderType mShaderType;
464
465
// Capabilities the shader is using. Accumulated as the instructions are generated. The Shader
466
// capability is unconditionally generated, so it's not tracked.
467
std::set<spv::Capability> mCapabilities;
468
// Execution modes the shader is using. Most execution modes are automatically derived from
469
// shader metadata, but some are only discovered while traversing the tree. Only the latter
470
// execution modes are stored here.
471
angle::BitSet<32> mExecutionModes;
472
// Extensions used by the shader.
473
angle::PackedEnumBitSet<SPIRVExtensions> mExtensions;
474
475
// The list of interface variables and the id of main() populated as the instructions are
476
// generated. Used for the OpEntryPoint instruction.
477
spirv::IdRefList mEntryPointInterfaceList;
478
spirv::IdRef mEntryPointId;
479
480
// Id of imported instructions, if used.
481
spirv::IdRef mExtInstImportIdStd;
482
483
// Current ID bound, used to allocate new ids.
484
spirv::IdRef mNextAvailableId;
485
486
// A map from the AST type to the corresponding SPIR-V ID and associated data. Note that TType
487
// includes a lot of information that pertains to the variable that has the type, not the type
488
// itself. SpirvType instead contains only information that can identify the type itself.
489
angle::HashMap<SpirvType, SpirvTypeData, SpirvTypeHash> mTypeMap;
490
491
// Various sections of SPIR-V. Each section grows as SPIR-V is generated, and the final result
492
// is obtained by stitching the sections together. This puts the instructions in the order
493
// required by the spec.
494
spirv::Blob mSpirvDebug;
495
spirv::Blob mSpirvDecorations;
496
spirv::Blob mSpirvTypeAndConstantDecls;
497
spirv::Blob mSpirvTypePointerDecls;
498
spirv::Blob mSpirvFunctionTypeDecls;
499
spirv::Blob mSpirvVariableDecls;
500
spirv::Blob mSpirvFunctions;
501
// A list of blocks created for the current function. These are assembled by
502
// assembleSpirvFunctionBlocks() when the function is entirely visited. Local variables need to
503
// be inserted at the beginning of the first function block, so the entire SPIR-V of the
504
// function cannot be obtained until it's fully visited.
505
//
506
// The last block in this list is the one currently being written to.
507
std::vector<SpirvBlock> mSpirvCurrentFunctionBlocks;
508
509
// List of constants that are already defined (for reuse).
510
spirv::IdRef mBoolConstants[2];
511
angle::HashMap<uint32_t, spirv::IdRef> mUintConstants;
512
angle::HashMap<uint32_t, spirv::IdRef> mIntConstants;
513
angle::HashMap<uint32_t, spirv::IdRef> mFloatConstants;
514
angle::HashMap<SpirvIdAndIdList, spirv::IdRef, SpirvIdAndIdListHash> mCompositeConstants;
515
// Keyed by typeId, returns the null constant corresponding to that type.
516
std::vector<spirv::IdRef> mNullConstants;
517
518
// List of type pointers that are already defined.
519
// TODO: if all users call getTypeData(), move to SpirvTypeData. http://anglebug.com/4889
520
angle::HashMap<SpirvIdAndStorageClass, spirv::IdRef, SpirvIdAndStorageClassHash>
521
mTypePointerIdMap;
522
523
// List of function types that are already defined.
524
angle::HashMap<SpirvIdAndIdList, spirv::IdRef, SpirvIdAndIdListHash> mFunctionTypeIdMap;
525
526
// Stack of conditionals. When an if, loop or switch is visited, a new conditional scope is
527
// added. When the conditional construct is entirely visited, it's popped. As the blocks of
528
// the conditional constructs are visited, ids are consumed from the top of the stack. When
529
// break or continue is visited, the stack is traversed backwards until a loop or switch is
530
// found.
531
std::vector<SpirvConditional> mConditionalStack;
532
533
// name hashing.
534
ShHashFunction64 mHashFunction;
535
NameMap &mNameMap;
536
537
// Every resource that requires set & binding layout qualifiers is assigned set 0 and an
538
// arbitrary binding. Every input/output that requires a location layout qualifier is assigned
539
// an arbitrary location as well.
540
//
541
// The link-time SPIR-V transformer modifies set, binding and location decorations in SPIR-V
542
// directly.
543
uint32_t mNextUnusedBinding;
544
uint32_t mNextUnusedInputLocation;
545
uint32_t mNextUnusedOutputLocation;
546
};
547
} // namespace sh
548
549
#endif // COMPILER_TRANSLATOR_BUILDSPIRV_H_
550
551