• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2014-2020 The Khronos Group Inc.
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a copy
4 // of this software and/or associated documentation files (the "Materials"),
5 // to deal in the Materials without restriction, including without limitation
6 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
7 // and/or sell copies of the Materials, and to permit persons to whom the
8 // Materials are furnished to do so, subject to the following conditions:
9 //
10 // The above copyright notice and this permission notice shall be included in
11 // all copies or substantial portions of the Materials.
12 //
13 // MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS
14 // STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND
15 // HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/
16 //
17 // THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 // FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
23 // IN THE MATERIALS.
24 
25 #include <assert.h>
26 #include <string.h>
27 #include <algorithm>
28 #include <cstdlib>
29 #include <iostream>
30 #include <unordered_map>
31 #include <unordered_set>
32 #include <utility>
33 #include <fstream>
34 
35 #include "jsoncpp/dist/json/json.h"
36 
37 #include "jsonToSpirv.h"
38 
39 namespace spv {
40 
41 // The set of objects that hold all the instruction/operand
42 // parameterization information.
43 InstructionValues InstructionDesc;
44 
45 // The ordered list (in printing order) of printing classes
46 // (specification subsections).
47 PrintingClasses InstructionPrintingClasses;
48 
49 // Note: There is no entry for OperandOpcode. Use InstructionDesc instead.
50 EnumDefinition OperandClassParams[OperandOpcode];
51 EnumValues SourceLanguageParams;
52 EnumValues ExecutionModelParams;
53 EnumValues AddressingParams;
54 EnumValues MemoryParams;
55 EnumValues ExecutionModeParams;
56 EnumValues StorageParams;
57 EnumValues SamplerAddressingModeParams;
58 EnumValues SamplerFilterModeParams;
59 EnumValues ImageFormatParams;
60 EnumValues ImageChannelOrderParams;
61 EnumValues ImageChannelDataTypeParams;
62 EnumValues ImageOperandsParams;
63 EnumValues FPFastMathParams;
64 EnumValues FPRoundingModeParams;
65 EnumValues FPDenormModeParams;
66 EnumValues FPOperationModeParams;
67 EnumValues QuantizationModesParams;
68 EnumValues OverflowModesParams;
69 EnumValues LinkageTypeParams;
70 EnumValues DecorationParams;
71 EnumValues BuiltInParams;
72 EnumValues DimensionalityParams;
73 EnumValues FuncParamAttrParams;
74 EnumValues AccessQualifierParams;
75 EnumValues GroupOperationParams;
76 EnumValues LoopControlParams;
77 EnumValues SelectionControlParams;
78 EnumValues FunctionControlParams;
79 EnumValues MemorySemanticsParams;
80 EnumValues MemoryAccessParams;
81 EnumValues ScopeParams;
82 EnumValues KernelEnqueueFlagsParams;
83 EnumValues KernelProfilingInfoParams;
84 EnumValues CapabilityParams;
85 EnumValues RayFlagsParams;
86 EnumValues RayQueryIntersectionParams;
87 EnumValues RayQueryCommittedIntersectionTypeParams;
88 EnumValues RayQueryCandidateIntersectionTypeParams;
89 EnumValues FragmentShadingRateParams;
90 EnumValues PackedVectorFormatParams;
91 
ReadFile(const std::string & path)92 std::pair<bool, std::string> ReadFile(const std::string& path)
93 {
94     std::ifstream fstream(path, std::ios::in);
95     if (fstream) {
96         std::string contents;
97         fstream.seekg(0, std::ios::end);
98         contents.reserve((unsigned int)fstream.tellg());
99         fstream.seekg(0, std::ios::beg);
100         contents.assign((std::istreambuf_iterator<char>(fstream)),
101                         std::istreambuf_iterator<char>());
102         return std::make_pair(true, contents);
103     }
104     return std::make_pair(false, "");
105 }
106 
107 struct ClassOptionality {
108     OperandClass type;
109     bool optional;
110 };
111 
112 // Converts the |operandKind| and |quantifier| pair used to describe operands
113 // in the JSON grammar to OperandClass and optionality used in this repo.
ToOperandClassAndOptionality(const std::string & operandKind,const std::string & quantifier)114 ClassOptionality ToOperandClassAndOptionality(const std::string& operandKind, const std::string& quantifier)
115 {
116     assert(quantifier.empty() || quantifier == "?" || quantifier == "*");
117 
118     if (operandKind == "IdRef") {
119         if (quantifier.empty())
120             return {OperandId, false};
121         else if (quantifier == "?")
122             return {OperandId, true};
123         else
124             return {OperandVariableIds, false};
125     } else if (operandKind == "LiteralInteger") {
126         if (quantifier.empty())
127             return {OperandLiteralNumber, false};
128         if (quantifier == "?")
129             return {OperandOptionalLiteral, true};
130         else
131             return {OperandVariableLiterals, false};
132     } else if (operandKind == "LiteralString") {
133         if (quantifier.empty())
134             return {OperandLiteralString, false};
135         else if (quantifier == "?")
136             return {OperandLiteralString, true};
137         else {
138             return {OperandOptionalLiteralStrings, false};
139         }
140     } else if (operandKind == "PairLiteralIntegerIdRef") {
141         // Used by OpSwitch in the grammar
142         return {OperandVariableLiteralId, false};
143     } else if (operandKind == "PairIdRefLiteralInteger") {
144         // Used by OpGroupMemberDecorate in the grammar
145         return {OperandVariableIdLiteral, false};
146     } else if (operandKind == "PairIdRefIdRef") {
147         // Used by OpPhi in the grammar
148         return {OperandVariableIds, false};
149     } else {
150         OperandClass type = OperandNone;
151         if (operandKind == "IdMemorySemantics" || operandKind == "MemorySemantics") {
152             type = OperandMemorySemantics;
153         } else if (operandKind == "IdScope" || operandKind == "Scope") {
154             type = OperandScope;
155         } else if (operandKind == "LiteralExtInstInteger") {
156             type = OperandLiteralNumber;
157         } else if (operandKind == "LiteralSpecConstantOpInteger") {
158             type = OperandLiteralNumber;
159         } else if (operandKind == "LiteralContextDependentNumber") {
160             type = OperandAnySizeLiteralNumber;
161         } else if (operandKind == "SourceLanguage") {
162             type = OperandSource;
163         } else if (operandKind == "ExecutionModel") {
164             type = OperandExecutionModel;
165         } else if (operandKind == "AddressingModel") {
166             type = OperandAddressing;
167         } else if (operandKind == "MemoryModel") {
168             type = OperandMemory;
169         } else if (operandKind == "ExecutionMode") {
170             type = OperandExecutionMode;
171         } else if (operandKind == "StorageClass") {
172             type = OperandStorage;
173         } else if (operandKind == "Dim") {
174             type = OperandDimensionality;
175         } else if (operandKind == "SamplerAddressingMode") {
176             type = OperandSamplerAddressingMode;
177         } else if (operandKind == "SamplerFilterMode") {
178             type = OperandSamplerFilterMode;
179         } else if (operandKind == "ImageFormat") {
180             type = OperandSamplerImageFormat;
181         } else if (operandKind == "ImageChannelOrder") {
182             type = OperandImageChannelOrder;
183         } else if (operandKind == "ImageChannelDataType") {
184             type = OperandImageChannelDataType;
185         } else if (operandKind == "FPRoundingMode") {
186             type = OperandFPRoundingMode;
187         } else if (operandKind == "FPDenormMode") {
188             type = OperandFPDenormMode;
189         } else if (operandKind == "FPOperationMode") {
190             type = OperandFPOperationMode;
191         } else if (operandKind == "QuantizationModes") {
192             type = OperandQuantizationModes;
193         } else if (operandKind == "OverflowModes") {
194             type = OperandOverflowModes;
195         } else if (operandKind == "LinkageType") {
196             type = OperandLinkageType;
197         } else if (operandKind == "AccessQualifier") {
198             type = OperandAccessQualifier;
199         } else if (operandKind == "FunctionParameterAttribute") {
200             type = OperandFuncParamAttr;
201         } else if (operandKind == "Decoration") {
202             type = OperandDecoration;
203         } else if (operandKind == "BuiltIn") {
204             type = OperandBuiltIn;
205         } else if (operandKind == "GroupOperation") {
206             type = OperandGroupOperation;
207         } else if (operandKind == "KernelEnqueueFlags") {
208             type = OperandKernelEnqueueFlags;
209         } else if (operandKind == "KernelProfilingInfo") {
210             type = OperandKernelProfilingInfo;
211         } else if (operandKind == "Capability") {
212             type = OperandCapability;
213         } else if (operandKind == "ImageOperands") {
214             type = OperandImageOperands;
215         } else if (operandKind == "FPFastMathMode") {
216             type = OperandFPFastMath;
217         } else if (operandKind == "SelectionControl") {
218             type = OperandSelect;
219         } else if (operandKind == "LoopControl") {
220             type = OperandLoop;
221         } else if (operandKind == "FunctionControl") {
222             type = OperandFunction;
223         } else if (operandKind == "MemoryAccess") {
224             type = OperandMemoryOperands;
225         } else if (operandKind == "RayFlags") {
226             type = OperandRayFlags;
227         } else if (operandKind == "RayQueryIntersection") {
228             type = OperandRayQueryIntersection;
229         } else if (operandKind == "RayQueryCommittedIntersectionType") {
230             type = OperandRayQueryCommittedIntersectionType;
231         } else if (operandKind == "RayQueryCandidateIntersectionType") {
232             type = OperandRayQueryCandidateIntersectionType;
233         } else if (operandKind == "FragmentShadingRate") {
234             type = OperandFragmentShadingRate;
235         } else if (operandKind == "PackedVectorFormat") {
236             type = OperandPackedVectorFormat;
237         }
238 
239         if (type == OperandNone) {
240             std::cerr << "Unhandled operand kind found: " << operandKind << std::endl;
241             exit(1);
242         }
243         return {type, !quantifier.empty()};
244     }
245 }
246 
IsTypeOrResultId(const std::string & str,bool * isType,bool * isResult)247 bool IsTypeOrResultId(const std::string& str, bool* isType, bool* isResult)
248 {
249     if (str == "IdResultType")
250         return *isType = true;
251     if (str == "IdResult")
252         return *isResult = true;
253     return false;
254 }
255 
256 // Given a number string, returns the position of the only bits set in the number.
257 // So it requires the number is a power of two.
NumberStringToBit(const std::string & str)258 unsigned int NumberStringToBit(const std::string& str)
259 {
260     char* parseEnd;
261     unsigned int value = (unsigned int)std::strtol(str.c_str(), &parseEnd, 16);
262     assert(!(value & (value - 1)) && "input number is not a power of 2");
263     unsigned int bit = 0;
264     for (; value; value >>= 1) ++bit;
265     return bit;
266 }
267 
jsonToSpirv(const std::string & jsonPath,bool buildingHeaders)268 void jsonToSpirv(const std::string& jsonPath, bool buildingHeaders)
269 {
270     // only do this once.
271     static bool initialized = false;
272     if (initialized)
273         return;
274     initialized = true;
275 
276     // Read the JSON grammar file.
277     bool fileReadOk = false;
278     std::string content;
279     std::tie(fileReadOk, content) = ReadFile(jsonPath);
280     if (!fileReadOk) {
281         std::cerr << "Failed to read JSON grammar file: "
282                   << jsonPath << std::endl;
283         exit(1);
284     }
285 
286     // Decode the JSON grammar file.
287     Json::Reader reader;
288     Json::Value root;
289     if (!reader.parse(content, root)) {
290         std::cerr << "Failed to parse JSON grammar:\n"
291                   << reader.getFormattedErrorMessages();
292         exit(1);
293     }
294 
295     // Layouts for all instructions.
296 
297     // A lambda for returning capabilities from a JSON object as strings.
298     const auto getCaps = [](const Json::Value& object) {
299         EnumCaps result;
300         const auto& caps = object["capabilities"];
301         if (!caps.empty()) {
302             assert(caps.isArray());
303             for (const auto& cap : caps) {
304                 result.emplace_back(cap.asString());
305             }
306         }
307         return result;
308     };
309 
310     // A lambda for returning extensions from a JSON object as strings.
311     const auto getExts = [](const Json::Value& object) {
312         Extensions result;
313         const auto& exts = object["extensions"];
314         if (!exts.empty()) {
315             assert(exts.isArray());
316             for (const auto& ext : exts) {
317                 result.emplace_back(ext.asString());
318             }
319         }
320         return result;
321     };
322 
323     // set up the printing classes
324     std::unordered_set<std::string> tags;  // short-lived local for error checking below
325     const Json::Value printingClasses = root["instruction_printing_class"];
326     for (const auto& printingClass : printingClasses) {
327         if (printingClass["tag"].asString().size() > 0)
328             tags.insert(printingClass["tag"].asString()); // just for error checking
329         else
330             std::cerr << "Error: each instruction_printing_class requires a non-empty \"tag\"" << std::endl;
331         if (buildingHeaders || printingClass["tag"].asString() != "@exclude") {
332             InstructionPrintingClasses.push_back({printingClass["tag"].asString(),
333                                                   printingClass["heading"].asString()});
334         }
335     }
336 
337     // process the instructions
338     const Json::Value insts = root["instructions"];
339     unsigned maxOpcode = 0;
340     bool firstOpcode = true;
341     for (const auto& inst : insts) {
342         const auto printingClass = inst["class"].asString();
343         if (printingClass.size() == 0) {
344             std::cerr << "Error: " << inst["opname"].asString()
345                       << " requires a non-empty printing \"class\" tag" << std::endl;
346         }
347         if (!buildingHeaders && printingClass == "@exclude")
348             continue;
349         if (tags.find(printingClass) == tags.end()) {
350             std::cerr << "Error: " << inst["opname"].asString()
351                       << " requires a \"class\" declared as a \"tag\" in \"instruction printing_class\""
352                       << std::endl;
353         }
354         const auto opcode = inst["opcode"].asUInt();
355         const std::string name = inst["opname"].asString();
356         if (firstOpcode) {
357           maxOpcode = opcode;
358           firstOpcode = false;
359         } else {
360           if (maxOpcode > opcode) {
361             std::cerr << "Error: " << name
362                       << " is out of order. It follows the instruction with opcode " << maxOpcode
363                       << std::endl;
364             std::exit(1);
365           } else {
366             maxOpcode = opcode;
367           }
368         }
369         EnumCaps caps = getCaps(inst);
370         std::string version = inst["version"].asString();
371         std::string lastVersion = inst["lastVersion"].asString();
372         Extensions exts = getExts(inst);
373         OperandParameters operands;
374         bool defResultId = false;
375         bool defTypeId = false;
376         for (const auto& operand : inst["operands"]) {
377             const std::string kind = operand["kind"].asString();
378             const std::string quantifier = operand.get("quantifier", "").asString();
379             const std::string doc = operand.get("name", "").asString();
380             if (!IsTypeOrResultId(kind, &defTypeId, &defResultId)) {
381                 const auto p = ToOperandClassAndOptionality(kind, quantifier);
382                 operands.push(p.type, doc, p.optional);
383             }
384         }
385         InstructionDesc.emplace_back(
386             std::move(EnumValue(opcode, name,
387                                 std::move(caps), std::move(version), std::move(lastVersion), std::move(exts),
388                                 std::move(operands))),
389              printingClass, defTypeId, defResultId);
390     }
391 
392     // Specific additional context-dependent operands
393 
394     // Populate dest with EnumValue objects constructed from source.
395     const auto populateEnumValues = [&getCaps,&getExts](EnumValues* dest, const Json::Value& source, bool bitEnum) {
396         // A lambda for determining the numeric value to be used for a given
397         // enumerant in JSON form, and whether that value is a 0 in a bitfield.
398         auto getValue = [&bitEnum](const Json::Value& enumerant) {
399             std::pair<unsigned, bool> result{0u,false};
400             if (!bitEnum) {
401                 result.first = enumerant["value"].asUInt();
402             } else {
403                 const unsigned int bit = NumberStringToBit(enumerant["value"].asString());
404                 if (bit == 0)
405                     result.second = true;
406                 else
407                     result.first = bit - 1;  // This is the *shift* amount.
408             }
409             return result;
410         };
411 
412         unsigned maxValue = 0;
413         bool firstValue = true;
414         for (const auto& enumerant : source["enumerants"]) {
415             unsigned value;
416             bool skip_zero_in_bitfield;
417             std::tie(value, skip_zero_in_bitfield) = getValue(enumerant);
418             if (skip_zero_in_bitfield)
419                 continue;
420             if (firstValue) {
421               maxValue = value;
422               firstValue = false;
423             } else {
424               if (maxValue > value) {
425                 std::cerr << "Error: " << source["kind"] << " enumerant " << enumerant["enumerant"]
426                           << " is out of order. It has value " <<  value
427                           << " but follows the enumerant with value " << maxValue << std::endl;
428                 std::exit(1);
429               } else {
430                 maxValue = value;
431               }
432             }
433             EnumCaps caps(getCaps(enumerant));
434             std::string version = enumerant["version"].asString();
435             std::string lastVersion = enumerant["lastVersion"].asString();
436             Extensions exts(getExts(enumerant));
437             OperandParameters params;
438             const Json::Value& paramsJson = enumerant["parameters"];
439             if (!paramsJson.empty()) {  // This enumerant has parameters.
440                 assert(paramsJson.isArray());
441                 for (const auto& param : paramsJson) {
442                     const std::string kind = param["kind"].asString();
443                     const std::string doc = param.get("name", "").asString();
444                     const auto p = ToOperandClassAndOptionality(kind, ""); // All parameters are required!
445                     params.push(p.type, doc);
446                 }
447             }
448             dest->emplace_back(
449                 value, enumerant["enumerant"].asString(),
450                 std::move(caps), std::move(version), std::move(lastVersion), std::move(exts), std::move(params));
451         }
452     };
453 
454     const auto establishOperandClass = [&populateEnumValues](
455             const std::string& enumName, spv::OperandClass operandClass,
456             spv::EnumValues* enumValues, const Json::Value& operandEnum, const std::string& category) {
457         assert(category == "BitEnum" || category == "ValueEnum");
458         bool bitEnum = (category == "BitEnum");
459         populateEnumValues(enumValues, operandEnum, bitEnum);
460         OperandClassParams[operandClass].set(enumName, enumValues, bitEnum);
461     };
462 
463     const Json::Value operandEnums = root["operand_kinds"];
464     for (const auto& operandEnum : operandEnums) {
465         const std::string enumName = operandEnum["kind"].asString();
466         const std::string category = operandEnum["category"].asString();
467         if (enumName == "SourceLanguage") {
468             establishOperandClass(enumName, OperandSource, &SourceLanguageParams, operandEnum, category);
469         } else if (enumName == "Decoration") {
470             establishOperandClass(enumName, OperandDecoration, &DecorationParams, operandEnum, category);
471         } else if (enumName == "ExecutionMode") {
472             establishOperandClass(enumName, OperandExecutionMode, &ExecutionModeParams, operandEnum, category);
473         } else if (enumName == "Capability") {
474             establishOperandClass(enumName, OperandCapability, &CapabilityParams, operandEnum, category);
475         } else if (enumName == "AddressingModel") {
476             establishOperandClass(enumName, OperandAddressing, &AddressingParams, operandEnum, category);
477         } else if (enumName == "MemoryModel") {
478             establishOperandClass(enumName, OperandMemory, &MemoryParams, operandEnum, category);
479         } else if (enumName == "MemorySemantics") {
480             establishOperandClass(enumName, OperandMemorySemantics, &MemorySemanticsParams, operandEnum, category);
481         } else if (enumName == "ExecutionModel") {
482             establishOperandClass(enumName, OperandExecutionModel, &ExecutionModelParams, operandEnum, category);
483         } else if (enumName == "StorageClass") {
484             establishOperandClass(enumName, OperandStorage, &StorageParams, operandEnum, category);
485         } else if (enumName == "SamplerAddressingMode") {
486             establishOperandClass(enumName, OperandSamplerAddressingMode, &SamplerAddressingModeParams, operandEnum, category);
487         } else if (enumName == "SamplerFilterMode") {
488             establishOperandClass(enumName, OperandSamplerFilterMode, &SamplerFilterModeParams, operandEnum, category);
489         } else if (enumName == "ImageFormat") {
490             establishOperandClass(enumName, OperandSamplerImageFormat, &ImageFormatParams, operandEnum, category);
491         } else if (enumName == "ImageChannelOrder") {
492             establishOperandClass(enumName, OperandImageChannelOrder, &ImageChannelOrderParams, operandEnum, category);
493         } else if (enumName == "ImageChannelDataType") {
494             establishOperandClass(enumName, OperandImageChannelDataType, &ImageChannelDataTypeParams, operandEnum, category);
495         } else if (enumName == "ImageOperands") {
496             establishOperandClass(enumName, OperandImageOperands, &ImageOperandsParams, operandEnum, category);
497         } else if (enumName == "FPFastMathMode") {
498             establishOperandClass(enumName, OperandFPFastMath, &FPFastMathParams, operandEnum, category);
499         } else if (enumName == "FPRoundingMode") {
500             establishOperandClass(enumName, OperandFPRoundingMode, &FPRoundingModeParams, operandEnum, category);
501         } else if (enumName == "FPDenormMode") {
502             establishOperandClass(enumName, OperandFPDenormMode, &FPDenormModeParams, operandEnum, category);
503         } else if (enumName == "FPOperationMode") {
504             establishOperandClass(enumName, OperandFPOperationMode, &FPOperationModeParams, operandEnum, category);
505         } else if (enumName == "QuantizationModes") {
506             establishOperandClass(enumName, OperandQuantizationModes, &QuantizationModesParams, operandEnum, category);
507         } else if (enumName == "OverflowModes") {
508             establishOperandClass(enumName, OperandOverflowModes, &OverflowModesParams, operandEnum, category);
509         } else if (enumName == "LinkageType") {
510             establishOperandClass(enumName, OperandLinkageType, &LinkageTypeParams, operandEnum, category);
511         } else if (enumName == "FunctionParameterAttribute") {
512             establishOperandClass(enumName, OperandFuncParamAttr, &FuncParamAttrParams, operandEnum, category);
513         } else if (enumName == "AccessQualifier") {
514             establishOperandClass(enumName, OperandAccessQualifier, &AccessQualifierParams, operandEnum, category);
515         } else if (enumName == "BuiltIn") {
516             establishOperandClass(enumName, OperandBuiltIn, &BuiltInParams, operandEnum, category);
517         } else if (enumName == "SelectionControl") {
518             establishOperandClass(enumName, OperandSelect, &SelectionControlParams, operandEnum, category);
519         } else if (enumName == "LoopControl") {
520             establishOperandClass(enumName, OperandLoop, &LoopControlParams, operandEnum, category);
521         } else if (enumName == "FunctionControl") {
522             establishOperandClass(enumName, OperandFunction, &FunctionControlParams, operandEnum, category);
523         } else if (enumName == "Dim") {
524             establishOperandClass(enumName, OperandDimensionality, &DimensionalityParams, operandEnum, category);
525         } else if (enumName == "MemoryAccess") {
526             establishOperandClass(enumName, OperandMemoryOperands, &MemoryAccessParams, operandEnum, category);
527         } else if (enumName == "Scope") {
528             establishOperandClass(enumName, OperandScope, &ScopeParams, operandEnum, category);
529         } else if (enumName == "GroupOperation") {
530             establishOperandClass(enumName, OperandGroupOperation, &GroupOperationParams, operandEnum, category);
531         } else if (enumName == "KernelEnqueueFlags") {
532             establishOperandClass(enumName, OperandKernelEnqueueFlags, &KernelEnqueueFlagsParams, operandEnum, category);
533         } else if (enumName == "KernelProfilingInfo") {
534             establishOperandClass(enumName, OperandKernelProfilingInfo, &KernelProfilingInfoParams, operandEnum, category);
535         } else if (enumName == "RayFlags") {
536             establishOperandClass(enumName, OperandRayFlags, &RayFlagsParams, operandEnum, category);
537         } else if (enumName == "RayQueryIntersection") {
538             establishOperandClass(enumName, OperandRayQueryIntersection, &RayQueryIntersectionParams, operandEnum, category);
539         } else if (enumName == "RayQueryCommittedIntersectionType") {
540             establishOperandClass(enumName, OperandRayQueryCommittedIntersectionType, &RayQueryCommittedIntersectionTypeParams, operandEnum, category);
541         } else if (enumName == "RayQueryCandidateIntersectionType") {
542             establishOperandClass(enumName, OperandRayQueryCandidateIntersectionType, &RayQueryCandidateIntersectionTypeParams, operandEnum, category);
543         } else if (enumName == "FragmentShadingRate") {
544             establishOperandClass(enumName, OperandFragmentShadingRate, &FragmentShadingRateParams, operandEnum, category);
545         } else if (enumName == "PackedVectorFormat") {
546             establishOperandClass(enumName, OperandPackedVectorFormat, &PackedVectorFormatParams, operandEnum, category);
547         }
548     }
549 }
550 
551 };  // end namespace spv
552