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