packages feed

spirv-reflect-ffi (empty) → 0.1

raw patch · 9 files changed

+10651/−0 lines, 9 filesdep +basedep +bytestringdep +directory

Dependencies added: base, bytestring, directory, filepath, spirv-reflect-ffi, spirv-reflect-types, tasty, tasty-hunit, text, vector

Files

+ ChangeLog.md view
@@ -0,0 +1,7 @@+# Changelog for spirv-reflect-ffi++## [0.1] - 2022-09-04++* Initial release.++[0.1]: https://gitlab.com/dpwiz/spirv-reflect/-/tree/v0.1-ffi
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright IC Rainbow (c) 2022++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of Author name here nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ cbits/include/spirv/unified1/spirv.h view
@@ -0,0 +1,2542 @@+/*+** Copyright (c) 2014-2020 The Khronos Group Inc.+** +** Permission is hereby granted, free of charge, to any person obtaining a copy+** of this software and/or associated documentation files (the "Materials"),+** to deal in the Materials without restriction, including without limitation+** the rights to use, copy, modify, merge, publish, distribute, sublicense,+** and/or sell copies of the Materials, and to permit persons to whom the+** Materials are furnished to do so, subject to the following conditions:+** +** The above copyright notice and this permission notice shall be included in+** all copies or substantial portions of the Materials.+** +** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS+** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND+** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS+** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL+** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING+** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS+** IN THE MATERIALS.+*/++/*+** This header is automatically generated by the same tool that creates+** the Binary Section of the SPIR-V specification.+*/++/*+** Enumeration tokens for SPIR-V, in various styles:+**   C, C++, C++11, JSON, Lua, Python, C#, D+** +** - C will have tokens with a "Spv" prefix, e.g.: SpvSourceLanguageGLSL+** - C++ will have tokens in the "spv" name space, e.g.: spv::SourceLanguageGLSL+** - C++11 will use enum classes in the spv namespace, e.g.: spv::SourceLanguage::GLSL+** - Lua will use tables, e.g.: spv.SourceLanguage.GLSL+** - Python will use dictionaries, e.g.: spv['SourceLanguage']['GLSL']+** - C# will use enum classes in the Specification class located in the "Spv" namespace,+**     e.g.: Spv.Specification.SourceLanguage.GLSL+** - D will have tokens under the "spv" module, e.g: spv.SourceLanguage.GLSL+** +** Some tokens act like mask values, which can be OR'd together,+** while others are mutually exclusive.  The mask-like ones have+** "Mask" in their name, and a parallel enum that has the shift+** amount (1 << x) for each corresponding enumerant.+*/++#ifndef spirv_H+#define spirv_H++typedef unsigned int SpvId;++#define SPV_VERSION 0x10600+#define SPV_REVISION 1++static const unsigned int SpvMagicNumber = 0x07230203;+static const unsigned int SpvVersion = 0x00010600;+static const unsigned int SpvRevision = 1;+static const unsigned int SpvOpCodeMask = 0xffff;+static const unsigned int SpvWordCountShift = 16;++typedef enum SpvSourceLanguage_ {+    SpvSourceLanguageUnknown = 0,+    SpvSourceLanguageESSL = 1,+    SpvSourceLanguageGLSL = 2,+    SpvSourceLanguageOpenCL_C = 3,+    SpvSourceLanguageOpenCL_CPP = 4,+    SpvSourceLanguageHLSL = 5,+    SpvSourceLanguageCPP_for_OpenCL = 6,+    SpvSourceLanguageSYCL = 7,+    SpvSourceLanguageMax = 0x7fffffff,+} SpvSourceLanguage;++typedef enum SpvExecutionModel_ {+    SpvExecutionModelVertex = 0,+    SpvExecutionModelTessellationControl = 1,+    SpvExecutionModelTessellationEvaluation = 2,+    SpvExecutionModelGeometry = 3,+    SpvExecutionModelFragment = 4,+    SpvExecutionModelGLCompute = 5,+    SpvExecutionModelKernel = 6,+    SpvExecutionModelTaskNV = 5267,+    SpvExecutionModelMeshNV = 5268,+    SpvExecutionModelRayGenerationKHR = 5313,+    SpvExecutionModelRayGenerationNV = 5313,+    SpvExecutionModelIntersectionKHR = 5314,+    SpvExecutionModelIntersectionNV = 5314,+    SpvExecutionModelAnyHitKHR = 5315,+    SpvExecutionModelAnyHitNV = 5315,+    SpvExecutionModelClosestHitKHR = 5316,+    SpvExecutionModelClosestHitNV = 5316,+    SpvExecutionModelMissKHR = 5317,+    SpvExecutionModelMissNV = 5317,+    SpvExecutionModelCallableKHR = 5318,+    SpvExecutionModelCallableNV = 5318,+    SpvExecutionModelMax = 0x7fffffff,+} SpvExecutionModel;++typedef enum SpvAddressingModel_ {+    SpvAddressingModelLogical = 0,+    SpvAddressingModelPhysical32 = 1,+    SpvAddressingModelPhysical64 = 2,+    SpvAddressingModelPhysicalStorageBuffer64 = 5348,+    SpvAddressingModelPhysicalStorageBuffer64EXT = 5348,+    SpvAddressingModelMax = 0x7fffffff,+} SpvAddressingModel;++typedef enum SpvMemoryModel_ {+    SpvMemoryModelSimple = 0,+    SpvMemoryModelGLSL450 = 1,+    SpvMemoryModelOpenCL = 2,+    SpvMemoryModelVulkan = 3,+    SpvMemoryModelVulkanKHR = 3,+    SpvMemoryModelMax = 0x7fffffff,+} SpvMemoryModel;++typedef enum SpvExecutionMode_ {+    SpvExecutionModeInvocations = 0,+    SpvExecutionModeSpacingEqual = 1,+    SpvExecutionModeSpacingFractionalEven = 2,+    SpvExecutionModeSpacingFractionalOdd = 3,+    SpvExecutionModeVertexOrderCw = 4,+    SpvExecutionModeVertexOrderCcw = 5,+    SpvExecutionModePixelCenterInteger = 6,+    SpvExecutionModeOriginUpperLeft = 7,+    SpvExecutionModeOriginLowerLeft = 8,+    SpvExecutionModeEarlyFragmentTests = 9,+    SpvExecutionModePointMode = 10,+    SpvExecutionModeXfb = 11,+    SpvExecutionModeDepthReplacing = 12,+    SpvExecutionModeDepthGreater = 14,+    SpvExecutionModeDepthLess = 15,+    SpvExecutionModeDepthUnchanged = 16,+    SpvExecutionModeLocalSize = 17,+    SpvExecutionModeLocalSizeHint = 18,+    SpvExecutionModeInputPoints = 19,+    SpvExecutionModeInputLines = 20,+    SpvExecutionModeInputLinesAdjacency = 21,+    SpvExecutionModeTriangles = 22,+    SpvExecutionModeInputTrianglesAdjacency = 23,+    SpvExecutionModeQuads = 24,+    SpvExecutionModeIsolines = 25,+    SpvExecutionModeOutputVertices = 26,+    SpvExecutionModeOutputPoints = 27,+    SpvExecutionModeOutputLineStrip = 28,+    SpvExecutionModeOutputTriangleStrip = 29,+    SpvExecutionModeVecTypeHint = 30,+    SpvExecutionModeContractionOff = 31,+    SpvExecutionModeInitializer = 33,+    SpvExecutionModeFinalizer = 34,+    SpvExecutionModeSubgroupSize = 35,+    SpvExecutionModeSubgroupsPerWorkgroup = 36,+    SpvExecutionModeSubgroupsPerWorkgroupId = 37,+    SpvExecutionModeLocalSizeId = 38,+    SpvExecutionModeLocalSizeHintId = 39,+    SpvExecutionModeSubgroupUniformControlFlowKHR = 4421,+    SpvExecutionModePostDepthCoverage = 4446,+    SpvExecutionModeDenormPreserve = 4459,+    SpvExecutionModeDenormFlushToZero = 4460,+    SpvExecutionModeSignedZeroInfNanPreserve = 4461,+    SpvExecutionModeRoundingModeRTE = 4462,+    SpvExecutionModeRoundingModeRTZ = 4463,+    SpvExecutionModeStencilRefReplacingEXT = 5027,+    SpvExecutionModeOutputLinesNV = 5269,+    SpvExecutionModeOutputPrimitivesNV = 5270,+    SpvExecutionModeDerivativeGroupQuadsNV = 5289,+    SpvExecutionModeDerivativeGroupLinearNV = 5290,+    SpvExecutionModeOutputTrianglesNV = 5298,+    SpvExecutionModePixelInterlockOrderedEXT = 5366,+    SpvExecutionModePixelInterlockUnorderedEXT = 5367,+    SpvExecutionModeSampleInterlockOrderedEXT = 5368,+    SpvExecutionModeSampleInterlockUnorderedEXT = 5369,+    SpvExecutionModeShadingRateInterlockOrderedEXT = 5370,+    SpvExecutionModeShadingRateInterlockUnorderedEXT = 5371,+    SpvExecutionModeSharedLocalMemorySizeINTEL = 5618,+    SpvExecutionModeRoundingModeRTPINTEL = 5620,+    SpvExecutionModeRoundingModeRTNINTEL = 5621,+    SpvExecutionModeFloatingPointModeALTINTEL = 5622,+    SpvExecutionModeFloatingPointModeIEEEINTEL = 5623,+    SpvExecutionModeMaxWorkgroupSizeINTEL = 5893,+    SpvExecutionModeMaxWorkDimINTEL = 5894,+    SpvExecutionModeNoGlobalOffsetINTEL = 5895,+    SpvExecutionModeNumSIMDWorkitemsINTEL = 5896,+    SpvExecutionModeSchedulerTargetFmaxMhzINTEL = 5903,+    SpvExecutionModeNamedBarrierCountINTEL = 6417,+    SpvExecutionModeMax = 0x7fffffff,+} SpvExecutionMode;++typedef enum SpvStorageClass_ {+    SpvStorageClassUniformConstant = 0,+    SpvStorageClassInput = 1,+    SpvStorageClassUniform = 2,+    SpvStorageClassOutput = 3,+    SpvStorageClassWorkgroup = 4,+    SpvStorageClassCrossWorkgroup = 5,+    SpvStorageClassPrivate = 6,+    SpvStorageClassFunction = 7,+    SpvStorageClassGeneric = 8,+    SpvStorageClassPushConstant = 9,+    SpvStorageClassAtomicCounter = 10,+    SpvStorageClassImage = 11,+    SpvStorageClassStorageBuffer = 12,+    SpvStorageClassCallableDataKHR = 5328,+    SpvStorageClassCallableDataNV = 5328,+    SpvStorageClassIncomingCallableDataKHR = 5329,+    SpvStorageClassIncomingCallableDataNV = 5329,+    SpvStorageClassRayPayloadKHR = 5338,+    SpvStorageClassRayPayloadNV = 5338,+    SpvStorageClassHitAttributeKHR = 5339,+    SpvStorageClassHitAttributeNV = 5339,+    SpvStorageClassIncomingRayPayloadKHR = 5342,+    SpvStorageClassIncomingRayPayloadNV = 5342,+    SpvStorageClassShaderRecordBufferKHR = 5343,+    SpvStorageClassShaderRecordBufferNV = 5343,+    SpvStorageClassPhysicalStorageBuffer = 5349,+    SpvStorageClassPhysicalStorageBufferEXT = 5349,+    SpvStorageClassCodeSectionINTEL = 5605,+    SpvStorageClassDeviceOnlyINTEL = 5936,+    SpvStorageClassHostOnlyINTEL = 5937,+    SpvStorageClassMax = 0x7fffffff,+} SpvStorageClass;++typedef enum SpvDim_ {+    SpvDim1D = 0,+    SpvDim2D = 1,+    SpvDim3D = 2,+    SpvDimCube = 3,+    SpvDimRect = 4,+    SpvDimBuffer = 5,+    SpvDimSubpassData = 6,+    SpvDimMax = 0x7fffffff,+} SpvDim;++typedef enum SpvSamplerAddressingMode_ {+    SpvSamplerAddressingModeNone = 0,+    SpvSamplerAddressingModeClampToEdge = 1,+    SpvSamplerAddressingModeClamp = 2,+    SpvSamplerAddressingModeRepeat = 3,+    SpvSamplerAddressingModeRepeatMirrored = 4,+    SpvSamplerAddressingModeMax = 0x7fffffff,+} SpvSamplerAddressingMode;++typedef enum SpvSamplerFilterMode_ {+    SpvSamplerFilterModeNearest = 0,+    SpvSamplerFilterModeLinear = 1,+    SpvSamplerFilterModeMax = 0x7fffffff,+} SpvSamplerFilterMode;++typedef enum SpvImageFormat_ {+    SpvImageFormatUnknown = 0,+    SpvImageFormatRgba32f = 1,+    SpvImageFormatRgba16f = 2,+    SpvImageFormatR32f = 3,+    SpvImageFormatRgba8 = 4,+    SpvImageFormatRgba8Snorm = 5,+    SpvImageFormatRg32f = 6,+    SpvImageFormatRg16f = 7,+    SpvImageFormatR11fG11fB10f = 8,+    SpvImageFormatR16f = 9,+    SpvImageFormatRgba16 = 10,+    SpvImageFormatRgb10A2 = 11,+    SpvImageFormatRg16 = 12,+    SpvImageFormatRg8 = 13,+    SpvImageFormatR16 = 14,+    SpvImageFormatR8 = 15,+    SpvImageFormatRgba16Snorm = 16,+    SpvImageFormatRg16Snorm = 17,+    SpvImageFormatRg8Snorm = 18,+    SpvImageFormatR16Snorm = 19,+    SpvImageFormatR8Snorm = 20,+    SpvImageFormatRgba32i = 21,+    SpvImageFormatRgba16i = 22,+    SpvImageFormatRgba8i = 23,+    SpvImageFormatR32i = 24,+    SpvImageFormatRg32i = 25,+    SpvImageFormatRg16i = 26,+    SpvImageFormatRg8i = 27,+    SpvImageFormatR16i = 28,+    SpvImageFormatR8i = 29,+    SpvImageFormatRgba32ui = 30,+    SpvImageFormatRgba16ui = 31,+    SpvImageFormatRgba8ui = 32,+    SpvImageFormatR32ui = 33,+    SpvImageFormatRgb10a2ui = 34,+    SpvImageFormatRg32ui = 35,+    SpvImageFormatRg16ui = 36,+    SpvImageFormatRg8ui = 37,+    SpvImageFormatR16ui = 38,+    SpvImageFormatR8ui = 39,+    SpvImageFormatR64ui = 40,+    SpvImageFormatR64i = 41,+    SpvImageFormatMax = 0x7fffffff,+} SpvImageFormat;++typedef enum SpvImageChannelOrder_ {+    SpvImageChannelOrderR = 0,+    SpvImageChannelOrderA = 1,+    SpvImageChannelOrderRG = 2,+    SpvImageChannelOrderRA = 3,+    SpvImageChannelOrderRGB = 4,+    SpvImageChannelOrderRGBA = 5,+    SpvImageChannelOrderBGRA = 6,+    SpvImageChannelOrderARGB = 7,+    SpvImageChannelOrderIntensity = 8,+    SpvImageChannelOrderLuminance = 9,+    SpvImageChannelOrderRx = 10,+    SpvImageChannelOrderRGx = 11,+    SpvImageChannelOrderRGBx = 12,+    SpvImageChannelOrderDepth = 13,+    SpvImageChannelOrderDepthStencil = 14,+    SpvImageChannelOrdersRGB = 15,+    SpvImageChannelOrdersRGBx = 16,+    SpvImageChannelOrdersRGBA = 17,+    SpvImageChannelOrdersBGRA = 18,+    SpvImageChannelOrderABGR = 19,+    SpvImageChannelOrderMax = 0x7fffffff,+} SpvImageChannelOrder;++typedef enum SpvImageChannelDataType_ {+    SpvImageChannelDataTypeSnormInt8 = 0,+    SpvImageChannelDataTypeSnormInt16 = 1,+    SpvImageChannelDataTypeUnormInt8 = 2,+    SpvImageChannelDataTypeUnormInt16 = 3,+    SpvImageChannelDataTypeUnormShort565 = 4,+    SpvImageChannelDataTypeUnormShort555 = 5,+    SpvImageChannelDataTypeUnormInt101010 = 6,+    SpvImageChannelDataTypeSignedInt8 = 7,+    SpvImageChannelDataTypeSignedInt16 = 8,+    SpvImageChannelDataTypeSignedInt32 = 9,+    SpvImageChannelDataTypeUnsignedInt8 = 10,+    SpvImageChannelDataTypeUnsignedInt16 = 11,+    SpvImageChannelDataTypeUnsignedInt32 = 12,+    SpvImageChannelDataTypeHalfFloat = 13,+    SpvImageChannelDataTypeFloat = 14,+    SpvImageChannelDataTypeUnormInt24 = 15,+    SpvImageChannelDataTypeUnormInt101010_2 = 16,+    SpvImageChannelDataTypeMax = 0x7fffffff,+} SpvImageChannelDataType;++typedef enum SpvImageOperandsShift_ {+    SpvImageOperandsBiasShift = 0,+    SpvImageOperandsLodShift = 1,+    SpvImageOperandsGradShift = 2,+    SpvImageOperandsConstOffsetShift = 3,+    SpvImageOperandsOffsetShift = 4,+    SpvImageOperandsConstOffsetsShift = 5,+    SpvImageOperandsSampleShift = 6,+    SpvImageOperandsMinLodShift = 7,+    SpvImageOperandsMakeTexelAvailableShift = 8,+    SpvImageOperandsMakeTexelAvailableKHRShift = 8,+    SpvImageOperandsMakeTexelVisibleShift = 9,+    SpvImageOperandsMakeTexelVisibleKHRShift = 9,+    SpvImageOperandsNonPrivateTexelShift = 10,+    SpvImageOperandsNonPrivateTexelKHRShift = 10,+    SpvImageOperandsVolatileTexelShift = 11,+    SpvImageOperandsVolatileTexelKHRShift = 11,+    SpvImageOperandsSignExtendShift = 12,+    SpvImageOperandsZeroExtendShift = 13,+    SpvImageOperandsNontemporalShift = 14,+    SpvImageOperandsOffsetsShift = 16,+    SpvImageOperandsMax = 0x7fffffff,+} SpvImageOperandsShift;++typedef enum SpvImageOperandsMask_ {+    SpvImageOperandsMaskNone = 0,+    SpvImageOperandsBiasMask = 0x00000001,+    SpvImageOperandsLodMask = 0x00000002,+    SpvImageOperandsGradMask = 0x00000004,+    SpvImageOperandsConstOffsetMask = 0x00000008,+    SpvImageOperandsOffsetMask = 0x00000010,+    SpvImageOperandsConstOffsetsMask = 0x00000020,+    SpvImageOperandsSampleMask = 0x00000040,+    SpvImageOperandsMinLodMask = 0x00000080,+    SpvImageOperandsMakeTexelAvailableMask = 0x00000100,+    SpvImageOperandsMakeTexelAvailableKHRMask = 0x00000100,+    SpvImageOperandsMakeTexelVisibleMask = 0x00000200,+    SpvImageOperandsMakeTexelVisibleKHRMask = 0x00000200,+    SpvImageOperandsNonPrivateTexelMask = 0x00000400,+    SpvImageOperandsNonPrivateTexelKHRMask = 0x00000400,+    SpvImageOperandsVolatileTexelMask = 0x00000800,+    SpvImageOperandsVolatileTexelKHRMask = 0x00000800,+    SpvImageOperandsSignExtendMask = 0x00001000,+    SpvImageOperandsZeroExtendMask = 0x00002000,+    SpvImageOperandsNontemporalMask = 0x00004000,+    SpvImageOperandsOffsetsMask = 0x00010000,+} SpvImageOperandsMask;++typedef enum SpvFPFastMathModeShift_ {+    SpvFPFastMathModeNotNaNShift = 0,+    SpvFPFastMathModeNotInfShift = 1,+    SpvFPFastMathModeNSZShift = 2,+    SpvFPFastMathModeAllowRecipShift = 3,+    SpvFPFastMathModeFastShift = 4,+    SpvFPFastMathModeAllowContractFastINTELShift = 16,+    SpvFPFastMathModeAllowReassocINTELShift = 17,+    SpvFPFastMathModeMax = 0x7fffffff,+} SpvFPFastMathModeShift;++typedef enum SpvFPFastMathModeMask_ {+    SpvFPFastMathModeMaskNone = 0,+    SpvFPFastMathModeNotNaNMask = 0x00000001,+    SpvFPFastMathModeNotInfMask = 0x00000002,+    SpvFPFastMathModeNSZMask = 0x00000004,+    SpvFPFastMathModeAllowRecipMask = 0x00000008,+    SpvFPFastMathModeFastMask = 0x00000010,+    SpvFPFastMathModeAllowContractFastINTELMask = 0x00010000,+    SpvFPFastMathModeAllowReassocINTELMask = 0x00020000,+} SpvFPFastMathModeMask;++typedef enum SpvFPRoundingMode_ {+    SpvFPRoundingModeRTE = 0,+    SpvFPRoundingModeRTZ = 1,+    SpvFPRoundingModeRTP = 2,+    SpvFPRoundingModeRTN = 3,+    SpvFPRoundingModeMax = 0x7fffffff,+} SpvFPRoundingMode;++typedef enum SpvLinkageType_ {+    SpvLinkageTypeExport = 0,+    SpvLinkageTypeImport = 1,+    SpvLinkageTypeLinkOnceODR = 2,+    SpvLinkageTypeMax = 0x7fffffff,+} SpvLinkageType;++typedef enum SpvAccessQualifier_ {+    SpvAccessQualifierReadOnly = 0,+    SpvAccessQualifierWriteOnly = 1,+    SpvAccessQualifierReadWrite = 2,+    SpvAccessQualifierMax = 0x7fffffff,+} SpvAccessQualifier;++typedef enum SpvFunctionParameterAttribute_ {+    SpvFunctionParameterAttributeZext = 0,+    SpvFunctionParameterAttributeSext = 1,+    SpvFunctionParameterAttributeByVal = 2,+    SpvFunctionParameterAttributeSret = 3,+    SpvFunctionParameterAttributeNoAlias = 4,+    SpvFunctionParameterAttributeNoCapture = 5,+    SpvFunctionParameterAttributeNoWrite = 6,+    SpvFunctionParameterAttributeNoReadWrite = 7,+    SpvFunctionParameterAttributeMax = 0x7fffffff,+} SpvFunctionParameterAttribute;++typedef enum SpvDecoration_ {+    SpvDecorationRelaxedPrecision = 0,+    SpvDecorationSpecId = 1,+    SpvDecorationBlock = 2,+    SpvDecorationBufferBlock = 3,+    SpvDecorationRowMajor = 4,+    SpvDecorationColMajor = 5,+    SpvDecorationArrayStride = 6,+    SpvDecorationMatrixStride = 7,+    SpvDecorationGLSLShared = 8,+    SpvDecorationGLSLPacked = 9,+    SpvDecorationCPacked = 10,+    SpvDecorationBuiltIn = 11,+    SpvDecorationNoPerspective = 13,+    SpvDecorationFlat = 14,+    SpvDecorationPatch = 15,+    SpvDecorationCentroid = 16,+    SpvDecorationSample = 17,+    SpvDecorationInvariant = 18,+    SpvDecorationRestrict = 19,+    SpvDecorationAliased = 20,+    SpvDecorationVolatile = 21,+    SpvDecorationConstant = 22,+    SpvDecorationCoherent = 23,+    SpvDecorationNonWritable = 24,+    SpvDecorationNonReadable = 25,+    SpvDecorationUniform = 26,+    SpvDecorationUniformId = 27,+    SpvDecorationSaturatedConversion = 28,+    SpvDecorationStream = 29,+    SpvDecorationLocation = 30,+    SpvDecorationComponent = 31,+    SpvDecorationIndex = 32,+    SpvDecorationBinding = 33,+    SpvDecorationDescriptorSet = 34,+    SpvDecorationOffset = 35,+    SpvDecorationXfbBuffer = 36,+    SpvDecorationXfbStride = 37,+    SpvDecorationFuncParamAttr = 38,+    SpvDecorationFPRoundingMode = 39,+    SpvDecorationFPFastMathMode = 40,+    SpvDecorationLinkageAttributes = 41,+    SpvDecorationNoContraction = 42,+    SpvDecorationInputAttachmentIndex = 43,+    SpvDecorationAlignment = 44,+    SpvDecorationMaxByteOffset = 45,+    SpvDecorationAlignmentId = 46,+    SpvDecorationMaxByteOffsetId = 47,+    SpvDecorationNoSignedWrap = 4469,+    SpvDecorationNoUnsignedWrap = 4470,+    SpvDecorationExplicitInterpAMD = 4999,+    SpvDecorationOverrideCoverageNV = 5248,+    SpvDecorationPassthroughNV = 5250,+    SpvDecorationViewportRelativeNV = 5252,+    SpvDecorationSecondaryViewportRelativeNV = 5256,+    SpvDecorationPerPrimitiveNV = 5271,+    SpvDecorationPerViewNV = 5272,+    SpvDecorationPerTaskNV = 5273,+    SpvDecorationPerVertexKHR = 5285,+    SpvDecorationPerVertexNV = 5285,+    SpvDecorationNonUniform = 5300,+    SpvDecorationNonUniformEXT = 5300,+    SpvDecorationRestrictPointer = 5355,+    SpvDecorationRestrictPointerEXT = 5355,+    SpvDecorationAliasedPointer = 5356,+    SpvDecorationAliasedPointerEXT = 5356,+    SpvDecorationBindlessSamplerNV = 5398,+    SpvDecorationBindlessImageNV = 5399,+    SpvDecorationBoundSamplerNV = 5400,+    SpvDecorationBoundImageNV = 5401,+    SpvDecorationSIMTCallINTEL = 5599,+    SpvDecorationReferencedIndirectlyINTEL = 5602,+    SpvDecorationClobberINTEL = 5607,+    SpvDecorationSideEffectsINTEL = 5608,+    SpvDecorationVectorComputeVariableINTEL = 5624,+    SpvDecorationFuncParamIOKindINTEL = 5625,+    SpvDecorationVectorComputeFunctionINTEL = 5626,+    SpvDecorationStackCallINTEL = 5627,+    SpvDecorationGlobalVariableOffsetINTEL = 5628,+    SpvDecorationCounterBuffer = 5634,+    SpvDecorationHlslCounterBufferGOOGLE = 5634,+    SpvDecorationHlslSemanticGOOGLE = 5635,+    SpvDecorationUserSemantic = 5635,+    SpvDecorationUserTypeGOOGLE = 5636,+    SpvDecorationFunctionRoundingModeINTEL = 5822,+    SpvDecorationFunctionDenormModeINTEL = 5823,+    SpvDecorationRegisterINTEL = 5825,+    SpvDecorationMemoryINTEL = 5826,+    SpvDecorationNumbanksINTEL = 5827,+    SpvDecorationBankwidthINTEL = 5828,+    SpvDecorationMaxPrivateCopiesINTEL = 5829,+    SpvDecorationSinglepumpINTEL = 5830,+    SpvDecorationDoublepumpINTEL = 5831,+    SpvDecorationMaxReplicatesINTEL = 5832,+    SpvDecorationSimpleDualPortINTEL = 5833,+    SpvDecorationMergeINTEL = 5834,+    SpvDecorationBankBitsINTEL = 5835,+    SpvDecorationForcePow2DepthINTEL = 5836,+    SpvDecorationBurstCoalesceINTEL = 5899,+    SpvDecorationCacheSizeINTEL = 5900,+    SpvDecorationDontStaticallyCoalesceINTEL = 5901,+    SpvDecorationPrefetchINTEL = 5902,+    SpvDecorationStallEnableINTEL = 5905,+    SpvDecorationFuseLoopsInFunctionINTEL = 5907,+    SpvDecorationAliasScopeINTEL = 5914,+    SpvDecorationNoAliasINTEL = 5915,+    SpvDecorationBufferLocationINTEL = 5921,+    SpvDecorationIOPipeStorageINTEL = 5944,+    SpvDecorationFunctionFloatingPointModeINTEL = 6080,+    SpvDecorationSingleElementVectorINTEL = 6085,+    SpvDecorationVectorComputeCallableFunctionINTEL = 6087,+    SpvDecorationMediaBlockIOINTEL = 6140,+    SpvDecorationMax = 0x7fffffff,+} SpvDecoration;++typedef enum SpvBuiltIn_ {+    SpvBuiltInPosition = 0,+    SpvBuiltInPointSize = 1,+    SpvBuiltInClipDistance = 3,+    SpvBuiltInCullDistance = 4,+    SpvBuiltInVertexId = 5,+    SpvBuiltInInstanceId = 6,+    SpvBuiltInPrimitiveId = 7,+    SpvBuiltInInvocationId = 8,+    SpvBuiltInLayer = 9,+    SpvBuiltInViewportIndex = 10,+    SpvBuiltInTessLevelOuter = 11,+    SpvBuiltInTessLevelInner = 12,+    SpvBuiltInTessCoord = 13,+    SpvBuiltInPatchVertices = 14,+    SpvBuiltInFragCoord = 15,+    SpvBuiltInPointCoord = 16,+    SpvBuiltInFrontFacing = 17,+    SpvBuiltInSampleId = 18,+    SpvBuiltInSamplePosition = 19,+    SpvBuiltInSampleMask = 20,+    SpvBuiltInFragDepth = 22,+    SpvBuiltInHelperInvocation = 23,+    SpvBuiltInNumWorkgroups = 24,+    SpvBuiltInWorkgroupSize = 25,+    SpvBuiltInWorkgroupId = 26,+    SpvBuiltInLocalInvocationId = 27,+    SpvBuiltInGlobalInvocationId = 28,+    SpvBuiltInLocalInvocationIndex = 29,+    SpvBuiltInWorkDim = 30,+    SpvBuiltInGlobalSize = 31,+    SpvBuiltInEnqueuedWorkgroupSize = 32,+    SpvBuiltInGlobalOffset = 33,+    SpvBuiltInGlobalLinearId = 34,+    SpvBuiltInSubgroupSize = 36,+    SpvBuiltInSubgroupMaxSize = 37,+    SpvBuiltInNumSubgroups = 38,+    SpvBuiltInNumEnqueuedSubgroups = 39,+    SpvBuiltInSubgroupId = 40,+    SpvBuiltInSubgroupLocalInvocationId = 41,+    SpvBuiltInVertexIndex = 42,+    SpvBuiltInInstanceIndex = 43,+    SpvBuiltInSubgroupEqMask = 4416,+    SpvBuiltInSubgroupEqMaskKHR = 4416,+    SpvBuiltInSubgroupGeMask = 4417,+    SpvBuiltInSubgroupGeMaskKHR = 4417,+    SpvBuiltInSubgroupGtMask = 4418,+    SpvBuiltInSubgroupGtMaskKHR = 4418,+    SpvBuiltInSubgroupLeMask = 4419,+    SpvBuiltInSubgroupLeMaskKHR = 4419,+    SpvBuiltInSubgroupLtMask = 4420,+    SpvBuiltInSubgroupLtMaskKHR = 4420,+    SpvBuiltInBaseVertex = 4424,+    SpvBuiltInBaseInstance = 4425,+    SpvBuiltInDrawIndex = 4426,+    SpvBuiltInPrimitiveShadingRateKHR = 4432,+    SpvBuiltInDeviceIndex = 4438,+    SpvBuiltInViewIndex = 4440,+    SpvBuiltInShadingRateKHR = 4444,+    SpvBuiltInBaryCoordNoPerspAMD = 4992,+    SpvBuiltInBaryCoordNoPerspCentroidAMD = 4993,+    SpvBuiltInBaryCoordNoPerspSampleAMD = 4994,+    SpvBuiltInBaryCoordSmoothAMD = 4995,+    SpvBuiltInBaryCoordSmoothCentroidAMD = 4996,+    SpvBuiltInBaryCoordSmoothSampleAMD = 4997,+    SpvBuiltInBaryCoordPullModelAMD = 4998,+    SpvBuiltInFragStencilRefEXT = 5014,+    SpvBuiltInViewportMaskNV = 5253,+    SpvBuiltInSecondaryPositionNV = 5257,+    SpvBuiltInSecondaryViewportMaskNV = 5258,+    SpvBuiltInPositionPerViewNV = 5261,+    SpvBuiltInViewportMaskPerViewNV = 5262,+    SpvBuiltInFullyCoveredEXT = 5264,+    SpvBuiltInTaskCountNV = 5274,+    SpvBuiltInPrimitiveCountNV = 5275,+    SpvBuiltInPrimitiveIndicesNV = 5276,+    SpvBuiltInClipDistancePerViewNV = 5277,+    SpvBuiltInCullDistancePerViewNV = 5278,+    SpvBuiltInLayerPerViewNV = 5279,+    SpvBuiltInMeshViewCountNV = 5280,+    SpvBuiltInMeshViewIndicesNV = 5281,+    SpvBuiltInBaryCoordKHR = 5286,+    SpvBuiltInBaryCoordNV = 5286,+    SpvBuiltInBaryCoordNoPerspKHR = 5287,+    SpvBuiltInBaryCoordNoPerspNV = 5287,+    SpvBuiltInFragSizeEXT = 5292,+    SpvBuiltInFragmentSizeNV = 5292,+    SpvBuiltInFragInvocationCountEXT = 5293,+    SpvBuiltInInvocationsPerPixelNV = 5293,+    SpvBuiltInLaunchIdKHR = 5319,+    SpvBuiltInLaunchIdNV = 5319,+    SpvBuiltInLaunchSizeKHR = 5320,+    SpvBuiltInLaunchSizeNV = 5320,+    SpvBuiltInWorldRayOriginKHR = 5321,+    SpvBuiltInWorldRayOriginNV = 5321,+    SpvBuiltInWorldRayDirectionKHR = 5322,+    SpvBuiltInWorldRayDirectionNV = 5322,+    SpvBuiltInObjectRayOriginKHR = 5323,+    SpvBuiltInObjectRayOriginNV = 5323,+    SpvBuiltInObjectRayDirectionKHR = 5324,+    SpvBuiltInObjectRayDirectionNV = 5324,+    SpvBuiltInRayTminKHR = 5325,+    SpvBuiltInRayTminNV = 5325,+    SpvBuiltInRayTmaxKHR = 5326,+    SpvBuiltInRayTmaxNV = 5326,+    SpvBuiltInInstanceCustomIndexKHR = 5327,+    SpvBuiltInInstanceCustomIndexNV = 5327,+    SpvBuiltInObjectToWorldKHR = 5330,+    SpvBuiltInObjectToWorldNV = 5330,+    SpvBuiltInWorldToObjectKHR = 5331,+    SpvBuiltInWorldToObjectNV = 5331,+    SpvBuiltInHitTNV = 5332,+    SpvBuiltInHitKindKHR = 5333,+    SpvBuiltInHitKindNV = 5333,+    SpvBuiltInCurrentRayTimeNV = 5334,+    SpvBuiltInIncomingRayFlagsKHR = 5351,+    SpvBuiltInIncomingRayFlagsNV = 5351,+    SpvBuiltInRayGeometryIndexKHR = 5352,+    SpvBuiltInWarpsPerSMNV = 5374,+    SpvBuiltInSMCountNV = 5375,+    SpvBuiltInWarpIDNV = 5376,+    SpvBuiltInSMIDNV = 5377,+    SpvBuiltInCullMaskKHR = 6021,+    SpvBuiltInMax = 0x7fffffff,+} SpvBuiltIn;++typedef enum SpvSelectionControlShift_ {+    SpvSelectionControlFlattenShift = 0,+    SpvSelectionControlDontFlattenShift = 1,+    SpvSelectionControlMax = 0x7fffffff,+} SpvSelectionControlShift;++typedef enum SpvSelectionControlMask_ {+    SpvSelectionControlMaskNone = 0,+    SpvSelectionControlFlattenMask = 0x00000001,+    SpvSelectionControlDontFlattenMask = 0x00000002,+} SpvSelectionControlMask;++typedef enum SpvLoopControlShift_ {+    SpvLoopControlUnrollShift = 0,+    SpvLoopControlDontUnrollShift = 1,+    SpvLoopControlDependencyInfiniteShift = 2,+    SpvLoopControlDependencyLengthShift = 3,+    SpvLoopControlMinIterationsShift = 4,+    SpvLoopControlMaxIterationsShift = 5,+    SpvLoopControlIterationMultipleShift = 6,+    SpvLoopControlPeelCountShift = 7,+    SpvLoopControlPartialCountShift = 8,+    SpvLoopControlInitiationIntervalINTELShift = 16,+    SpvLoopControlMaxConcurrencyINTELShift = 17,+    SpvLoopControlDependencyArrayINTELShift = 18,+    SpvLoopControlPipelineEnableINTELShift = 19,+    SpvLoopControlLoopCoalesceINTELShift = 20,+    SpvLoopControlMaxInterleavingINTELShift = 21,+    SpvLoopControlSpeculatedIterationsINTELShift = 22,+    SpvLoopControlNoFusionINTELShift = 23,+    SpvLoopControlMax = 0x7fffffff,+} SpvLoopControlShift;++typedef enum SpvLoopControlMask_ {+    SpvLoopControlMaskNone = 0,+    SpvLoopControlUnrollMask = 0x00000001,+    SpvLoopControlDontUnrollMask = 0x00000002,+    SpvLoopControlDependencyInfiniteMask = 0x00000004,+    SpvLoopControlDependencyLengthMask = 0x00000008,+    SpvLoopControlMinIterationsMask = 0x00000010,+    SpvLoopControlMaxIterationsMask = 0x00000020,+    SpvLoopControlIterationMultipleMask = 0x00000040,+    SpvLoopControlPeelCountMask = 0x00000080,+    SpvLoopControlPartialCountMask = 0x00000100,+    SpvLoopControlInitiationIntervalINTELMask = 0x00010000,+    SpvLoopControlMaxConcurrencyINTELMask = 0x00020000,+    SpvLoopControlDependencyArrayINTELMask = 0x00040000,+    SpvLoopControlPipelineEnableINTELMask = 0x00080000,+    SpvLoopControlLoopCoalesceINTELMask = 0x00100000,+    SpvLoopControlMaxInterleavingINTELMask = 0x00200000,+    SpvLoopControlSpeculatedIterationsINTELMask = 0x00400000,+    SpvLoopControlNoFusionINTELMask = 0x00800000,+} SpvLoopControlMask;++typedef enum SpvFunctionControlShift_ {+    SpvFunctionControlInlineShift = 0,+    SpvFunctionControlDontInlineShift = 1,+    SpvFunctionControlPureShift = 2,+    SpvFunctionControlConstShift = 3,+    SpvFunctionControlOptNoneINTELShift = 16,+    SpvFunctionControlMax = 0x7fffffff,+} SpvFunctionControlShift;++typedef enum SpvFunctionControlMask_ {+    SpvFunctionControlMaskNone = 0,+    SpvFunctionControlInlineMask = 0x00000001,+    SpvFunctionControlDontInlineMask = 0x00000002,+    SpvFunctionControlPureMask = 0x00000004,+    SpvFunctionControlConstMask = 0x00000008,+    SpvFunctionControlOptNoneINTELMask = 0x00010000,+} SpvFunctionControlMask;++typedef enum SpvMemorySemanticsShift_ {+    SpvMemorySemanticsAcquireShift = 1,+    SpvMemorySemanticsReleaseShift = 2,+    SpvMemorySemanticsAcquireReleaseShift = 3,+    SpvMemorySemanticsSequentiallyConsistentShift = 4,+    SpvMemorySemanticsUniformMemoryShift = 6,+    SpvMemorySemanticsSubgroupMemoryShift = 7,+    SpvMemorySemanticsWorkgroupMemoryShift = 8,+    SpvMemorySemanticsCrossWorkgroupMemoryShift = 9,+    SpvMemorySemanticsAtomicCounterMemoryShift = 10,+    SpvMemorySemanticsImageMemoryShift = 11,+    SpvMemorySemanticsOutputMemoryShift = 12,+    SpvMemorySemanticsOutputMemoryKHRShift = 12,+    SpvMemorySemanticsMakeAvailableShift = 13,+    SpvMemorySemanticsMakeAvailableKHRShift = 13,+    SpvMemorySemanticsMakeVisibleShift = 14,+    SpvMemorySemanticsMakeVisibleKHRShift = 14,+    SpvMemorySemanticsVolatileShift = 15,+    SpvMemorySemanticsMax = 0x7fffffff,+} SpvMemorySemanticsShift;++typedef enum SpvMemorySemanticsMask_ {+    SpvMemorySemanticsMaskNone = 0,+    SpvMemorySemanticsAcquireMask = 0x00000002,+    SpvMemorySemanticsReleaseMask = 0x00000004,+    SpvMemorySemanticsAcquireReleaseMask = 0x00000008,+    SpvMemorySemanticsSequentiallyConsistentMask = 0x00000010,+    SpvMemorySemanticsUniformMemoryMask = 0x00000040,+    SpvMemorySemanticsSubgroupMemoryMask = 0x00000080,+    SpvMemorySemanticsWorkgroupMemoryMask = 0x00000100,+    SpvMemorySemanticsCrossWorkgroupMemoryMask = 0x00000200,+    SpvMemorySemanticsAtomicCounterMemoryMask = 0x00000400,+    SpvMemorySemanticsImageMemoryMask = 0x00000800,+    SpvMemorySemanticsOutputMemoryMask = 0x00001000,+    SpvMemorySemanticsOutputMemoryKHRMask = 0x00001000,+    SpvMemorySemanticsMakeAvailableMask = 0x00002000,+    SpvMemorySemanticsMakeAvailableKHRMask = 0x00002000,+    SpvMemorySemanticsMakeVisibleMask = 0x00004000,+    SpvMemorySemanticsMakeVisibleKHRMask = 0x00004000,+    SpvMemorySemanticsVolatileMask = 0x00008000,+} SpvMemorySemanticsMask;++typedef enum SpvMemoryAccessShift_ {+    SpvMemoryAccessVolatileShift = 0,+    SpvMemoryAccessAlignedShift = 1,+    SpvMemoryAccessNontemporalShift = 2,+    SpvMemoryAccessMakePointerAvailableShift = 3,+    SpvMemoryAccessMakePointerAvailableKHRShift = 3,+    SpvMemoryAccessMakePointerVisibleShift = 4,+    SpvMemoryAccessMakePointerVisibleKHRShift = 4,+    SpvMemoryAccessNonPrivatePointerShift = 5,+    SpvMemoryAccessNonPrivatePointerKHRShift = 5,+    SpvMemoryAccessAliasScopeINTELMaskShift = 16,+    SpvMemoryAccessNoAliasINTELMaskShift = 17,+    SpvMemoryAccessMax = 0x7fffffff,+} SpvMemoryAccessShift;++typedef enum SpvMemoryAccessMask_ {+    SpvMemoryAccessMaskNone = 0,+    SpvMemoryAccessVolatileMask = 0x00000001,+    SpvMemoryAccessAlignedMask = 0x00000002,+    SpvMemoryAccessNontemporalMask = 0x00000004,+    SpvMemoryAccessMakePointerAvailableMask = 0x00000008,+    SpvMemoryAccessMakePointerAvailableKHRMask = 0x00000008,+    SpvMemoryAccessMakePointerVisibleMask = 0x00000010,+    SpvMemoryAccessMakePointerVisibleKHRMask = 0x00000010,+    SpvMemoryAccessNonPrivatePointerMask = 0x00000020,+    SpvMemoryAccessNonPrivatePointerKHRMask = 0x00000020,+    SpvMemoryAccessAliasScopeINTELMaskMask = 0x00010000,+    SpvMemoryAccessNoAliasINTELMaskMask = 0x00020000,+} SpvMemoryAccessMask;++typedef enum SpvScope_ {+    SpvScopeCrossDevice = 0,+    SpvScopeDevice = 1,+    SpvScopeWorkgroup = 2,+    SpvScopeSubgroup = 3,+    SpvScopeInvocation = 4,+    SpvScopeQueueFamily = 5,+    SpvScopeQueueFamilyKHR = 5,+    SpvScopeShaderCallKHR = 6,+    SpvScopeMax = 0x7fffffff,+} SpvScope;++typedef enum SpvGroupOperation_ {+    SpvGroupOperationReduce = 0,+    SpvGroupOperationInclusiveScan = 1,+    SpvGroupOperationExclusiveScan = 2,+    SpvGroupOperationClusteredReduce = 3,+    SpvGroupOperationPartitionedReduceNV = 6,+    SpvGroupOperationPartitionedInclusiveScanNV = 7,+    SpvGroupOperationPartitionedExclusiveScanNV = 8,+    SpvGroupOperationMax = 0x7fffffff,+} SpvGroupOperation;++typedef enum SpvKernelEnqueueFlags_ {+    SpvKernelEnqueueFlagsNoWait = 0,+    SpvKernelEnqueueFlagsWaitKernel = 1,+    SpvKernelEnqueueFlagsWaitWorkGroup = 2,+    SpvKernelEnqueueFlagsMax = 0x7fffffff,+} SpvKernelEnqueueFlags;++typedef enum SpvKernelProfilingInfoShift_ {+    SpvKernelProfilingInfoCmdExecTimeShift = 0,+    SpvKernelProfilingInfoMax = 0x7fffffff,+} SpvKernelProfilingInfoShift;++typedef enum SpvKernelProfilingInfoMask_ {+    SpvKernelProfilingInfoMaskNone = 0,+    SpvKernelProfilingInfoCmdExecTimeMask = 0x00000001,+} SpvKernelProfilingInfoMask;++typedef enum SpvCapability_ {+    SpvCapabilityMatrix = 0,+    SpvCapabilityShader = 1,+    SpvCapabilityGeometry = 2,+    SpvCapabilityTessellation = 3,+    SpvCapabilityAddresses = 4,+    SpvCapabilityLinkage = 5,+    SpvCapabilityKernel = 6,+    SpvCapabilityVector16 = 7,+    SpvCapabilityFloat16Buffer = 8,+    SpvCapabilityFloat16 = 9,+    SpvCapabilityFloat64 = 10,+    SpvCapabilityInt64 = 11,+    SpvCapabilityInt64Atomics = 12,+    SpvCapabilityImageBasic = 13,+    SpvCapabilityImageReadWrite = 14,+    SpvCapabilityImageMipmap = 15,+    SpvCapabilityPipes = 17,+    SpvCapabilityGroups = 18,+    SpvCapabilityDeviceEnqueue = 19,+    SpvCapabilityLiteralSampler = 20,+    SpvCapabilityAtomicStorage = 21,+    SpvCapabilityInt16 = 22,+    SpvCapabilityTessellationPointSize = 23,+    SpvCapabilityGeometryPointSize = 24,+    SpvCapabilityImageGatherExtended = 25,+    SpvCapabilityStorageImageMultisample = 27,+    SpvCapabilityUniformBufferArrayDynamicIndexing = 28,+    SpvCapabilitySampledImageArrayDynamicIndexing = 29,+    SpvCapabilityStorageBufferArrayDynamicIndexing = 30,+    SpvCapabilityStorageImageArrayDynamicIndexing = 31,+    SpvCapabilityClipDistance = 32,+    SpvCapabilityCullDistance = 33,+    SpvCapabilityImageCubeArray = 34,+    SpvCapabilitySampleRateShading = 35,+    SpvCapabilityImageRect = 36,+    SpvCapabilitySampledRect = 37,+    SpvCapabilityGenericPointer = 38,+    SpvCapabilityInt8 = 39,+    SpvCapabilityInputAttachment = 40,+    SpvCapabilitySparseResidency = 41,+    SpvCapabilityMinLod = 42,+    SpvCapabilitySampled1D = 43,+    SpvCapabilityImage1D = 44,+    SpvCapabilitySampledCubeArray = 45,+    SpvCapabilitySampledBuffer = 46,+    SpvCapabilityImageBuffer = 47,+    SpvCapabilityImageMSArray = 48,+    SpvCapabilityStorageImageExtendedFormats = 49,+    SpvCapabilityImageQuery = 50,+    SpvCapabilityDerivativeControl = 51,+    SpvCapabilityInterpolationFunction = 52,+    SpvCapabilityTransformFeedback = 53,+    SpvCapabilityGeometryStreams = 54,+    SpvCapabilityStorageImageReadWithoutFormat = 55,+    SpvCapabilityStorageImageWriteWithoutFormat = 56,+    SpvCapabilityMultiViewport = 57,+    SpvCapabilitySubgroupDispatch = 58,+    SpvCapabilityNamedBarrier = 59,+    SpvCapabilityPipeStorage = 60,+    SpvCapabilityGroupNonUniform = 61,+    SpvCapabilityGroupNonUniformVote = 62,+    SpvCapabilityGroupNonUniformArithmetic = 63,+    SpvCapabilityGroupNonUniformBallot = 64,+    SpvCapabilityGroupNonUniformShuffle = 65,+    SpvCapabilityGroupNonUniformShuffleRelative = 66,+    SpvCapabilityGroupNonUniformClustered = 67,+    SpvCapabilityGroupNonUniformQuad = 68,+    SpvCapabilityShaderLayer = 69,+    SpvCapabilityShaderViewportIndex = 70,+    SpvCapabilityUniformDecoration = 71,+    SpvCapabilityFragmentShadingRateKHR = 4422,+    SpvCapabilitySubgroupBallotKHR = 4423,+    SpvCapabilityDrawParameters = 4427,+    SpvCapabilityWorkgroupMemoryExplicitLayoutKHR = 4428,+    SpvCapabilityWorkgroupMemoryExplicitLayout8BitAccessKHR = 4429,+    SpvCapabilityWorkgroupMemoryExplicitLayout16BitAccessKHR = 4430,+    SpvCapabilitySubgroupVoteKHR = 4431,+    SpvCapabilityStorageBuffer16BitAccess = 4433,+    SpvCapabilityStorageUniformBufferBlock16 = 4433,+    SpvCapabilityStorageUniform16 = 4434,+    SpvCapabilityUniformAndStorageBuffer16BitAccess = 4434,+    SpvCapabilityStoragePushConstant16 = 4435,+    SpvCapabilityStorageInputOutput16 = 4436,+    SpvCapabilityDeviceGroup = 4437,+    SpvCapabilityMultiView = 4439,+    SpvCapabilityVariablePointersStorageBuffer = 4441,+    SpvCapabilityVariablePointers = 4442,+    SpvCapabilityAtomicStorageOps = 4445,+    SpvCapabilitySampleMaskPostDepthCoverage = 4447,+    SpvCapabilityStorageBuffer8BitAccess = 4448,+    SpvCapabilityUniformAndStorageBuffer8BitAccess = 4449,+    SpvCapabilityStoragePushConstant8 = 4450,+    SpvCapabilityDenormPreserve = 4464,+    SpvCapabilityDenormFlushToZero = 4465,+    SpvCapabilitySignedZeroInfNanPreserve = 4466,+    SpvCapabilityRoundingModeRTE = 4467,+    SpvCapabilityRoundingModeRTZ = 4468,+    SpvCapabilityRayQueryProvisionalKHR = 4471,+    SpvCapabilityRayQueryKHR = 4472,+    SpvCapabilityRayTraversalPrimitiveCullingKHR = 4478,+    SpvCapabilityRayTracingKHR = 4479,+    SpvCapabilityFloat16ImageAMD = 5008,+    SpvCapabilityImageGatherBiasLodAMD = 5009,+    SpvCapabilityFragmentMaskAMD = 5010,+    SpvCapabilityStencilExportEXT = 5013,+    SpvCapabilityImageReadWriteLodAMD = 5015,+    SpvCapabilityInt64ImageEXT = 5016,+    SpvCapabilityShaderClockKHR = 5055,+    SpvCapabilitySampleMaskOverrideCoverageNV = 5249,+    SpvCapabilityGeometryShaderPassthroughNV = 5251,+    SpvCapabilityShaderViewportIndexLayerEXT = 5254,+    SpvCapabilityShaderViewportIndexLayerNV = 5254,+    SpvCapabilityShaderViewportMaskNV = 5255,+    SpvCapabilityShaderStereoViewNV = 5259,+    SpvCapabilityPerViewAttributesNV = 5260,+    SpvCapabilityFragmentFullyCoveredEXT = 5265,+    SpvCapabilityMeshShadingNV = 5266,+    SpvCapabilityImageFootprintNV = 5282,+    SpvCapabilityFragmentBarycentricKHR = 5284,+    SpvCapabilityFragmentBarycentricNV = 5284,+    SpvCapabilityComputeDerivativeGroupQuadsNV = 5288,+    SpvCapabilityFragmentDensityEXT = 5291,+    SpvCapabilityShadingRateNV = 5291,+    SpvCapabilityGroupNonUniformPartitionedNV = 5297,+    SpvCapabilityShaderNonUniform = 5301,+    SpvCapabilityShaderNonUniformEXT = 5301,+    SpvCapabilityRuntimeDescriptorArray = 5302,+    SpvCapabilityRuntimeDescriptorArrayEXT = 5302,+    SpvCapabilityInputAttachmentArrayDynamicIndexing = 5303,+    SpvCapabilityInputAttachmentArrayDynamicIndexingEXT = 5303,+    SpvCapabilityUniformTexelBufferArrayDynamicIndexing = 5304,+    SpvCapabilityUniformTexelBufferArrayDynamicIndexingEXT = 5304,+    SpvCapabilityStorageTexelBufferArrayDynamicIndexing = 5305,+    SpvCapabilityStorageTexelBufferArrayDynamicIndexingEXT = 5305,+    SpvCapabilityUniformBufferArrayNonUniformIndexing = 5306,+    SpvCapabilityUniformBufferArrayNonUniformIndexingEXT = 5306,+    SpvCapabilitySampledImageArrayNonUniformIndexing = 5307,+    SpvCapabilitySampledImageArrayNonUniformIndexingEXT = 5307,+    SpvCapabilityStorageBufferArrayNonUniformIndexing = 5308,+    SpvCapabilityStorageBufferArrayNonUniformIndexingEXT = 5308,+    SpvCapabilityStorageImageArrayNonUniformIndexing = 5309,+    SpvCapabilityStorageImageArrayNonUniformIndexingEXT = 5309,+    SpvCapabilityInputAttachmentArrayNonUniformIndexing = 5310,+    SpvCapabilityInputAttachmentArrayNonUniformIndexingEXT = 5310,+    SpvCapabilityUniformTexelBufferArrayNonUniformIndexing = 5311,+    SpvCapabilityUniformTexelBufferArrayNonUniformIndexingEXT = 5311,+    SpvCapabilityStorageTexelBufferArrayNonUniformIndexing = 5312,+    SpvCapabilityStorageTexelBufferArrayNonUniformIndexingEXT = 5312,+    SpvCapabilityRayTracingNV = 5340,+    SpvCapabilityRayTracingMotionBlurNV = 5341,+    SpvCapabilityVulkanMemoryModel = 5345,+    SpvCapabilityVulkanMemoryModelKHR = 5345,+    SpvCapabilityVulkanMemoryModelDeviceScope = 5346,+    SpvCapabilityVulkanMemoryModelDeviceScopeKHR = 5346,+    SpvCapabilityPhysicalStorageBufferAddresses = 5347,+    SpvCapabilityPhysicalStorageBufferAddressesEXT = 5347,+    SpvCapabilityComputeDerivativeGroupLinearNV = 5350,+    SpvCapabilityRayTracingProvisionalKHR = 5353,+    SpvCapabilityCooperativeMatrixNV = 5357,+    SpvCapabilityFragmentShaderSampleInterlockEXT = 5363,+    SpvCapabilityFragmentShaderShadingRateInterlockEXT = 5372,+    SpvCapabilityShaderSMBuiltinsNV = 5373,+    SpvCapabilityFragmentShaderPixelInterlockEXT = 5378,+    SpvCapabilityDemoteToHelperInvocation = 5379,+    SpvCapabilityDemoteToHelperInvocationEXT = 5379,+    SpvCapabilityBindlessTextureNV = 5390,+    SpvCapabilitySubgroupShuffleINTEL = 5568,+    SpvCapabilitySubgroupBufferBlockIOINTEL = 5569,+    SpvCapabilitySubgroupImageBlockIOINTEL = 5570,+    SpvCapabilitySubgroupImageMediaBlockIOINTEL = 5579,+    SpvCapabilityRoundToInfinityINTEL = 5582,+    SpvCapabilityFloatingPointModeINTEL = 5583,+    SpvCapabilityIntegerFunctions2INTEL = 5584,+    SpvCapabilityFunctionPointersINTEL = 5603,+    SpvCapabilityIndirectReferencesINTEL = 5604,+    SpvCapabilityAsmINTEL = 5606,+    SpvCapabilityAtomicFloat32MinMaxEXT = 5612,+    SpvCapabilityAtomicFloat64MinMaxEXT = 5613,+    SpvCapabilityAtomicFloat16MinMaxEXT = 5616,+    SpvCapabilityVectorComputeINTEL = 5617,+    SpvCapabilityVectorAnyINTEL = 5619,+    SpvCapabilityExpectAssumeKHR = 5629,+    SpvCapabilitySubgroupAvcMotionEstimationINTEL = 5696,+    SpvCapabilitySubgroupAvcMotionEstimationIntraINTEL = 5697,+    SpvCapabilitySubgroupAvcMotionEstimationChromaINTEL = 5698,+    SpvCapabilityVariableLengthArrayINTEL = 5817,+    SpvCapabilityFunctionFloatControlINTEL = 5821,+    SpvCapabilityFPGAMemoryAttributesINTEL = 5824,+    SpvCapabilityFPFastMathModeINTEL = 5837,+    SpvCapabilityArbitraryPrecisionIntegersINTEL = 5844,+    SpvCapabilityArbitraryPrecisionFloatingPointINTEL = 5845,+    SpvCapabilityUnstructuredLoopControlsINTEL = 5886,+    SpvCapabilityFPGALoopControlsINTEL = 5888,+    SpvCapabilityKernelAttributesINTEL = 5892,+    SpvCapabilityFPGAKernelAttributesINTEL = 5897,+    SpvCapabilityFPGAMemoryAccessesINTEL = 5898,+    SpvCapabilityFPGAClusterAttributesINTEL = 5904,+    SpvCapabilityLoopFuseINTEL = 5906,+    SpvCapabilityMemoryAccessAliasingINTEL = 5910,+    SpvCapabilityFPGABufferLocationINTEL = 5920,+    SpvCapabilityArbitraryPrecisionFixedPointINTEL = 5922,+    SpvCapabilityUSMStorageClassesINTEL = 5935,+    SpvCapabilityIOPipesINTEL = 5943,+    SpvCapabilityBlockingPipesINTEL = 5945,+    SpvCapabilityFPGARegINTEL = 5948,+    SpvCapabilityDotProductInputAll = 6016,+    SpvCapabilityDotProductInputAllKHR = 6016,+    SpvCapabilityDotProductInput4x8Bit = 6017,+    SpvCapabilityDotProductInput4x8BitKHR = 6017,+    SpvCapabilityDotProductInput4x8BitPacked = 6018,+    SpvCapabilityDotProductInput4x8BitPackedKHR = 6018,+    SpvCapabilityDotProduct = 6019,+    SpvCapabilityDotProductKHR = 6019,+    SpvCapabilityRayCullMaskKHR = 6020,+    SpvCapabilityBitInstructions = 6025,+    SpvCapabilityGroupNonUniformRotateKHR = 6026,+    SpvCapabilityAtomicFloat32AddEXT = 6033,+    SpvCapabilityAtomicFloat64AddEXT = 6034,+    SpvCapabilityLongConstantCompositeINTEL = 6089,+    SpvCapabilityOptNoneINTEL = 6094,+    SpvCapabilityAtomicFloat16AddEXT = 6095,+    SpvCapabilityDebugInfoModuleINTEL = 6114,+    SpvCapabilitySplitBarrierINTEL = 6141,+    SpvCapabilityGroupUniformArithmeticKHR = 6400,+    SpvCapabilityMax = 0x7fffffff,+} SpvCapability;++typedef enum SpvRayFlagsShift_ {+    SpvRayFlagsOpaqueKHRShift = 0,+    SpvRayFlagsNoOpaqueKHRShift = 1,+    SpvRayFlagsTerminateOnFirstHitKHRShift = 2,+    SpvRayFlagsSkipClosestHitShaderKHRShift = 3,+    SpvRayFlagsCullBackFacingTrianglesKHRShift = 4,+    SpvRayFlagsCullFrontFacingTrianglesKHRShift = 5,+    SpvRayFlagsCullOpaqueKHRShift = 6,+    SpvRayFlagsCullNoOpaqueKHRShift = 7,+    SpvRayFlagsSkipTrianglesKHRShift = 8,+    SpvRayFlagsSkipAABBsKHRShift = 9,+    SpvRayFlagsMax = 0x7fffffff,+} SpvRayFlagsShift;++typedef enum SpvRayFlagsMask_ {+    SpvRayFlagsMaskNone = 0,+    SpvRayFlagsOpaqueKHRMask = 0x00000001,+    SpvRayFlagsNoOpaqueKHRMask = 0x00000002,+    SpvRayFlagsTerminateOnFirstHitKHRMask = 0x00000004,+    SpvRayFlagsSkipClosestHitShaderKHRMask = 0x00000008,+    SpvRayFlagsCullBackFacingTrianglesKHRMask = 0x00000010,+    SpvRayFlagsCullFrontFacingTrianglesKHRMask = 0x00000020,+    SpvRayFlagsCullOpaqueKHRMask = 0x00000040,+    SpvRayFlagsCullNoOpaqueKHRMask = 0x00000080,+    SpvRayFlagsSkipTrianglesKHRMask = 0x00000100,+    SpvRayFlagsSkipAABBsKHRMask = 0x00000200,+} SpvRayFlagsMask;++typedef enum SpvRayQueryIntersection_ {+    SpvRayQueryIntersectionRayQueryCandidateIntersectionKHR = 0,+    SpvRayQueryIntersectionRayQueryCommittedIntersectionKHR = 1,+    SpvRayQueryIntersectionMax = 0x7fffffff,+} SpvRayQueryIntersection;++typedef enum SpvRayQueryCommittedIntersectionType_ {+    SpvRayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionNoneKHR = 0,+    SpvRayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionTriangleKHR = 1,+    SpvRayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionGeneratedKHR = 2,+    SpvRayQueryCommittedIntersectionTypeMax = 0x7fffffff,+} SpvRayQueryCommittedIntersectionType;++typedef enum SpvRayQueryCandidateIntersectionType_ {+    SpvRayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionTriangleKHR = 0,+    SpvRayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionAABBKHR = 1,+    SpvRayQueryCandidateIntersectionTypeMax = 0x7fffffff,+} SpvRayQueryCandidateIntersectionType;++typedef enum SpvFragmentShadingRateShift_ {+    SpvFragmentShadingRateVertical2PixelsShift = 0,+    SpvFragmentShadingRateVertical4PixelsShift = 1,+    SpvFragmentShadingRateHorizontal2PixelsShift = 2,+    SpvFragmentShadingRateHorizontal4PixelsShift = 3,+    SpvFragmentShadingRateMax = 0x7fffffff,+} SpvFragmentShadingRateShift;++typedef enum SpvFragmentShadingRateMask_ {+    SpvFragmentShadingRateMaskNone = 0,+    SpvFragmentShadingRateVertical2PixelsMask = 0x00000001,+    SpvFragmentShadingRateVertical4PixelsMask = 0x00000002,+    SpvFragmentShadingRateHorizontal2PixelsMask = 0x00000004,+    SpvFragmentShadingRateHorizontal4PixelsMask = 0x00000008,+} SpvFragmentShadingRateMask;++typedef enum SpvFPDenormMode_ {+    SpvFPDenormModePreserve = 0,+    SpvFPDenormModeFlushToZero = 1,+    SpvFPDenormModeMax = 0x7fffffff,+} SpvFPDenormMode;++typedef enum SpvFPOperationMode_ {+    SpvFPOperationModeIEEE = 0,+    SpvFPOperationModeALT = 1,+    SpvFPOperationModeMax = 0x7fffffff,+} SpvFPOperationMode;++typedef enum SpvQuantizationModes_ {+    SpvQuantizationModesTRN = 0,+    SpvQuantizationModesTRN_ZERO = 1,+    SpvQuantizationModesRND = 2,+    SpvQuantizationModesRND_ZERO = 3,+    SpvQuantizationModesRND_INF = 4,+    SpvQuantizationModesRND_MIN_INF = 5,+    SpvQuantizationModesRND_CONV = 6,+    SpvQuantizationModesRND_CONV_ODD = 7,+    SpvQuantizationModesMax = 0x7fffffff,+} SpvQuantizationModes;++typedef enum SpvOverflowModes_ {+    SpvOverflowModesWRAP = 0,+    SpvOverflowModesSAT = 1,+    SpvOverflowModesSAT_ZERO = 2,+    SpvOverflowModesSAT_SYM = 3,+    SpvOverflowModesMax = 0x7fffffff,+} SpvOverflowModes;++typedef enum SpvPackedVectorFormat_ {+    SpvPackedVectorFormatPackedVectorFormat4x8Bit = 0,+    SpvPackedVectorFormatPackedVectorFormat4x8BitKHR = 0,+    SpvPackedVectorFormatMax = 0x7fffffff,+} SpvPackedVectorFormat;++typedef enum SpvOp_ {+    SpvOpNop = 0,+    SpvOpUndef = 1,+    SpvOpSourceContinued = 2,+    SpvOpSource = 3,+    SpvOpSourceExtension = 4,+    SpvOpName = 5,+    SpvOpMemberName = 6,+    SpvOpString = 7,+    SpvOpLine = 8,+    SpvOpExtension = 10,+    SpvOpExtInstImport = 11,+    SpvOpExtInst = 12,+    SpvOpMemoryModel = 14,+    SpvOpEntryPoint = 15,+    SpvOpExecutionMode = 16,+    SpvOpCapability = 17,+    SpvOpTypeVoid = 19,+    SpvOpTypeBool = 20,+    SpvOpTypeInt = 21,+    SpvOpTypeFloat = 22,+    SpvOpTypeVector = 23,+    SpvOpTypeMatrix = 24,+    SpvOpTypeImage = 25,+    SpvOpTypeSampler = 26,+    SpvOpTypeSampledImage = 27,+    SpvOpTypeArray = 28,+    SpvOpTypeRuntimeArray = 29,+    SpvOpTypeStruct = 30,+    SpvOpTypeOpaque = 31,+    SpvOpTypePointer = 32,+    SpvOpTypeFunction = 33,+    SpvOpTypeEvent = 34,+    SpvOpTypeDeviceEvent = 35,+    SpvOpTypeReserveId = 36,+    SpvOpTypeQueue = 37,+    SpvOpTypePipe = 38,+    SpvOpTypeForwardPointer = 39,+    SpvOpConstantTrue = 41,+    SpvOpConstantFalse = 42,+    SpvOpConstant = 43,+    SpvOpConstantComposite = 44,+    SpvOpConstantSampler = 45,+    SpvOpConstantNull = 46,+    SpvOpSpecConstantTrue = 48,+    SpvOpSpecConstantFalse = 49,+    SpvOpSpecConstant = 50,+    SpvOpSpecConstantComposite = 51,+    SpvOpSpecConstantOp = 52,+    SpvOpFunction = 54,+    SpvOpFunctionParameter = 55,+    SpvOpFunctionEnd = 56,+    SpvOpFunctionCall = 57,+    SpvOpVariable = 59,+    SpvOpImageTexelPointer = 60,+    SpvOpLoad = 61,+    SpvOpStore = 62,+    SpvOpCopyMemory = 63,+    SpvOpCopyMemorySized = 64,+    SpvOpAccessChain = 65,+    SpvOpInBoundsAccessChain = 66,+    SpvOpPtrAccessChain = 67,+    SpvOpArrayLength = 68,+    SpvOpGenericPtrMemSemantics = 69,+    SpvOpInBoundsPtrAccessChain = 70,+    SpvOpDecorate = 71,+    SpvOpMemberDecorate = 72,+    SpvOpDecorationGroup = 73,+    SpvOpGroupDecorate = 74,+    SpvOpGroupMemberDecorate = 75,+    SpvOpVectorExtractDynamic = 77,+    SpvOpVectorInsertDynamic = 78,+    SpvOpVectorShuffle = 79,+    SpvOpCompositeConstruct = 80,+    SpvOpCompositeExtract = 81,+    SpvOpCompositeInsert = 82,+    SpvOpCopyObject = 83,+    SpvOpTranspose = 84,+    SpvOpSampledImage = 86,+    SpvOpImageSampleImplicitLod = 87,+    SpvOpImageSampleExplicitLod = 88,+    SpvOpImageSampleDrefImplicitLod = 89,+    SpvOpImageSampleDrefExplicitLod = 90,+    SpvOpImageSampleProjImplicitLod = 91,+    SpvOpImageSampleProjExplicitLod = 92,+    SpvOpImageSampleProjDrefImplicitLod = 93,+    SpvOpImageSampleProjDrefExplicitLod = 94,+    SpvOpImageFetch = 95,+    SpvOpImageGather = 96,+    SpvOpImageDrefGather = 97,+    SpvOpImageRead = 98,+    SpvOpImageWrite = 99,+    SpvOpImage = 100,+    SpvOpImageQueryFormat = 101,+    SpvOpImageQueryOrder = 102,+    SpvOpImageQuerySizeLod = 103,+    SpvOpImageQuerySize = 104,+    SpvOpImageQueryLod = 105,+    SpvOpImageQueryLevels = 106,+    SpvOpImageQuerySamples = 107,+    SpvOpConvertFToU = 109,+    SpvOpConvertFToS = 110,+    SpvOpConvertSToF = 111,+    SpvOpConvertUToF = 112,+    SpvOpUConvert = 113,+    SpvOpSConvert = 114,+    SpvOpFConvert = 115,+    SpvOpQuantizeToF16 = 116,+    SpvOpConvertPtrToU = 117,+    SpvOpSatConvertSToU = 118,+    SpvOpSatConvertUToS = 119,+    SpvOpConvertUToPtr = 120,+    SpvOpPtrCastToGeneric = 121,+    SpvOpGenericCastToPtr = 122,+    SpvOpGenericCastToPtrExplicit = 123,+    SpvOpBitcast = 124,+    SpvOpSNegate = 126,+    SpvOpFNegate = 127,+    SpvOpIAdd = 128,+    SpvOpFAdd = 129,+    SpvOpISub = 130,+    SpvOpFSub = 131,+    SpvOpIMul = 132,+    SpvOpFMul = 133,+    SpvOpUDiv = 134,+    SpvOpSDiv = 135,+    SpvOpFDiv = 136,+    SpvOpUMod = 137,+    SpvOpSRem = 138,+    SpvOpSMod = 139,+    SpvOpFRem = 140,+    SpvOpFMod = 141,+    SpvOpVectorTimesScalar = 142,+    SpvOpMatrixTimesScalar = 143,+    SpvOpVectorTimesMatrix = 144,+    SpvOpMatrixTimesVector = 145,+    SpvOpMatrixTimesMatrix = 146,+    SpvOpOuterProduct = 147,+    SpvOpDot = 148,+    SpvOpIAddCarry = 149,+    SpvOpISubBorrow = 150,+    SpvOpUMulExtended = 151,+    SpvOpSMulExtended = 152,+    SpvOpAny = 154,+    SpvOpAll = 155,+    SpvOpIsNan = 156,+    SpvOpIsInf = 157,+    SpvOpIsFinite = 158,+    SpvOpIsNormal = 159,+    SpvOpSignBitSet = 160,+    SpvOpLessOrGreater = 161,+    SpvOpOrdered = 162,+    SpvOpUnordered = 163,+    SpvOpLogicalEqual = 164,+    SpvOpLogicalNotEqual = 165,+    SpvOpLogicalOr = 166,+    SpvOpLogicalAnd = 167,+    SpvOpLogicalNot = 168,+    SpvOpSelect = 169,+    SpvOpIEqual = 170,+    SpvOpINotEqual = 171,+    SpvOpUGreaterThan = 172,+    SpvOpSGreaterThan = 173,+    SpvOpUGreaterThanEqual = 174,+    SpvOpSGreaterThanEqual = 175,+    SpvOpULessThan = 176,+    SpvOpSLessThan = 177,+    SpvOpULessThanEqual = 178,+    SpvOpSLessThanEqual = 179,+    SpvOpFOrdEqual = 180,+    SpvOpFUnordEqual = 181,+    SpvOpFOrdNotEqual = 182,+    SpvOpFUnordNotEqual = 183,+    SpvOpFOrdLessThan = 184,+    SpvOpFUnordLessThan = 185,+    SpvOpFOrdGreaterThan = 186,+    SpvOpFUnordGreaterThan = 187,+    SpvOpFOrdLessThanEqual = 188,+    SpvOpFUnordLessThanEqual = 189,+    SpvOpFOrdGreaterThanEqual = 190,+    SpvOpFUnordGreaterThanEqual = 191,+    SpvOpShiftRightLogical = 194,+    SpvOpShiftRightArithmetic = 195,+    SpvOpShiftLeftLogical = 196,+    SpvOpBitwiseOr = 197,+    SpvOpBitwiseXor = 198,+    SpvOpBitwiseAnd = 199,+    SpvOpNot = 200,+    SpvOpBitFieldInsert = 201,+    SpvOpBitFieldSExtract = 202,+    SpvOpBitFieldUExtract = 203,+    SpvOpBitReverse = 204,+    SpvOpBitCount = 205,+    SpvOpDPdx = 207,+    SpvOpDPdy = 208,+    SpvOpFwidth = 209,+    SpvOpDPdxFine = 210,+    SpvOpDPdyFine = 211,+    SpvOpFwidthFine = 212,+    SpvOpDPdxCoarse = 213,+    SpvOpDPdyCoarse = 214,+    SpvOpFwidthCoarse = 215,+    SpvOpEmitVertex = 218,+    SpvOpEndPrimitive = 219,+    SpvOpEmitStreamVertex = 220,+    SpvOpEndStreamPrimitive = 221,+    SpvOpControlBarrier = 224,+    SpvOpMemoryBarrier = 225,+    SpvOpAtomicLoad = 227,+    SpvOpAtomicStore = 228,+    SpvOpAtomicExchange = 229,+    SpvOpAtomicCompareExchange = 230,+    SpvOpAtomicCompareExchangeWeak = 231,+    SpvOpAtomicIIncrement = 232,+    SpvOpAtomicIDecrement = 233,+    SpvOpAtomicIAdd = 234,+    SpvOpAtomicISub = 235,+    SpvOpAtomicSMin = 236,+    SpvOpAtomicUMin = 237,+    SpvOpAtomicSMax = 238,+    SpvOpAtomicUMax = 239,+    SpvOpAtomicAnd = 240,+    SpvOpAtomicOr = 241,+    SpvOpAtomicXor = 242,+    SpvOpPhi = 245,+    SpvOpLoopMerge = 246,+    SpvOpSelectionMerge = 247,+    SpvOpLabel = 248,+    SpvOpBranch = 249,+    SpvOpBranchConditional = 250,+    SpvOpSwitch = 251,+    SpvOpKill = 252,+    SpvOpReturn = 253,+    SpvOpReturnValue = 254,+    SpvOpUnreachable = 255,+    SpvOpLifetimeStart = 256,+    SpvOpLifetimeStop = 257,+    SpvOpGroupAsyncCopy = 259,+    SpvOpGroupWaitEvents = 260,+    SpvOpGroupAll = 261,+    SpvOpGroupAny = 262,+    SpvOpGroupBroadcast = 263,+    SpvOpGroupIAdd = 264,+    SpvOpGroupFAdd = 265,+    SpvOpGroupFMin = 266,+    SpvOpGroupUMin = 267,+    SpvOpGroupSMin = 268,+    SpvOpGroupFMax = 269,+    SpvOpGroupUMax = 270,+    SpvOpGroupSMax = 271,+    SpvOpReadPipe = 274,+    SpvOpWritePipe = 275,+    SpvOpReservedReadPipe = 276,+    SpvOpReservedWritePipe = 277,+    SpvOpReserveReadPipePackets = 278,+    SpvOpReserveWritePipePackets = 279,+    SpvOpCommitReadPipe = 280,+    SpvOpCommitWritePipe = 281,+    SpvOpIsValidReserveId = 282,+    SpvOpGetNumPipePackets = 283,+    SpvOpGetMaxPipePackets = 284,+    SpvOpGroupReserveReadPipePackets = 285,+    SpvOpGroupReserveWritePipePackets = 286,+    SpvOpGroupCommitReadPipe = 287,+    SpvOpGroupCommitWritePipe = 288,+    SpvOpEnqueueMarker = 291,+    SpvOpEnqueueKernel = 292,+    SpvOpGetKernelNDrangeSubGroupCount = 293,+    SpvOpGetKernelNDrangeMaxSubGroupSize = 294,+    SpvOpGetKernelWorkGroupSize = 295,+    SpvOpGetKernelPreferredWorkGroupSizeMultiple = 296,+    SpvOpRetainEvent = 297,+    SpvOpReleaseEvent = 298,+    SpvOpCreateUserEvent = 299,+    SpvOpIsValidEvent = 300,+    SpvOpSetUserEventStatus = 301,+    SpvOpCaptureEventProfilingInfo = 302,+    SpvOpGetDefaultQueue = 303,+    SpvOpBuildNDRange = 304,+    SpvOpImageSparseSampleImplicitLod = 305,+    SpvOpImageSparseSampleExplicitLod = 306,+    SpvOpImageSparseSampleDrefImplicitLod = 307,+    SpvOpImageSparseSampleDrefExplicitLod = 308,+    SpvOpImageSparseSampleProjImplicitLod = 309,+    SpvOpImageSparseSampleProjExplicitLod = 310,+    SpvOpImageSparseSampleProjDrefImplicitLod = 311,+    SpvOpImageSparseSampleProjDrefExplicitLod = 312,+    SpvOpImageSparseFetch = 313,+    SpvOpImageSparseGather = 314,+    SpvOpImageSparseDrefGather = 315,+    SpvOpImageSparseTexelsResident = 316,+    SpvOpNoLine = 317,+    SpvOpAtomicFlagTestAndSet = 318,+    SpvOpAtomicFlagClear = 319,+    SpvOpImageSparseRead = 320,+    SpvOpSizeOf = 321,+    SpvOpTypePipeStorage = 322,+    SpvOpConstantPipeStorage = 323,+    SpvOpCreatePipeFromPipeStorage = 324,+    SpvOpGetKernelLocalSizeForSubgroupCount = 325,+    SpvOpGetKernelMaxNumSubgroups = 326,+    SpvOpTypeNamedBarrier = 327,+    SpvOpNamedBarrierInitialize = 328,+    SpvOpMemoryNamedBarrier = 329,+    SpvOpModuleProcessed = 330,+    SpvOpExecutionModeId = 331,+    SpvOpDecorateId = 332,+    SpvOpGroupNonUniformElect = 333,+    SpvOpGroupNonUniformAll = 334,+    SpvOpGroupNonUniformAny = 335,+    SpvOpGroupNonUniformAllEqual = 336,+    SpvOpGroupNonUniformBroadcast = 337,+    SpvOpGroupNonUniformBroadcastFirst = 338,+    SpvOpGroupNonUniformBallot = 339,+    SpvOpGroupNonUniformInverseBallot = 340,+    SpvOpGroupNonUniformBallotBitExtract = 341,+    SpvOpGroupNonUniformBallotBitCount = 342,+    SpvOpGroupNonUniformBallotFindLSB = 343,+    SpvOpGroupNonUniformBallotFindMSB = 344,+    SpvOpGroupNonUniformShuffle = 345,+    SpvOpGroupNonUniformShuffleXor = 346,+    SpvOpGroupNonUniformShuffleUp = 347,+    SpvOpGroupNonUniformShuffleDown = 348,+    SpvOpGroupNonUniformIAdd = 349,+    SpvOpGroupNonUniformFAdd = 350,+    SpvOpGroupNonUniformIMul = 351,+    SpvOpGroupNonUniformFMul = 352,+    SpvOpGroupNonUniformSMin = 353,+    SpvOpGroupNonUniformUMin = 354,+    SpvOpGroupNonUniformFMin = 355,+    SpvOpGroupNonUniformSMax = 356,+    SpvOpGroupNonUniformUMax = 357,+    SpvOpGroupNonUniformFMax = 358,+    SpvOpGroupNonUniformBitwiseAnd = 359,+    SpvOpGroupNonUniformBitwiseOr = 360,+    SpvOpGroupNonUniformBitwiseXor = 361,+    SpvOpGroupNonUniformLogicalAnd = 362,+    SpvOpGroupNonUniformLogicalOr = 363,+    SpvOpGroupNonUniformLogicalXor = 364,+    SpvOpGroupNonUniformQuadBroadcast = 365,+    SpvOpGroupNonUniformQuadSwap = 366,+    SpvOpCopyLogical = 400,+    SpvOpPtrEqual = 401,+    SpvOpPtrNotEqual = 402,+    SpvOpPtrDiff = 403,+    SpvOpTerminateInvocation = 4416,+    SpvOpSubgroupBallotKHR = 4421,+    SpvOpSubgroupFirstInvocationKHR = 4422,+    SpvOpSubgroupAllKHR = 4428,+    SpvOpSubgroupAnyKHR = 4429,+    SpvOpSubgroupAllEqualKHR = 4430,+    SpvOpGroupNonUniformRotateKHR = 4431,+    SpvOpSubgroupReadInvocationKHR = 4432,+    SpvOpTraceRayKHR = 4445,+    SpvOpExecuteCallableKHR = 4446,+    SpvOpConvertUToAccelerationStructureKHR = 4447,+    SpvOpIgnoreIntersectionKHR = 4448,+    SpvOpTerminateRayKHR = 4449,+    SpvOpSDot = 4450,+    SpvOpSDotKHR = 4450,+    SpvOpUDot = 4451,+    SpvOpUDotKHR = 4451,+    SpvOpSUDot = 4452,+    SpvOpSUDotKHR = 4452,+    SpvOpSDotAccSat = 4453,+    SpvOpSDotAccSatKHR = 4453,+    SpvOpUDotAccSat = 4454,+    SpvOpUDotAccSatKHR = 4454,+    SpvOpSUDotAccSat = 4455,+    SpvOpSUDotAccSatKHR = 4455,+    SpvOpTypeRayQueryKHR = 4472,+    SpvOpRayQueryInitializeKHR = 4473,+    SpvOpRayQueryTerminateKHR = 4474,+    SpvOpRayQueryGenerateIntersectionKHR = 4475,+    SpvOpRayQueryConfirmIntersectionKHR = 4476,+    SpvOpRayQueryProceedKHR = 4477,+    SpvOpRayQueryGetIntersectionTypeKHR = 4479,+    SpvOpGroupIAddNonUniformAMD = 5000,+    SpvOpGroupFAddNonUniformAMD = 5001,+    SpvOpGroupFMinNonUniformAMD = 5002,+    SpvOpGroupUMinNonUniformAMD = 5003,+    SpvOpGroupSMinNonUniformAMD = 5004,+    SpvOpGroupFMaxNonUniformAMD = 5005,+    SpvOpGroupUMaxNonUniformAMD = 5006,+    SpvOpGroupSMaxNonUniformAMD = 5007,+    SpvOpFragmentMaskFetchAMD = 5011,+    SpvOpFragmentFetchAMD = 5012,+    SpvOpReadClockKHR = 5056,+    SpvOpImageSampleFootprintNV = 5283,+    SpvOpGroupNonUniformPartitionNV = 5296,+    SpvOpWritePackedPrimitiveIndices4x8NV = 5299,+    SpvOpReportIntersectionKHR = 5334,+    SpvOpReportIntersectionNV = 5334,+    SpvOpIgnoreIntersectionNV = 5335,+    SpvOpTerminateRayNV = 5336,+    SpvOpTraceNV = 5337,+    SpvOpTraceMotionNV = 5338,+    SpvOpTraceRayMotionNV = 5339,+    SpvOpTypeAccelerationStructureKHR = 5341,+    SpvOpTypeAccelerationStructureNV = 5341,+    SpvOpExecuteCallableNV = 5344,+    SpvOpTypeCooperativeMatrixNV = 5358,+    SpvOpCooperativeMatrixLoadNV = 5359,+    SpvOpCooperativeMatrixStoreNV = 5360,+    SpvOpCooperativeMatrixMulAddNV = 5361,+    SpvOpCooperativeMatrixLengthNV = 5362,+    SpvOpBeginInvocationInterlockEXT = 5364,+    SpvOpEndInvocationInterlockEXT = 5365,+    SpvOpDemoteToHelperInvocation = 5380,+    SpvOpDemoteToHelperInvocationEXT = 5380,+    SpvOpIsHelperInvocationEXT = 5381,+    SpvOpConvertUToImageNV = 5391,+    SpvOpConvertUToSamplerNV = 5392,+    SpvOpConvertImageToUNV = 5393,+    SpvOpConvertSamplerToUNV = 5394,+    SpvOpConvertUToSampledImageNV = 5395,+    SpvOpConvertSampledImageToUNV = 5396,+    SpvOpSamplerImageAddressingModeNV = 5397,+    SpvOpSubgroupShuffleINTEL = 5571,+    SpvOpSubgroupShuffleDownINTEL = 5572,+    SpvOpSubgroupShuffleUpINTEL = 5573,+    SpvOpSubgroupShuffleXorINTEL = 5574,+    SpvOpSubgroupBlockReadINTEL = 5575,+    SpvOpSubgroupBlockWriteINTEL = 5576,+    SpvOpSubgroupImageBlockReadINTEL = 5577,+    SpvOpSubgroupImageBlockWriteINTEL = 5578,+    SpvOpSubgroupImageMediaBlockReadINTEL = 5580,+    SpvOpSubgroupImageMediaBlockWriteINTEL = 5581,+    SpvOpUCountLeadingZerosINTEL = 5585,+    SpvOpUCountTrailingZerosINTEL = 5586,+    SpvOpAbsISubINTEL = 5587,+    SpvOpAbsUSubINTEL = 5588,+    SpvOpIAddSatINTEL = 5589,+    SpvOpUAddSatINTEL = 5590,+    SpvOpIAverageINTEL = 5591,+    SpvOpUAverageINTEL = 5592,+    SpvOpIAverageRoundedINTEL = 5593,+    SpvOpUAverageRoundedINTEL = 5594,+    SpvOpISubSatINTEL = 5595,+    SpvOpUSubSatINTEL = 5596,+    SpvOpIMul32x16INTEL = 5597,+    SpvOpUMul32x16INTEL = 5598,+    SpvOpConstantFunctionPointerINTEL = 5600,+    SpvOpFunctionPointerCallINTEL = 5601,+    SpvOpAsmTargetINTEL = 5609,+    SpvOpAsmINTEL = 5610,+    SpvOpAsmCallINTEL = 5611,+    SpvOpAtomicFMinEXT = 5614,+    SpvOpAtomicFMaxEXT = 5615,+    SpvOpAssumeTrueKHR = 5630,+    SpvOpExpectKHR = 5631,+    SpvOpDecorateString = 5632,+    SpvOpDecorateStringGOOGLE = 5632,+    SpvOpMemberDecorateString = 5633,+    SpvOpMemberDecorateStringGOOGLE = 5633,+    SpvOpVmeImageINTEL = 5699,+    SpvOpTypeVmeImageINTEL = 5700,+    SpvOpTypeAvcImePayloadINTEL = 5701,+    SpvOpTypeAvcRefPayloadINTEL = 5702,+    SpvOpTypeAvcSicPayloadINTEL = 5703,+    SpvOpTypeAvcMcePayloadINTEL = 5704,+    SpvOpTypeAvcMceResultINTEL = 5705,+    SpvOpTypeAvcImeResultINTEL = 5706,+    SpvOpTypeAvcImeResultSingleReferenceStreamoutINTEL = 5707,+    SpvOpTypeAvcImeResultDualReferenceStreamoutINTEL = 5708,+    SpvOpTypeAvcImeSingleReferenceStreaminINTEL = 5709,+    SpvOpTypeAvcImeDualReferenceStreaminINTEL = 5710,+    SpvOpTypeAvcRefResultINTEL = 5711,+    SpvOpTypeAvcSicResultINTEL = 5712,+    SpvOpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL = 5713,+    SpvOpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL = 5714,+    SpvOpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL = 5715,+    SpvOpSubgroupAvcMceSetInterShapePenaltyINTEL = 5716,+    SpvOpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL = 5717,+    SpvOpSubgroupAvcMceSetInterDirectionPenaltyINTEL = 5718,+    SpvOpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL = 5719,+    SpvOpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL = 5720,+    SpvOpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL = 5721,+    SpvOpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL = 5722,+    SpvOpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL = 5723,+    SpvOpSubgroupAvcMceSetMotionVectorCostFunctionINTEL = 5724,+    SpvOpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL = 5725,+    SpvOpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL = 5726,+    SpvOpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL = 5727,+    SpvOpSubgroupAvcMceSetAcOnlyHaarINTEL = 5728,+    SpvOpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL = 5729,+    SpvOpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL = 5730,+    SpvOpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL = 5731,+    SpvOpSubgroupAvcMceConvertToImePayloadINTEL = 5732,+    SpvOpSubgroupAvcMceConvertToImeResultINTEL = 5733,+    SpvOpSubgroupAvcMceConvertToRefPayloadINTEL = 5734,+    SpvOpSubgroupAvcMceConvertToRefResultINTEL = 5735,+    SpvOpSubgroupAvcMceConvertToSicPayloadINTEL = 5736,+    SpvOpSubgroupAvcMceConvertToSicResultINTEL = 5737,+    SpvOpSubgroupAvcMceGetMotionVectorsINTEL = 5738,+    SpvOpSubgroupAvcMceGetInterDistortionsINTEL = 5739,+    SpvOpSubgroupAvcMceGetBestInterDistortionsINTEL = 5740,+    SpvOpSubgroupAvcMceGetInterMajorShapeINTEL = 5741,+    SpvOpSubgroupAvcMceGetInterMinorShapeINTEL = 5742,+    SpvOpSubgroupAvcMceGetInterDirectionsINTEL = 5743,+    SpvOpSubgroupAvcMceGetInterMotionVectorCountINTEL = 5744,+    SpvOpSubgroupAvcMceGetInterReferenceIdsINTEL = 5745,+    SpvOpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL = 5746,+    SpvOpSubgroupAvcImeInitializeINTEL = 5747,+    SpvOpSubgroupAvcImeSetSingleReferenceINTEL = 5748,+    SpvOpSubgroupAvcImeSetDualReferenceINTEL = 5749,+    SpvOpSubgroupAvcImeRefWindowSizeINTEL = 5750,+    SpvOpSubgroupAvcImeAdjustRefOffsetINTEL = 5751,+    SpvOpSubgroupAvcImeConvertToMcePayloadINTEL = 5752,+    SpvOpSubgroupAvcImeSetMaxMotionVectorCountINTEL = 5753,+    SpvOpSubgroupAvcImeSetUnidirectionalMixDisableINTEL = 5754,+    SpvOpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL = 5755,+    SpvOpSubgroupAvcImeSetWeightedSadINTEL = 5756,+    SpvOpSubgroupAvcImeEvaluateWithSingleReferenceINTEL = 5757,+    SpvOpSubgroupAvcImeEvaluateWithDualReferenceINTEL = 5758,+    SpvOpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL = 5759,+    SpvOpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL = 5760,+    SpvOpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL = 5761,+    SpvOpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL = 5762,+    SpvOpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL = 5763,+    SpvOpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL = 5764,+    SpvOpSubgroupAvcImeConvertToMceResultINTEL = 5765,+    SpvOpSubgroupAvcImeGetSingleReferenceStreaminINTEL = 5766,+    SpvOpSubgroupAvcImeGetDualReferenceStreaminINTEL = 5767,+    SpvOpSubgroupAvcImeStripSingleReferenceStreamoutINTEL = 5768,+    SpvOpSubgroupAvcImeStripDualReferenceStreamoutINTEL = 5769,+    SpvOpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL = 5770,+    SpvOpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL = 5771,+    SpvOpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL = 5772,+    SpvOpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL = 5773,+    SpvOpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL = 5774,+    SpvOpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL = 5775,+    SpvOpSubgroupAvcImeGetBorderReachedINTEL = 5776,+    SpvOpSubgroupAvcImeGetTruncatedSearchIndicationINTEL = 5777,+    SpvOpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL = 5778,+    SpvOpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL = 5779,+    SpvOpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL = 5780,+    SpvOpSubgroupAvcFmeInitializeINTEL = 5781,+    SpvOpSubgroupAvcBmeInitializeINTEL = 5782,+    SpvOpSubgroupAvcRefConvertToMcePayloadINTEL = 5783,+    SpvOpSubgroupAvcRefSetBidirectionalMixDisableINTEL = 5784,+    SpvOpSubgroupAvcRefSetBilinearFilterEnableINTEL = 5785,+    SpvOpSubgroupAvcRefEvaluateWithSingleReferenceINTEL = 5786,+    SpvOpSubgroupAvcRefEvaluateWithDualReferenceINTEL = 5787,+    SpvOpSubgroupAvcRefEvaluateWithMultiReferenceINTEL = 5788,+    SpvOpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL = 5789,+    SpvOpSubgroupAvcRefConvertToMceResultINTEL = 5790,+    SpvOpSubgroupAvcSicInitializeINTEL = 5791,+    SpvOpSubgroupAvcSicConfigureSkcINTEL = 5792,+    SpvOpSubgroupAvcSicConfigureIpeLumaINTEL = 5793,+    SpvOpSubgroupAvcSicConfigureIpeLumaChromaINTEL = 5794,+    SpvOpSubgroupAvcSicGetMotionVectorMaskINTEL = 5795,+    SpvOpSubgroupAvcSicConvertToMcePayloadINTEL = 5796,+    SpvOpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL = 5797,+    SpvOpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL = 5798,+    SpvOpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL = 5799,+    SpvOpSubgroupAvcSicSetBilinearFilterEnableINTEL = 5800,+    SpvOpSubgroupAvcSicSetSkcForwardTransformEnableINTEL = 5801,+    SpvOpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL = 5802,+    SpvOpSubgroupAvcSicEvaluateIpeINTEL = 5803,+    SpvOpSubgroupAvcSicEvaluateWithSingleReferenceINTEL = 5804,+    SpvOpSubgroupAvcSicEvaluateWithDualReferenceINTEL = 5805,+    SpvOpSubgroupAvcSicEvaluateWithMultiReferenceINTEL = 5806,+    SpvOpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL = 5807,+    SpvOpSubgroupAvcSicConvertToMceResultINTEL = 5808,+    SpvOpSubgroupAvcSicGetIpeLumaShapeINTEL = 5809,+    SpvOpSubgroupAvcSicGetBestIpeLumaDistortionINTEL = 5810,+    SpvOpSubgroupAvcSicGetBestIpeChromaDistortionINTEL = 5811,+    SpvOpSubgroupAvcSicGetPackedIpeLumaModesINTEL = 5812,+    SpvOpSubgroupAvcSicGetIpeChromaModeINTEL = 5813,+    SpvOpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL = 5814,+    SpvOpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL = 5815,+    SpvOpSubgroupAvcSicGetInterRawSadsINTEL = 5816,+    SpvOpVariableLengthArrayINTEL = 5818,+    SpvOpSaveMemoryINTEL = 5819,+    SpvOpRestoreMemoryINTEL = 5820,+    SpvOpArbitraryFloatSinCosPiINTEL = 5840,+    SpvOpArbitraryFloatCastINTEL = 5841,+    SpvOpArbitraryFloatCastFromIntINTEL = 5842,+    SpvOpArbitraryFloatCastToIntINTEL = 5843,+    SpvOpArbitraryFloatAddINTEL = 5846,+    SpvOpArbitraryFloatSubINTEL = 5847,+    SpvOpArbitraryFloatMulINTEL = 5848,+    SpvOpArbitraryFloatDivINTEL = 5849,+    SpvOpArbitraryFloatGTINTEL = 5850,+    SpvOpArbitraryFloatGEINTEL = 5851,+    SpvOpArbitraryFloatLTINTEL = 5852,+    SpvOpArbitraryFloatLEINTEL = 5853,+    SpvOpArbitraryFloatEQINTEL = 5854,+    SpvOpArbitraryFloatRecipINTEL = 5855,+    SpvOpArbitraryFloatRSqrtINTEL = 5856,+    SpvOpArbitraryFloatCbrtINTEL = 5857,+    SpvOpArbitraryFloatHypotINTEL = 5858,+    SpvOpArbitraryFloatSqrtINTEL = 5859,+    SpvOpArbitraryFloatLogINTEL = 5860,+    SpvOpArbitraryFloatLog2INTEL = 5861,+    SpvOpArbitraryFloatLog10INTEL = 5862,+    SpvOpArbitraryFloatLog1pINTEL = 5863,+    SpvOpArbitraryFloatExpINTEL = 5864,+    SpvOpArbitraryFloatExp2INTEL = 5865,+    SpvOpArbitraryFloatExp10INTEL = 5866,+    SpvOpArbitraryFloatExpm1INTEL = 5867,+    SpvOpArbitraryFloatSinINTEL = 5868,+    SpvOpArbitraryFloatCosINTEL = 5869,+    SpvOpArbitraryFloatSinCosINTEL = 5870,+    SpvOpArbitraryFloatSinPiINTEL = 5871,+    SpvOpArbitraryFloatCosPiINTEL = 5872,+    SpvOpArbitraryFloatASinINTEL = 5873,+    SpvOpArbitraryFloatASinPiINTEL = 5874,+    SpvOpArbitraryFloatACosINTEL = 5875,+    SpvOpArbitraryFloatACosPiINTEL = 5876,+    SpvOpArbitraryFloatATanINTEL = 5877,+    SpvOpArbitraryFloatATanPiINTEL = 5878,+    SpvOpArbitraryFloatATan2INTEL = 5879,+    SpvOpArbitraryFloatPowINTEL = 5880,+    SpvOpArbitraryFloatPowRINTEL = 5881,+    SpvOpArbitraryFloatPowNINTEL = 5882,+    SpvOpLoopControlINTEL = 5887,+    SpvOpAliasDomainDeclINTEL = 5911,+    SpvOpAliasScopeDeclINTEL = 5912,+    SpvOpAliasScopeListDeclINTEL = 5913,+    SpvOpFixedSqrtINTEL = 5923,+    SpvOpFixedRecipINTEL = 5924,+    SpvOpFixedRsqrtINTEL = 5925,+    SpvOpFixedSinINTEL = 5926,+    SpvOpFixedCosINTEL = 5927,+    SpvOpFixedSinCosINTEL = 5928,+    SpvOpFixedSinPiINTEL = 5929,+    SpvOpFixedCosPiINTEL = 5930,+    SpvOpFixedSinCosPiINTEL = 5931,+    SpvOpFixedLogINTEL = 5932,+    SpvOpFixedExpINTEL = 5933,+    SpvOpPtrCastToCrossWorkgroupINTEL = 5934,+    SpvOpCrossWorkgroupCastToPtrINTEL = 5938,+    SpvOpReadPipeBlockingINTEL = 5946,+    SpvOpWritePipeBlockingINTEL = 5947,+    SpvOpFPGARegINTEL = 5949,+    SpvOpRayQueryGetRayTMinKHR = 6016,+    SpvOpRayQueryGetRayFlagsKHR = 6017,+    SpvOpRayQueryGetIntersectionTKHR = 6018,+    SpvOpRayQueryGetIntersectionInstanceCustomIndexKHR = 6019,+    SpvOpRayQueryGetIntersectionInstanceIdKHR = 6020,+    SpvOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR = 6021,+    SpvOpRayQueryGetIntersectionGeometryIndexKHR = 6022,+    SpvOpRayQueryGetIntersectionPrimitiveIndexKHR = 6023,+    SpvOpRayQueryGetIntersectionBarycentricsKHR = 6024,+    SpvOpRayQueryGetIntersectionFrontFaceKHR = 6025,+    SpvOpRayQueryGetIntersectionCandidateAABBOpaqueKHR = 6026,+    SpvOpRayQueryGetIntersectionObjectRayDirectionKHR = 6027,+    SpvOpRayQueryGetIntersectionObjectRayOriginKHR = 6028,+    SpvOpRayQueryGetWorldRayDirectionKHR = 6029,+    SpvOpRayQueryGetWorldRayOriginKHR = 6030,+    SpvOpRayQueryGetIntersectionObjectToWorldKHR = 6031,+    SpvOpRayQueryGetIntersectionWorldToObjectKHR = 6032,+    SpvOpAtomicFAddEXT = 6035,+    SpvOpTypeBufferSurfaceINTEL = 6086,+    SpvOpTypeStructContinuedINTEL = 6090,+    SpvOpConstantCompositeContinuedINTEL = 6091,+    SpvOpSpecConstantCompositeContinuedINTEL = 6092,+    SpvOpControlBarrierArriveINTEL = 6142,+    SpvOpControlBarrierWaitINTEL = 6143,+    SpvOpGroupIMulKHR = 6401,+    SpvOpGroupFMulKHR = 6402,+    SpvOpGroupBitwiseAndKHR = 6403,+    SpvOpGroupBitwiseOrKHR = 6404,+    SpvOpGroupBitwiseXorKHR = 6405,+    SpvOpGroupLogicalAndKHR = 6406,+    SpvOpGroupLogicalOrKHR = 6407,+    SpvOpGroupLogicalXorKHR = 6408,+    SpvOpMax = 0x7fffffff,+} SpvOp;++#ifdef SPV_ENABLE_UTILITY_CODE+#ifndef __cplusplus+#include <stdbool.h>+#endif+inline void SpvHasResultAndType(SpvOp opcode, bool *hasResult, bool *hasResultType) {+    *hasResult = *hasResultType = false;+    switch (opcode) {+    default: /* unknown opcode */ break;+    case SpvOpNop: *hasResult = false; *hasResultType = false; break;+    case SpvOpUndef: *hasResult = true; *hasResultType = true; break;+    case SpvOpSourceContinued: *hasResult = false; *hasResultType = false; break;+    case SpvOpSource: *hasResult = false; *hasResultType = false; break;+    case SpvOpSourceExtension: *hasResult = false; *hasResultType = false; break;+    case SpvOpName: *hasResult = false; *hasResultType = false; break;+    case SpvOpMemberName: *hasResult = false; *hasResultType = false; break;+    case SpvOpString: *hasResult = true; *hasResultType = false; break;+    case SpvOpLine: *hasResult = false; *hasResultType = false; break;+    case SpvOpExtension: *hasResult = false; *hasResultType = false; break;+    case SpvOpExtInstImport: *hasResult = true; *hasResultType = false; break;+    case SpvOpExtInst: *hasResult = true; *hasResultType = true; break;+    case SpvOpMemoryModel: *hasResult = false; *hasResultType = false; break;+    case SpvOpEntryPoint: *hasResult = false; *hasResultType = false; break;+    case SpvOpExecutionMode: *hasResult = false; *hasResultType = false; break;+    case SpvOpCapability: *hasResult = false; *hasResultType = false; break;+    case SpvOpTypeVoid: *hasResult = true; *hasResultType = false; break;+    case SpvOpTypeBool: *hasResult = true; *hasResultType = false; break;+    case SpvOpTypeInt: *hasResult = true; *hasResultType = false; break;+    case SpvOpTypeFloat: *hasResult = true; *hasResultType = false; break;+    case SpvOpTypeVector: *hasResult = true; *hasResultType = false; break;+    case SpvOpTypeMatrix: *hasResult = true; *hasResultType = false; break;+    case SpvOpTypeImage: *hasResult = true; *hasResultType = false; break;+    case SpvOpTypeSampler: *hasResult = true; *hasResultType = false; break;+    case SpvOpTypeSampledImage: *hasResult = true; *hasResultType = false; break;+    case SpvOpTypeArray: *hasResult = true; *hasResultType = false; break;+    case SpvOpTypeRuntimeArray: *hasResult = true; *hasResultType = false; break;+    case SpvOpTypeStruct: *hasResult = true; *hasResultType = false; break;+    case SpvOpTypeOpaque: *hasResult = true; *hasResultType = false; break;+    case SpvOpTypePointer: *hasResult = true; *hasResultType = false; break;+    case SpvOpTypeFunction: *hasResult = true; *hasResultType = false; break;+    case SpvOpTypeEvent: *hasResult = true; *hasResultType = false; break;+    case SpvOpTypeDeviceEvent: *hasResult = true; *hasResultType = false; break;+    case SpvOpTypeReserveId: *hasResult = true; *hasResultType = false; break;+    case SpvOpTypeQueue: *hasResult = true; *hasResultType = false; break;+    case SpvOpTypePipe: *hasResult = true; *hasResultType = false; break;+    case SpvOpTypeForwardPointer: *hasResult = false; *hasResultType = false; break;+    case SpvOpConstantTrue: *hasResult = true; *hasResultType = true; break;+    case SpvOpConstantFalse: *hasResult = true; *hasResultType = true; break;+    case SpvOpConstant: *hasResult = true; *hasResultType = true; break;+    case SpvOpConstantComposite: *hasResult = true; *hasResultType = true; break;+    case SpvOpConstantSampler: *hasResult = true; *hasResultType = true; break;+    case SpvOpConstantNull: *hasResult = true; *hasResultType = true; break;+    case SpvOpSpecConstantTrue: *hasResult = true; *hasResultType = true; break;+    case SpvOpSpecConstantFalse: *hasResult = true; *hasResultType = true; break;+    case SpvOpSpecConstant: *hasResult = true; *hasResultType = true; break;+    case SpvOpSpecConstantComposite: *hasResult = true; *hasResultType = true; break;+    case SpvOpSpecConstantOp: *hasResult = true; *hasResultType = true; break;+    case SpvOpFunction: *hasResult = true; *hasResultType = true; break;+    case SpvOpFunctionParameter: *hasResult = true; *hasResultType = true; break;+    case SpvOpFunctionEnd: *hasResult = false; *hasResultType = false; break;+    case SpvOpFunctionCall: *hasResult = true; *hasResultType = true; break;+    case SpvOpVariable: *hasResult = true; *hasResultType = true; break;+    case SpvOpImageTexelPointer: *hasResult = true; *hasResultType = true; break;+    case SpvOpLoad: *hasResult = true; *hasResultType = true; break;+    case SpvOpStore: *hasResult = false; *hasResultType = false; break;+    case SpvOpCopyMemory: *hasResult = false; *hasResultType = false; break;+    case SpvOpCopyMemorySized: *hasResult = false; *hasResultType = false; break;+    case SpvOpAccessChain: *hasResult = true; *hasResultType = true; break;+    case SpvOpInBoundsAccessChain: *hasResult = true; *hasResultType = true; break;+    case SpvOpPtrAccessChain: *hasResult = true; *hasResultType = true; break;+    case SpvOpArrayLength: *hasResult = true; *hasResultType = true; break;+    case SpvOpGenericPtrMemSemantics: *hasResult = true; *hasResultType = true; break;+    case SpvOpInBoundsPtrAccessChain: *hasResult = true; *hasResultType = true; break;+    case SpvOpDecorate: *hasResult = false; *hasResultType = false; break;+    case SpvOpMemberDecorate: *hasResult = false; *hasResultType = false; break;+    case SpvOpDecorationGroup: *hasResult = true; *hasResultType = false; break;+    case SpvOpGroupDecorate: *hasResult = false; *hasResultType = false; break;+    case SpvOpGroupMemberDecorate: *hasResult = false; *hasResultType = false; break;+    case SpvOpVectorExtractDynamic: *hasResult = true; *hasResultType = true; break;+    case SpvOpVectorInsertDynamic: *hasResult = true; *hasResultType = true; break;+    case SpvOpVectorShuffle: *hasResult = true; *hasResultType = true; break;+    case SpvOpCompositeConstruct: *hasResult = true; *hasResultType = true; break;+    case SpvOpCompositeExtract: *hasResult = true; *hasResultType = true; break;+    case SpvOpCompositeInsert: *hasResult = true; *hasResultType = true; break;+    case SpvOpCopyObject: *hasResult = true; *hasResultType = true; break;+    case SpvOpTranspose: *hasResult = true; *hasResultType = true; break;+    case SpvOpSampledImage: *hasResult = true; *hasResultType = true; break;+    case SpvOpImageSampleImplicitLod: *hasResult = true; *hasResultType = true; break;+    case SpvOpImageSampleExplicitLod: *hasResult = true; *hasResultType = true; break;+    case SpvOpImageSampleDrefImplicitLod: *hasResult = true; *hasResultType = true; break;+    case SpvOpImageSampleDrefExplicitLod: *hasResult = true; *hasResultType = true; break;+    case SpvOpImageSampleProjImplicitLod: *hasResult = true; *hasResultType = true; break;+    case SpvOpImageSampleProjExplicitLod: *hasResult = true; *hasResultType = true; break;+    case SpvOpImageSampleProjDrefImplicitLod: *hasResult = true; *hasResultType = true; break;+    case SpvOpImageSampleProjDrefExplicitLod: *hasResult = true; *hasResultType = true; break;+    case SpvOpImageFetch: *hasResult = true; *hasResultType = true; break;+    case SpvOpImageGather: *hasResult = true; *hasResultType = true; break;+    case SpvOpImageDrefGather: *hasResult = true; *hasResultType = true; break;+    case SpvOpImageRead: *hasResult = true; *hasResultType = true; break;+    case SpvOpImageWrite: *hasResult = false; *hasResultType = false; break;+    case SpvOpImage: *hasResult = true; *hasResultType = true; break;+    case SpvOpImageQueryFormat: *hasResult = true; *hasResultType = true; break;+    case SpvOpImageQueryOrder: *hasResult = true; *hasResultType = true; break;+    case SpvOpImageQuerySizeLod: *hasResult = true; *hasResultType = true; break;+    case SpvOpImageQuerySize: *hasResult = true; *hasResultType = true; break;+    case SpvOpImageQueryLod: *hasResult = true; *hasResultType = true; break;+    case SpvOpImageQueryLevels: *hasResult = true; *hasResultType = true; break;+    case SpvOpImageQuerySamples: *hasResult = true; *hasResultType = true; break;+    case SpvOpConvertFToU: *hasResult = true; *hasResultType = true; break;+    case SpvOpConvertFToS: *hasResult = true; *hasResultType = true; break;+    case SpvOpConvertSToF: *hasResult = true; *hasResultType = true; break;+    case SpvOpConvertUToF: *hasResult = true; *hasResultType = true; break;+    case SpvOpUConvert: *hasResult = true; *hasResultType = true; break;+    case SpvOpSConvert: *hasResult = true; *hasResultType = true; break;+    case SpvOpFConvert: *hasResult = true; *hasResultType = true; break;+    case SpvOpQuantizeToF16: *hasResult = true; *hasResultType = true; break;+    case SpvOpConvertPtrToU: *hasResult = true; *hasResultType = true; break;+    case SpvOpSatConvertSToU: *hasResult = true; *hasResultType = true; break;+    case SpvOpSatConvertUToS: *hasResult = true; *hasResultType = true; break;+    case SpvOpConvertUToPtr: *hasResult = true; *hasResultType = true; break;+    case SpvOpPtrCastToGeneric: *hasResult = true; *hasResultType = true; break;+    case SpvOpGenericCastToPtr: *hasResult = true; *hasResultType = true; break;+    case SpvOpGenericCastToPtrExplicit: *hasResult = true; *hasResultType = true; break;+    case SpvOpBitcast: *hasResult = true; *hasResultType = true; break;+    case SpvOpSNegate: *hasResult = true; *hasResultType = true; break;+    case SpvOpFNegate: *hasResult = true; *hasResultType = true; break;+    case SpvOpIAdd: *hasResult = true; *hasResultType = true; break;+    case SpvOpFAdd: *hasResult = true; *hasResultType = true; break;+    case SpvOpISub: *hasResult = true; *hasResultType = true; break;+    case SpvOpFSub: *hasResult = true; *hasResultType = true; break;+    case SpvOpIMul: *hasResult = true; *hasResultType = true; break;+    case SpvOpFMul: *hasResult = true; *hasResultType = true; break;+    case SpvOpUDiv: *hasResult = true; *hasResultType = true; break;+    case SpvOpSDiv: *hasResult = true; *hasResultType = true; break;+    case SpvOpFDiv: *hasResult = true; *hasResultType = true; break;+    case SpvOpUMod: *hasResult = true; *hasResultType = true; break;+    case SpvOpSRem: *hasResult = true; *hasResultType = true; break;+    case SpvOpSMod: *hasResult = true; *hasResultType = true; break;+    case SpvOpFRem: *hasResult = true; *hasResultType = true; break;+    case SpvOpFMod: *hasResult = true; *hasResultType = true; break;+    case SpvOpVectorTimesScalar: *hasResult = true; *hasResultType = true; break;+    case SpvOpMatrixTimesScalar: *hasResult = true; *hasResultType = true; break;+    case SpvOpVectorTimesMatrix: *hasResult = true; *hasResultType = true; break;+    case SpvOpMatrixTimesVector: *hasResult = true; *hasResultType = true; break;+    case SpvOpMatrixTimesMatrix: *hasResult = true; *hasResultType = true; break;+    case SpvOpOuterProduct: *hasResult = true; *hasResultType = true; break;+    case SpvOpDot: *hasResult = true; *hasResultType = true; break;+    case SpvOpIAddCarry: *hasResult = true; *hasResultType = true; break;+    case SpvOpISubBorrow: *hasResult = true; *hasResultType = true; break;+    case SpvOpUMulExtended: *hasResult = true; *hasResultType = true; break;+    case SpvOpSMulExtended: *hasResult = true; *hasResultType = true; break;+    case SpvOpAny: *hasResult = true; *hasResultType = true; break;+    case SpvOpAll: *hasResult = true; *hasResultType = true; break;+    case SpvOpIsNan: *hasResult = true; *hasResultType = true; break;+    case SpvOpIsInf: *hasResult = true; *hasResultType = true; break;+    case SpvOpIsFinite: *hasResult = true; *hasResultType = true; break;+    case SpvOpIsNormal: *hasResult = true; *hasResultType = true; break;+    case SpvOpSignBitSet: *hasResult = true; *hasResultType = true; break;+    case SpvOpLessOrGreater: *hasResult = true; *hasResultType = true; break;+    case SpvOpOrdered: *hasResult = true; *hasResultType = true; break;+    case SpvOpUnordered: *hasResult = true; *hasResultType = true; break;+    case SpvOpLogicalEqual: *hasResult = true; *hasResultType = true; break;+    case SpvOpLogicalNotEqual: *hasResult = true; *hasResultType = true; break;+    case SpvOpLogicalOr: *hasResult = true; *hasResultType = true; break;+    case SpvOpLogicalAnd: *hasResult = true; *hasResultType = true; break;+    case SpvOpLogicalNot: *hasResult = true; *hasResultType = true; break;+    case SpvOpSelect: *hasResult = true; *hasResultType = true; break;+    case SpvOpIEqual: *hasResult = true; *hasResultType = true; break;+    case SpvOpINotEqual: *hasResult = true; *hasResultType = true; break;+    case SpvOpUGreaterThan: *hasResult = true; *hasResultType = true; break;+    case SpvOpSGreaterThan: *hasResult = true; *hasResultType = true; break;+    case SpvOpUGreaterThanEqual: *hasResult = true; *hasResultType = true; break;+    case SpvOpSGreaterThanEqual: *hasResult = true; *hasResultType = true; break;+    case SpvOpULessThan: *hasResult = true; *hasResultType = true; break;+    case SpvOpSLessThan: *hasResult = true; *hasResultType = true; break;+    case SpvOpULessThanEqual: *hasResult = true; *hasResultType = true; break;+    case SpvOpSLessThanEqual: *hasResult = true; *hasResultType = true; break;+    case SpvOpFOrdEqual: *hasResult = true; *hasResultType = true; break;+    case SpvOpFUnordEqual: *hasResult = true; *hasResultType = true; break;+    case SpvOpFOrdNotEqual: *hasResult = true; *hasResultType = true; break;+    case SpvOpFUnordNotEqual: *hasResult = true; *hasResultType = true; break;+    case SpvOpFOrdLessThan: *hasResult = true; *hasResultType = true; break;+    case SpvOpFUnordLessThan: *hasResult = true; *hasResultType = true; break;+    case SpvOpFOrdGreaterThan: *hasResult = true; *hasResultType = true; break;+    case SpvOpFUnordGreaterThan: *hasResult = true; *hasResultType = true; break;+    case SpvOpFOrdLessThanEqual: *hasResult = true; *hasResultType = true; break;+    case SpvOpFUnordLessThanEqual: *hasResult = true; *hasResultType = true; break;+    case SpvOpFOrdGreaterThanEqual: *hasResult = true; *hasResultType = true; break;+    case SpvOpFUnordGreaterThanEqual: *hasResult = true; *hasResultType = true; break;+    case SpvOpShiftRightLogical: *hasResult = true; *hasResultType = true; break;+    case SpvOpShiftRightArithmetic: *hasResult = true; *hasResultType = true; break;+    case SpvOpShiftLeftLogical: *hasResult = true; *hasResultType = true; break;+    case SpvOpBitwiseOr: *hasResult = true; *hasResultType = true; break;+    case SpvOpBitwiseXor: *hasResult = true; *hasResultType = true; break;+    case SpvOpBitwiseAnd: *hasResult = true; *hasResultType = true; break;+    case SpvOpNot: *hasResult = true; *hasResultType = true; break;+    case SpvOpBitFieldInsert: *hasResult = true; *hasResultType = true; break;+    case SpvOpBitFieldSExtract: *hasResult = true; *hasResultType = true; break;+    case SpvOpBitFieldUExtract: *hasResult = true; *hasResultType = true; break;+    case SpvOpBitReverse: *hasResult = true; *hasResultType = true; break;+    case SpvOpBitCount: *hasResult = true; *hasResultType = true; break;+    case SpvOpDPdx: *hasResult = true; *hasResultType = true; break;+    case SpvOpDPdy: *hasResult = true; *hasResultType = true; break;+    case SpvOpFwidth: *hasResult = true; *hasResultType = true; break;+    case SpvOpDPdxFine: *hasResult = true; *hasResultType = true; break;+    case SpvOpDPdyFine: *hasResult = true; *hasResultType = true; break;+    case SpvOpFwidthFine: *hasResult = true; *hasResultType = true; break;+    case SpvOpDPdxCoarse: *hasResult = true; *hasResultType = true; break;+    case SpvOpDPdyCoarse: *hasResult = true; *hasResultType = true; break;+    case SpvOpFwidthCoarse: *hasResult = true; *hasResultType = true; break;+    case SpvOpEmitVertex: *hasResult = false; *hasResultType = false; break;+    case SpvOpEndPrimitive: *hasResult = false; *hasResultType = false; break;+    case SpvOpEmitStreamVertex: *hasResult = false; *hasResultType = false; break;+    case SpvOpEndStreamPrimitive: *hasResult = false; *hasResultType = false; break;+    case SpvOpControlBarrier: *hasResult = false; *hasResultType = false; break;+    case SpvOpMemoryBarrier: *hasResult = false; *hasResultType = false; break;+    case SpvOpAtomicLoad: *hasResult = true; *hasResultType = true; break;+    case SpvOpAtomicStore: *hasResult = false; *hasResultType = false; break;+    case SpvOpAtomicExchange: *hasResult = true; *hasResultType = true; break;+    case SpvOpAtomicCompareExchange: *hasResult = true; *hasResultType = true; break;+    case SpvOpAtomicCompareExchangeWeak: *hasResult = true; *hasResultType = true; break;+    case SpvOpAtomicIIncrement: *hasResult = true; *hasResultType = true; break;+    case SpvOpAtomicIDecrement: *hasResult = true; *hasResultType = true; break;+    case SpvOpAtomicIAdd: *hasResult = true; *hasResultType = true; break;+    case SpvOpAtomicISub: *hasResult = true; *hasResultType = true; break;+    case SpvOpAtomicSMin: *hasResult = true; *hasResultType = true; break;+    case SpvOpAtomicUMin: *hasResult = true; *hasResultType = true; break;+    case SpvOpAtomicSMax: *hasResult = true; *hasResultType = true; break;+    case SpvOpAtomicUMax: *hasResult = true; *hasResultType = true; break;+    case SpvOpAtomicAnd: *hasResult = true; *hasResultType = true; break;+    case SpvOpAtomicOr: *hasResult = true; *hasResultType = true; break;+    case SpvOpAtomicXor: *hasResult = true; *hasResultType = true; break;+    case SpvOpPhi: *hasResult = true; *hasResultType = true; break;+    case SpvOpLoopMerge: *hasResult = false; *hasResultType = false; break;+    case SpvOpSelectionMerge: *hasResult = false; *hasResultType = false; break;+    case SpvOpLabel: *hasResult = true; *hasResultType = false; break;+    case SpvOpBranch: *hasResult = false; *hasResultType = false; break;+    case SpvOpBranchConditional: *hasResult = false; *hasResultType = false; break;+    case SpvOpSwitch: *hasResult = false; *hasResultType = false; break;+    case SpvOpKill: *hasResult = false; *hasResultType = false; break;+    case SpvOpReturn: *hasResult = false; *hasResultType = false; break;+    case SpvOpReturnValue: *hasResult = false; *hasResultType = false; break;+    case SpvOpUnreachable: *hasResult = false; *hasResultType = false; break;+    case SpvOpLifetimeStart: *hasResult = false; *hasResultType = false; break;+    case SpvOpLifetimeStop: *hasResult = false; *hasResultType = false; break;+    case SpvOpGroupAsyncCopy: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupWaitEvents: *hasResult = false; *hasResultType = false; break;+    case SpvOpGroupAll: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupAny: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupBroadcast: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupIAdd: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupFAdd: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupFMin: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupUMin: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupSMin: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupFMax: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupUMax: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupSMax: *hasResult = true; *hasResultType = true; break;+    case SpvOpReadPipe: *hasResult = true; *hasResultType = true; break;+    case SpvOpWritePipe: *hasResult = true; *hasResultType = true; break;+    case SpvOpReservedReadPipe: *hasResult = true; *hasResultType = true; break;+    case SpvOpReservedWritePipe: *hasResult = true; *hasResultType = true; break;+    case SpvOpReserveReadPipePackets: *hasResult = true; *hasResultType = true; break;+    case SpvOpReserveWritePipePackets: *hasResult = true; *hasResultType = true; break;+    case SpvOpCommitReadPipe: *hasResult = false; *hasResultType = false; break;+    case SpvOpCommitWritePipe: *hasResult = false; *hasResultType = false; break;+    case SpvOpIsValidReserveId: *hasResult = true; *hasResultType = true; break;+    case SpvOpGetNumPipePackets: *hasResult = true; *hasResultType = true; break;+    case SpvOpGetMaxPipePackets: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupReserveReadPipePackets: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupReserveWritePipePackets: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupCommitReadPipe: *hasResult = false; *hasResultType = false; break;+    case SpvOpGroupCommitWritePipe: *hasResult = false; *hasResultType = false; break;+    case SpvOpEnqueueMarker: *hasResult = true; *hasResultType = true; break;+    case SpvOpEnqueueKernel: *hasResult = true; *hasResultType = true; break;+    case SpvOpGetKernelNDrangeSubGroupCount: *hasResult = true; *hasResultType = true; break;+    case SpvOpGetKernelNDrangeMaxSubGroupSize: *hasResult = true; *hasResultType = true; break;+    case SpvOpGetKernelWorkGroupSize: *hasResult = true; *hasResultType = true; break;+    case SpvOpGetKernelPreferredWorkGroupSizeMultiple: *hasResult = true; *hasResultType = true; break;+    case SpvOpRetainEvent: *hasResult = false; *hasResultType = false; break;+    case SpvOpReleaseEvent: *hasResult = false; *hasResultType = false; break;+    case SpvOpCreateUserEvent: *hasResult = true; *hasResultType = true; break;+    case SpvOpIsValidEvent: *hasResult = true; *hasResultType = true; break;+    case SpvOpSetUserEventStatus: *hasResult = false; *hasResultType = false; break;+    case SpvOpCaptureEventProfilingInfo: *hasResult = false; *hasResultType = false; break;+    case SpvOpGetDefaultQueue: *hasResult = true; *hasResultType = true; break;+    case SpvOpBuildNDRange: *hasResult = true; *hasResultType = true; break;+    case SpvOpImageSparseSampleImplicitLod: *hasResult = true; *hasResultType = true; break;+    case SpvOpImageSparseSampleExplicitLod: *hasResult = true; *hasResultType = true; break;+    case SpvOpImageSparseSampleDrefImplicitLod: *hasResult = true; *hasResultType = true; break;+    case SpvOpImageSparseSampleDrefExplicitLod: *hasResult = true; *hasResultType = true; break;+    case SpvOpImageSparseSampleProjImplicitLod: *hasResult = true; *hasResultType = true; break;+    case SpvOpImageSparseSampleProjExplicitLod: *hasResult = true; *hasResultType = true; break;+    case SpvOpImageSparseSampleProjDrefImplicitLod: *hasResult = true; *hasResultType = true; break;+    case SpvOpImageSparseSampleProjDrefExplicitLod: *hasResult = true; *hasResultType = true; break;+    case SpvOpImageSparseFetch: *hasResult = true; *hasResultType = true; break;+    case SpvOpImageSparseGather: *hasResult = true; *hasResultType = true; break;+    case SpvOpImageSparseDrefGather: *hasResult = true; *hasResultType = true; break;+    case SpvOpImageSparseTexelsResident: *hasResult = true; *hasResultType = true; break;+    case SpvOpNoLine: *hasResult = false; *hasResultType = false; break;+    case SpvOpAtomicFlagTestAndSet: *hasResult = true; *hasResultType = true; break;+    case SpvOpAtomicFlagClear: *hasResult = false; *hasResultType = false; break;+    case SpvOpImageSparseRead: *hasResult = true; *hasResultType = true; break;+    case SpvOpSizeOf: *hasResult = true; *hasResultType = true; break;+    case SpvOpTypePipeStorage: *hasResult = true; *hasResultType = false; break;+    case SpvOpConstantPipeStorage: *hasResult = true; *hasResultType = true; break;+    case SpvOpCreatePipeFromPipeStorage: *hasResult = true; *hasResultType = true; break;+    case SpvOpGetKernelLocalSizeForSubgroupCount: *hasResult = true; *hasResultType = true; break;+    case SpvOpGetKernelMaxNumSubgroups: *hasResult = true; *hasResultType = true; break;+    case SpvOpTypeNamedBarrier: *hasResult = true; *hasResultType = false; break;+    case SpvOpNamedBarrierInitialize: *hasResult = true; *hasResultType = true; break;+    case SpvOpMemoryNamedBarrier: *hasResult = false; *hasResultType = false; break;+    case SpvOpModuleProcessed: *hasResult = false; *hasResultType = false; break;+    case SpvOpExecutionModeId: *hasResult = false; *hasResultType = false; break;+    case SpvOpDecorateId: *hasResult = false; *hasResultType = false; break;+    case SpvOpGroupNonUniformElect: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupNonUniformAll: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupNonUniformAny: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupNonUniformAllEqual: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupNonUniformBroadcast: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupNonUniformBroadcastFirst: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupNonUniformBallot: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupNonUniformInverseBallot: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupNonUniformBallotBitExtract: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupNonUniformBallotBitCount: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupNonUniformBallotFindLSB: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupNonUniformBallotFindMSB: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupNonUniformShuffle: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupNonUniformShuffleXor: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupNonUniformShuffleUp: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupNonUniformShuffleDown: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupNonUniformIAdd: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupNonUniformFAdd: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupNonUniformIMul: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupNonUniformFMul: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupNonUniformSMin: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupNonUniformUMin: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupNonUniformFMin: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupNonUniformSMax: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupNonUniformUMax: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupNonUniformFMax: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupNonUniformBitwiseAnd: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupNonUniformBitwiseOr: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupNonUniformBitwiseXor: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupNonUniformLogicalAnd: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupNonUniformLogicalOr: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupNonUniformLogicalXor: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupNonUniformQuadBroadcast: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupNonUniformQuadSwap: *hasResult = true; *hasResultType = true; break;+    case SpvOpCopyLogical: *hasResult = true; *hasResultType = true; break;+    case SpvOpPtrEqual: *hasResult = true; *hasResultType = true; break;+    case SpvOpPtrNotEqual: *hasResult = true; *hasResultType = true; break;+    case SpvOpPtrDiff: *hasResult = true; *hasResultType = true; break;+    case SpvOpTerminateInvocation: *hasResult = false; *hasResultType = false; break;+    case SpvOpSubgroupBallotKHR: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupFirstInvocationKHR: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAllKHR: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAnyKHR: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAllEqualKHR: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupNonUniformRotateKHR: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupReadInvocationKHR: *hasResult = true; *hasResultType = true; break;+    case SpvOpTraceRayKHR: *hasResult = false; *hasResultType = false; break;+    case SpvOpExecuteCallableKHR: *hasResult = false; *hasResultType = false; break;+    case SpvOpConvertUToAccelerationStructureKHR: *hasResult = true; *hasResultType = true; break;+    case SpvOpIgnoreIntersectionKHR: *hasResult = false; *hasResultType = false; break;+    case SpvOpTerminateRayKHR: *hasResult = false; *hasResultType = false; break;+    case SpvOpSDot: *hasResult = true; *hasResultType = true; break;+    case SpvOpUDot: *hasResult = true; *hasResultType = true; break;+    case SpvOpSUDot: *hasResult = true; *hasResultType = true; break;+    case SpvOpSDotAccSat: *hasResult = true; *hasResultType = true; break;+    case SpvOpUDotAccSat: *hasResult = true; *hasResultType = true; break;+    case SpvOpSUDotAccSat: *hasResult = true; *hasResultType = true; break;+    case SpvOpTypeRayQueryKHR: *hasResult = true; *hasResultType = false; break;+    case SpvOpRayQueryInitializeKHR: *hasResult = false; *hasResultType = false; break;+    case SpvOpRayQueryTerminateKHR: *hasResult = false; *hasResultType = false; break;+    case SpvOpRayQueryGenerateIntersectionKHR: *hasResult = false; *hasResultType = false; break;+    case SpvOpRayQueryConfirmIntersectionKHR: *hasResult = false; *hasResultType = false; break;+    case SpvOpRayQueryProceedKHR: *hasResult = true; *hasResultType = true; break;+    case SpvOpRayQueryGetIntersectionTypeKHR: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupIAddNonUniformAMD: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupFAddNonUniformAMD: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupFMinNonUniformAMD: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupUMinNonUniformAMD: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupSMinNonUniformAMD: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupFMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupUMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupSMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break;+    case SpvOpFragmentMaskFetchAMD: *hasResult = true; *hasResultType = true; break;+    case SpvOpFragmentFetchAMD: *hasResult = true; *hasResultType = true; break;+    case SpvOpReadClockKHR: *hasResult = true; *hasResultType = true; break;+    case SpvOpImageSampleFootprintNV: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupNonUniformPartitionNV: *hasResult = true; *hasResultType = true; break;+    case SpvOpWritePackedPrimitiveIndices4x8NV: *hasResult = false; *hasResultType = false; break;+    case SpvOpReportIntersectionNV: *hasResult = true; *hasResultType = true; break;+    case SpvOpIgnoreIntersectionNV: *hasResult = false; *hasResultType = false; break;+    case SpvOpTerminateRayNV: *hasResult = false; *hasResultType = false; break;+    case SpvOpTraceNV: *hasResult = false; *hasResultType = false; break;+    case SpvOpTraceMotionNV: *hasResult = false; *hasResultType = false; break;+    case SpvOpTraceRayMotionNV: *hasResult = false; *hasResultType = false; break;+    case SpvOpTypeAccelerationStructureNV: *hasResult = true; *hasResultType = false; break;+    case SpvOpExecuteCallableNV: *hasResult = false; *hasResultType = false; break;+    case SpvOpTypeCooperativeMatrixNV: *hasResult = true; *hasResultType = false; break;+    case SpvOpCooperativeMatrixLoadNV: *hasResult = true; *hasResultType = true; break;+    case SpvOpCooperativeMatrixStoreNV: *hasResult = false; *hasResultType = false; break;+    case SpvOpCooperativeMatrixMulAddNV: *hasResult = true; *hasResultType = true; break;+    case SpvOpCooperativeMatrixLengthNV: *hasResult = true; *hasResultType = true; break;+    case SpvOpBeginInvocationInterlockEXT: *hasResult = false; *hasResultType = false; break;+    case SpvOpEndInvocationInterlockEXT: *hasResult = false; *hasResultType = false; break;+    case SpvOpDemoteToHelperInvocation: *hasResult = false; *hasResultType = false; break;+    case SpvOpIsHelperInvocationEXT: *hasResult = true; *hasResultType = true; break;+    case SpvOpConvertUToImageNV: *hasResult = true; *hasResultType = true; break;+    case SpvOpConvertUToSamplerNV: *hasResult = true; *hasResultType = true; break;+    case SpvOpConvertImageToUNV: *hasResult = true; *hasResultType = true; break;+    case SpvOpConvertSamplerToUNV: *hasResult = true; *hasResultType = true; break;+    case SpvOpConvertUToSampledImageNV: *hasResult = true; *hasResultType = true; break;+    case SpvOpConvertSampledImageToUNV: *hasResult = true; *hasResultType = true; break;+    case SpvOpSamplerImageAddressingModeNV: *hasResult = false; *hasResultType = false; break;+    case SpvOpSubgroupShuffleINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupShuffleDownINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupShuffleUpINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupShuffleXorINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupBlockReadINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupBlockWriteINTEL: *hasResult = false; *hasResultType = false; break;+    case SpvOpSubgroupImageBlockReadINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupImageBlockWriteINTEL: *hasResult = false; *hasResultType = false; break;+    case SpvOpSubgroupImageMediaBlockReadINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupImageMediaBlockWriteINTEL: *hasResult = false; *hasResultType = false; break;+    case SpvOpUCountLeadingZerosINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpUCountTrailingZerosINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpAbsISubINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpAbsUSubINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpIAddSatINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpUAddSatINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpIAverageINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpUAverageINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpIAverageRoundedINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpUAverageRoundedINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpISubSatINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpUSubSatINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpIMul32x16INTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpUMul32x16INTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpConstantFunctionPointerINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpFunctionPointerCallINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpAsmTargetINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpAsmINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpAsmCallINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpAtomicFMinEXT: *hasResult = true; *hasResultType = true; break;+    case SpvOpAtomicFMaxEXT: *hasResult = true; *hasResultType = true; break;+    case SpvOpAssumeTrueKHR: *hasResult = false; *hasResultType = false; break;+    case SpvOpExpectKHR: *hasResult = true; *hasResultType = true; break;+    case SpvOpDecorateString: *hasResult = false; *hasResultType = false; break;+    case SpvOpMemberDecorateString: *hasResult = false; *hasResultType = false; break;+    case SpvOpVmeImageINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpTypeVmeImageINTEL: *hasResult = true; *hasResultType = false; break;+    case SpvOpTypeAvcImePayloadINTEL: *hasResult = true; *hasResultType = false; break;+    case SpvOpTypeAvcRefPayloadINTEL: *hasResult = true; *hasResultType = false; break;+    case SpvOpTypeAvcSicPayloadINTEL: *hasResult = true; *hasResultType = false; break;+    case SpvOpTypeAvcMcePayloadINTEL: *hasResult = true; *hasResultType = false; break;+    case SpvOpTypeAvcMceResultINTEL: *hasResult = true; *hasResultType = false; break;+    case SpvOpTypeAvcImeResultINTEL: *hasResult = true; *hasResultType = false; break;+    case SpvOpTypeAvcImeResultSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = false; break;+    case SpvOpTypeAvcImeResultDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = false; break;+    case SpvOpTypeAvcImeSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = false; break;+    case SpvOpTypeAvcImeDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = false; break;+    case SpvOpTypeAvcRefResultINTEL: *hasResult = true; *hasResultType = false; break;+    case SpvOpTypeAvcSicResultINTEL: *hasResult = true; *hasResultType = false; break;+    case SpvOpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcMceSetInterShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcMceSetInterDirectionPenaltyINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcMceSetMotionVectorCostFunctionINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcMceSetAcOnlyHaarINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcMceConvertToImePayloadINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcMceConvertToImeResultINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcMceConvertToRefPayloadINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcMceConvertToRefResultINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcMceConvertToSicPayloadINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcMceConvertToSicResultINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcMceGetMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcMceGetInterDistortionsINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcMceGetBestInterDistortionsINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcMceGetInterMajorShapeINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcMceGetInterMinorShapeINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcMceGetInterDirectionsINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcMceGetInterMotionVectorCountINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcMceGetInterReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcImeInitializeINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcImeSetSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcImeSetDualReferenceINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcImeRefWindowSizeINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcImeAdjustRefOffsetINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcImeConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcImeSetMaxMotionVectorCountINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcImeSetUnidirectionalMixDisableINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcImeSetWeightedSadINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcImeEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcImeEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcImeConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcImeGetSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcImeGetDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcImeStripSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcImeStripDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcImeGetBorderReachedINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcImeGetTruncatedSearchIndicationINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcFmeInitializeINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcBmeInitializeINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcRefConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcRefSetBidirectionalMixDisableINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcRefSetBilinearFilterEnableINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcRefEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcRefEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcRefEvaluateWithMultiReferenceINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcRefConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcSicInitializeINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcSicConfigureSkcINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcSicConfigureIpeLumaINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcSicConfigureIpeLumaChromaINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcSicGetMotionVectorMaskINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcSicConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcSicSetBilinearFilterEnableINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcSicSetSkcForwardTransformEnableINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcSicEvaluateIpeINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcSicEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcSicEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcSicEvaluateWithMultiReferenceINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcSicConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcSicGetIpeLumaShapeINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcSicGetBestIpeLumaDistortionINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcSicGetBestIpeChromaDistortionINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcSicGetPackedIpeLumaModesINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcSicGetIpeChromaModeINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSubgroupAvcSicGetInterRawSadsINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpVariableLengthArrayINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpSaveMemoryINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpRestoreMemoryINTEL: *hasResult = false; *hasResultType = false; break;+    case SpvOpArbitraryFloatSinCosPiINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpArbitraryFloatCastINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpArbitraryFloatCastFromIntINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpArbitraryFloatCastToIntINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpArbitraryFloatAddINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpArbitraryFloatSubINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpArbitraryFloatMulINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpArbitraryFloatDivINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpArbitraryFloatGTINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpArbitraryFloatGEINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpArbitraryFloatLTINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpArbitraryFloatLEINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpArbitraryFloatEQINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpArbitraryFloatRecipINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpArbitraryFloatRSqrtINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpArbitraryFloatCbrtINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpArbitraryFloatHypotINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpArbitraryFloatSqrtINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpArbitraryFloatLogINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpArbitraryFloatLog2INTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpArbitraryFloatLog10INTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpArbitraryFloatLog1pINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpArbitraryFloatExpINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpArbitraryFloatExp2INTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpArbitraryFloatExp10INTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpArbitraryFloatExpm1INTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpArbitraryFloatSinINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpArbitraryFloatCosINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpArbitraryFloatSinCosINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpArbitraryFloatSinPiINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpArbitraryFloatCosPiINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpArbitraryFloatASinINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpArbitraryFloatASinPiINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpArbitraryFloatACosINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpArbitraryFloatACosPiINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpArbitraryFloatATanINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpArbitraryFloatATanPiINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpArbitraryFloatATan2INTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpArbitraryFloatPowINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpArbitraryFloatPowRINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpArbitraryFloatPowNINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpLoopControlINTEL: *hasResult = false; *hasResultType = false; break;+    case SpvOpAliasDomainDeclINTEL: *hasResult = true; *hasResultType = false; break;+    case SpvOpAliasScopeDeclINTEL: *hasResult = true; *hasResultType = false; break;+    case SpvOpAliasScopeListDeclINTEL: *hasResult = true; *hasResultType = false; break;+    case SpvOpFixedSqrtINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpFixedRecipINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpFixedRsqrtINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpFixedSinINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpFixedCosINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpFixedSinCosINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpFixedSinPiINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpFixedCosPiINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpFixedSinCosPiINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpFixedLogINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpFixedExpINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpPtrCastToCrossWorkgroupINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpCrossWorkgroupCastToPtrINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpReadPipeBlockingINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpWritePipeBlockingINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpFPGARegINTEL: *hasResult = true; *hasResultType = true; break;+    case SpvOpRayQueryGetRayTMinKHR: *hasResult = true; *hasResultType = true; break;+    case SpvOpRayQueryGetRayFlagsKHR: *hasResult = true; *hasResultType = true; break;+    case SpvOpRayQueryGetIntersectionTKHR: *hasResult = true; *hasResultType = true; break;+    case SpvOpRayQueryGetIntersectionInstanceCustomIndexKHR: *hasResult = true; *hasResultType = true; break;+    case SpvOpRayQueryGetIntersectionInstanceIdKHR: *hasResult = true; *hasResultType = true; break;+    case SpvOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR: *hasResult = true; *hasResultType = true; break;+    case SpvOpRayQueryGetIntersectionGeometryIndexKHR: *hasResult = true; *hasResultType = true; break;+    case SpvOpRayQueryGetIntersectionPrimitiveIndexKHR: *hasResult = true; *hasResultType = true; break;+    case SpvOpRayQueryGetIntersectionBarycentricsKHR: *hasResult = true; *hasResultType = true; break;+    case SpvOpRayQueryGetIntersectionFrontFaceKHR: *hasResult = true; *hasResultType = true; break;+    case SpvOpRayQueryGetIntersectionCandidateAABBOpaqueKHR: *hasResult = true; *hasResultType = true; break;+    case SpvOpRayQueryGetIntersectionObjectRayDirectionKHR: *hasResult = true; *hasResultType = true; break;+    case SpvOpRayQueryGetIntersectionObjectRayOriginKHR: *hasResult = true; *hasResultType = true; break;+    case SpvOpRayQueryGetWorldRayDirectionKHR: *hasResult = true; *hasResultType = true; break;+    case SpvOpRayQueryGetWorldRayOriginKHR: *hasResult = true; *hasResultType = true; break;+    case SpvOpRayQueryGetIntersectionObjectToWorldKHR: *hasResult = true; *hasResultType = true; break;+    case SpvOpRayQueryGetIntersectionWorldToObjectKHR: *hasResult = true; *hasResultType = true; break;+    case SpvOpAtomicFAddEXT: *hasResult = true; *hasResultType = true; break;+    case SpvOpTypeBufferSurfaceINTEL: *hasResult = true; *hasResultType = false; break;+    case SpvOpTypeStructContinuedINTEL: *hasResult = false; *hasResultType = false; break;+    case SpvOpConstantCompositeContinuedINTEL: *hasResult = false; *hasResultType = false; break;+    case SpvOpSpecConstantCompositeContinuedINTEL: *hasResult = false; *hasResultType = false; break;+    case SpvOpControlBarrierArriveINTEL: *hasResult = false; *hasResultType = false; break;+    case SpvOpControlBarrierWaitINTEL: *hasResult = false; *hasResultType = false; break;+    case SpvOpGroupIMulKHR: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupFMulKHR: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupBitwiseAndKHR: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupBitwiseOrKHR: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupBitwiseXorKHR: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupLogicalAndKHR: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupLogicalOrKHR: *hasResult = true; *hasResultType = true; break;+    case SpvOpGroupLogicalXorKHR: *hasResult = true; *hasResultType = true; break;+    }+}+#endif /* SPV_ENABLE_UTILITY_CODE */++#endif
+ cbits/spirv_reflect.c view
@@ -0,0 +1,5097 @@+/*+ Copyright 2017-2022 Google Inc.++ Licensed under the Apache License, Version 2.0 (the "License");+ you may not use this file except in compliance with the License.+ You may obtain a copy of the License at++ http://www.apache.org/licenses/LICENSE-2.0++ Unless required by applicable law or agreed to in writing, software+ distributed under the License is distributed on an "AS IS" BASIS,+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+ See the License for the specific language governing permissions and+ limitations under the License.+*/++#include "spirv_reflect.h"+#include <assert.h>+#include <stdbool.h>+#include <string.h>++#if defined(WIN32)+  #define _CRTDBG_MAP_ALLOC+  #include <stdlib.h>+  #include <crtdbg.h>+#else+  #include <stdlib.h>+#endif++#if defined(SPIRV_REFLECT_ENABLE_ASSERTS)+  #define SPV_REFLECT_ASSERT(COND) \+    assert(COND);+#else+#define SPV_REFLECT_ASSERT(COND)+#endif++// Temporary enums until these make it into SPIR-V/Vulkan+// clang-format off+enum {+  SpvReflectOpDecorateId                      = 332,+  SpvReflectOpDecorateStringGOOGLE            = 5632,+  SpvReflectOpMemberDecorateStringGOOGLE      = 5633,+  SpvReflectDecorationHlslCounterBufferGOOGLE = 5634,+  SpvReflectDecorationHlslSemanticGOOGLE      = 5635+};+// clang-format on++// clang-format off+enum {+  SPIRV_STARTING_WORD_INDEX       = 5,+  SPIRV_WORD_SIZE                 = sizeof(uint32_t),+  SPIRV_BYTE_WIDTH                = 8,+  SPIRV_MINIMUM_FILE_SIZE         = SPIRV_STARTING_WORD_INDEX * SPIRV_WORD_SIZE,+  SPIRV_DATA_ALIGNMENT            = 4 * SPIRV_WORD_SIZE, // 16+  SPIRV_ACCESS_CHAIN_INDEX_OFFSET = 4,+};+// clang-format on++// clang-format off+enum {+  INVALID_VALUE  = 0xFFFFFFFF,+};+// clang-format on++// clang-format off+enum {+  MAX_NODE_NAME_LENGTH      = 1024,+};+// clang-format on++// clang-format off+enum {+  IMAGE_SAMPLED = 1,+  IMAGE_STORAGE = 2+};+// clang-format on++// clang-format off+typedef struct SpvReflectPrvArrayTraits {+  uint32_t                        element_type_id;+  uint32_t                        length_id;+} SpvReflectPrvArrayTraits;+// clang-format on++// clang-format off+typedef struct SpvReflectPrvImageTraits {+  uint32_t                        sampled_type_id;+  SpvDim                          dim;+  uint32_t                        depth;+  uint32_t                        arrayed;+  uint32_t                        ms;+  uint32_t                        sampled;+  SpvImageFormat                  image_format;+} SpvReflectPrvImageTraits;+// clang-format on++// clang-format off+typedef struct SpvReflectPrvNumberDecoration {+  uint32_t                        word_offset;+  uint32_t                        value;+} SpvReflectPrvNumberDecoration;+// clang-format on++// clang-format off+typedef struct SpvReflectPrvStringDecoration {+  uint32_t                        word_offset;+  const char*                     value;+} SpvReflectPrvStringDecoration;+// clang-format on++// clang-format off+typedef struct SpvReflectPrvDecorations {+  bool                            is_relaxed_precision;+  bool                            is_block;+  bool                            is_buffer_block;+  bool                            is_row_major;+  bool                            is_column_major;+  bool                            is_built_in;+  bool                            is_noperspective;+  bool                            is_flat;+  bool                            is_non_writable;+  bool                            is_non_readable;+  SpvReflectPrvNumberDecoration   set;+  SpvReflectPrvNumberDecoration   binding;+  SpvReflectPrvNumberDecoration   input_attachment_index;+  SpvReflectPrvNumberDecoration   location;+  SpvReflectPrvNumberDecoration   offset;+  SpvReflectPrvNumberDecoration   uav_counter_buffer;+  SpvReflectPrvStringDecoration   semantic;+  uint32_t                        array_stride;+  uint32_t                        matrix_stride;+  SpvBuiltIn                      built_in;+} SpvReflectPrvDecorations;+// clang-format on++// clang-format off+typedef struct SpvReflectPrvNode {+  uint32_t                        result_id;+  SpvOp                           op;+  uint32_t                        result_type_id;+  uint32_t                        type_id;+  SpvCapability                   capability;+  SpvStorageClass                 storage_class;+  uint32_t                        word_offset;+  uint32_t                        word_count;+  bool                            is_type;++  SpvReflectPrvArrayTraits        array_traits;+  SpvReflectPrvImageTraits        image_traits;+  uint32_t                        image_type_id;++  const char*                     name;+  SpvReflectPrvDecorations        decorations;+  uint32_t                        member_count;+  const char**                    member_names;+  SpvReflectPrvDecorations*       member_decorations;+} SpvReflectPrvNode;+// clang-format on++// clang-format off+typedef struct SpvReflectPrvString {+  uint32_t                        result_id;+  const char*                     string;+} SpvReflectPrvString;+// clang-format on++// clang-format off+typedef struct SpvReflectPrvFunction {+  uint32_t                        id;+  uint32_t                        callee_count;+  uint32_t*                       callees;+  struct SpvReflectPrvFunction**  callee_ptrs;+  uint32_t                        accessed_ptr_count;+  uint32_t*                       accessed_ptrs;+} SpvReflectPrvFunction;+// clang-format on++// clang-format off+typedef struct SpvReflectPrvAccessChain {+  uint32_t                        result_id;+  uint32_t                        result_type_id;+  //+  // Pointing to the base of a composite object.+  // Generally the id of descriptor block variable+  uint32_t                        base_id;+  // +  // From spec:+  //   The first index in Indexes will select the +  //   top-level member/element/component/element +  //   of the base composite+  uint32_t                        index_count;+  uint32_t*                       indexes;+} SpvReflectPrvAccessChain;+// clang-format on++// clang-format off+typedef struct SpvReflectPrvParser {+  size_t                          spirv_word_count;+  uint32_t*                       spirv_code;+  uint32_t                        string_count;+  SpvReflectPrvString*            strings;+  SpvSourceLanguage               source_language;+  uint32_t                        source_language_version;+  uint32_t                        source_file_id;+  const char*                     source_embedded;+  size_t                          node_count;+  SpvReflectPrvNode*              nodes;+  uint32_t                        entry_point_count;+  uint32_t                        capability_count;+  uint32_t                        function_count;+  SpvReflectPrvFunction*          functions;+  uint32_t                        access_chain_count;+  SpvReflectPrvAccessChain*       access_chains;++  uint32_t                        type_count;+  uint32_t                        descriptor_count;+  uint32_t                        push_constant_count;+} SpvReflectPrvParser;+// clang-format on++static uint32_t Max(+   uint32_t a, +   uint32_t b)+{+  return a > b ? a : b;+}++static uint32_t RoundUp(+   uint32_t value,+   uint32_t multiple)+{+  assert(multiple && ((multiple & (multiple - 1)) == 0));+  return (value + multiple - 1) & ~(multiple - 1);+}++#define IsNull(ptr) \+  (ptr == NULL)++#define IsNotNull(ptr) \+  (ptr != NULL)++#define SafeFree(ptr)  \+  {                    \+     free((void*)ptr); \+     ptr = NULL;       \+  }++static int SortCompareUint32(+  const void* a, +  const void* b)+{+  const uint32_t* p_a = (const uint32_t*)a;+  const uint32_t* p_b = (const uint32_t*)b;++  return (int)*p_a - (int)*p_b;+}++//+// De-duplicates a sorted array and returns the new size.+//+// Note: The array doesn't actually need to be sorted, just+// arranged into "runs" so that all the entries with one+// value are adjacent.+//+static size_t DedupSortedUint32(uint32_t* arr, size_t size)+{+  if (size == 0) {+    return 0;+  }+  size_t dedup_idx = 0;+  for (size_t i = 0; i < size; ++i) {+    if (arr[dedup_idx] != arr[i]) {+      ++dedup_idx;+      arr[dedup_idx] = arr[i];+    }+  }+  return dedup_idx+1;+}++static bool SearchSortedUint32(+  const uint32_t* arr, +  size_t          size, +  uint32_t        target)+{+  size_t lo = 0;+  size_t hi = size;+  while (lo < hi) {+    size_t mid = (hi - lo) / 2 + lo;+    if (arr[mid] == target) {+      return true;+    } else if (arr[mid] < target) {+      lo = mid+1;+    } else {+      hi = mid;+    }+  }+  return false;+}++static SpvReflectResult IntersectSortedUint32(+  const uint32_t* p_arr0, +  size_t          arr0_size,+  const uint32_t* p_arr1, +  size_t          arr1_size,+  uint32_t**      pp_res,+  size_t*         res_size+)+{+  *pp_res = NULL;+  *res_size = 0;+  if (IsNull(p_arr0) || IsNull(p_arr1)) {+    return SPV_REFLECT_RESULT_SUCCESS;+  }++  const uint32_t* arr0_end = p_arr0 + arr0_size;+  const uint32_t* arr1_end = p_arr1 + arr1_size;++  const uint32_t* idx0 = p_arr0;+  const uint32_t* idx1 = p_arr1;+  while (idx0 != arr0_end && idx1 != arr1_end) {+    if (*idx0 < *idx1) {+      ++idx0;+    } else if (*idx0 > *idx1) {+      ++idx1;+    } else {+      ++*res_size;+      ++idx0;+      ++idx1;+    }+  }++  if (*res_size > 0) {+    *pp_res = (uint32_t*)calloc(*res_size, sizeof(**pp_res));+    if (IsNull(*pp_res)) {+      return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;+    }+    uint32_t* idxr = *pp_res;+    idx0 = p_arr0;+    idx1 = p_arr1;+    while (idx0 != arr0_end && idx1 != arr1_end) {+      if (*idx0 < *idx1) {+        ++idx0;+      } else if (*idx0 > *idx1) {+        ++idx1;+      } else {+        *(idxr++) = *idx0;+        ++idx0;+        ++idx1;+      }+    }+  }+  return SPV_REFLECT_RESULT_SUCCESS;+}+++static bool InRange(+  const SpvReflectPrvParser* p_parser, +  uint32_t                   index)+{+  bool in_range = false;+  if (IsNotNull(p_parser)) {+    in_range = (index < p_parser->spirv_word_count);+  }+  return in_range;+}++static SpvReflectResult ReadU32(+  SpvReflectPrvParser* p_parser,+  uint32_t             word_offset,+  uint32_t*            p_value)+{+  assert(IsNotNull(p_parser));+  assert(IsNotNull(p_parser->spirv_code));+  assert(InRange(p_parser, word_offset));+  SpvReflectResult result = SPV_REFLECT_RESULT_ERROR_SPIRV_UNEXPECTED_EOF;+  if (IsNotNull(p_parser) && IsNotNull(p_parser->spirv_code) && InRange(p_parser, word_offset)) {+    *p_value = *(p_parser->spirv_code + word_offset);+    result = SPV_REFLECT_RESULT_SUCCESS;+  }+  return result;+}++#define CHECKED_READU32(parser, word_offset, value)                                      \+  {                                                                                      \+    SpvReflectResult checked_readu32_result = ReadU32(parser,                            \+                                                      word_offset, (uint32_t*)&(value)); \+    if (checked_readu32_result != SPV_REFLECT_RESULT_SUCCESS) {                          \+      return checked_readu32_result;                                                     \+    }                                                                                    \+  }++#define CHECKED_READU32_CAST(parser, word_offset, cast_to_type, value)         \+  {                                                                            \+    uint32_t checked_readu32_cast_u32 = UINT32_MAX;                            \+    SpvReflectResult checked_readu32_cast_result = ReadU32(parser,             \+                                      word_offset,                             \+                                      (uint32_t*)&(checked_readu32_cast_u32)); \+    if (checked_readu32_cast_result != SPV_REFLECT_RESULT_SUCCESS) {           \+      return checked_readu32_cast_result;                                      \+    }                                                                          \+    value = (cast_to_type)checked_readu32_cast_u32;                            \+  }++#define IF_READU32(result, parser, word_offset, value)          \+  if ((result) == SPV_REFLECT_RESULT_SUCCESS) {                 \+    result = ReadU32(parser, word_offset, (uint32_t*)&(value)); \+  }++#define IF_READU32_CAST(result, parser, word_offset, cast_to_type, value) \+  if ((result) == SPV_REFLECT_RESULT_SUCCESS) {                           \+    uint32_t if_readu32_cast_u32 = UINT32_MAX;                            \+    result = ReadU32(parser, word_offset, &if_readu32_cast_u32);          \+    if ((result) == SPV_REFLECT_RESULT_SUCCESS) {                         \+      value = (cast_to_type)if_readu32_cast_u32;                          \+    }                                                                     \+  }++static SpvReflectResult ReadStr(+  SpvReflectPrvParser* p_parser, +  uint32_t             word_offset, +  uint32_t             word_index, +  uint32_t             word_count,+  uint32_t*            p_buf_size, +  char*                p_buf+)+{+  uint32_t limit = (word_offset + word_count);+  assert(IsNotNull(p_parser));+  assert(IsNotNull(p_parser->spirv_code));+  assert(InRange(p_parser, limit));+  SpvReflectResult result = SPV_REFLECT_RESULT_ERROR_SPIRV_UNEXPECTED_EOF;+  if (IsNotNull(p_parser) && IsNotNull(p_parser->spirv_code) && InRange(p_parser, limit)) {+    const char* c_str = (const char*)(p_parser->spirv_code + word_offset + word_index);+    uint32_t n = word_count * SPIRV_WORD_SIZE;+    uint32_t length_with_terminator = 0;+    for (uint32_t i = 0; i < n; ++i) {+      char c = *(c_str + i);+      if (c == 0) {+        length_with_terminator = i + 1;+        break;+      }+    }++    if (length_with_terminator > 0) {+      result = SPV_REFLECT_RESULT_ERROR_NULL_POINTER;+      if (IsNotNull(p_buf_size) && IsNotNull(p_buf)) {+        result = SPV_REFLECT_RESULT_ERROR_RANGE_EXCEEDED;+        if (length_with_terminator <= *p_buf_size) {+          memset(p_buf, 0, *p_buf_size);+          memcpy(p_buf, c_str, length_with_terminator);+          result = SPV_REFLECT_RESULT_SUCCESS;+        }+      }+      else {+        if (IsNotNull(p_buf_size)) {+          *p_buf_size = length_with_terminator;+          result = SPV_REFLECT_RESULT_SUCCESS;+        }+      }+    }+  }+  return result;+}++static SpvReflectDecorationFlags ApplyDecorations(const SpvReflectPrvDecorations* p_decoration_fields)+{+  SpvReflectDecorationFlags decorations = SPV_REFLECT_DECORATION_NONE;+  if (p_decoration_fields->is_relaxed_precision) {+    decorations |= SPV_REFLECT_DECORATION_RELAXED_PRECISION;+  }+  if (p_decoration_fields->is_block) {+    decorations |= SPV_REFLECT_DECORATION_BLOCK;+  }+  if (p_decoration_fields->is_buffer_block) {+    decorations |= SPV_REFLECT_DECORATION_BUFFER_BLOCK;+  }+  if (p_decoration_fields->is_row_major) {+    decorations |= SPV_REFLECT_DECORATION_ROW_MAJOR;+  }+  if (p_decoration_fields->is_column_major) {+    decorations |= SPV_REFLECT_DECORATION_COLUMN_MAJOR;+  }+  if (p_decoration_fields->is_built_in) {+    decorations |= SPV_REFLECT_DECORATION_BUILT_IN;+  }+  if (p_decoration_fields->is_noperspective) {+    decorations |= SPV_REFLECT_DECORATION_NOPERSPECTIVE;+  }+  if (p_decoration_fields->is_flat) {+    decorations |= SPV_REFLECT_DECORATION_FLAT;+  }+  if (p_decoration_fields->is_non_writable) {+    decorations |= SPV_REFLECT_DECORATION_NON_WRITABLE;+  }+  if (p_decoration_fields->is_non_readable) {+    decorations |= SPV_REFLECT_DECORATION_NON_READABLE;+  }+  return decorations;+}++static void ApplyNumericTraits(const SpvReflectTypeDescription* p_type, SpvReflectNumericTraits* p_numeric_traits)+{+  memcpy(p_numeric_traits, &p_type->traits.numeric, sizeof(p_type->traits.numeric));+}++static void ApplyArrayTraits(const SpvReflectTypeDescription* p_type, SpvReflectArrayTraits* p_array_traits)+{+  memcpy(p_array_traits, &p_type->traits.array, sizeof(p_type->traits.array));+}++static SpvReflectPrvNode* FindNode(+  SpvReflectPrvParser* p_parser,+  uint32_t             result_id)+{+  SpvReflectPrvNode* p_node = NULL;+  for (size_t i = 0; i < p_parser->node_count; ++i) {+    SpvReflectPrvNode* p_elem = &(p_parser->nodes[i]);+    if (p_elem->result_id == result_id) {+      p_node = p_elem;+      break;+    }+  }+  return p_node;+}++static SpvReflectTypeDescription* FindType(SpvReflectShaderModule* p_module, uint32_t type_id)+{+  SpvReflectTypeDescription* p_type = NULL;+  for (size_t i = 0; i < p_module->_internal->type_description_count; ++i) {+    SpvReflectTypeDescription* p_elem = &(p_module->_internal->type_descriptions[i]);+    if (p_elem->id == type_id) {+      p_type = p_elem;+      break;+    }+  }+  return p_type;+}++static SpvReflectResult CreateParser(+  size_t               size, +  void*                p_code, +  SpvReflectPrvParser* p_parser)+{+  if (p_code == NULL) {+    return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;+  }++  if (size < SPIRV_MINIMUM_FILE_SIZE) {+    return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_CODE_SIZE;+  }+  if ((size % 4) != 0) {+    return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_CODE_SIZE;+  }++  p_parser->spirv_word_count = size / SPIRV_WORD_SIZE;+  p_parser->spirv_code = (uint32_t*)p_code;++  if (p_parser->spirv_code[0] != SpvMagicNumber) {+    return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_MAGIC_NUMBER;+  }++  return SPV_REFLECT_RESULT_SUCCESS;+}++static void DestroyParser(SpvReflectPrvParser* p_parser)+{+  if (!IsNull(p_parser->nodes)) {+    // Free nodes+    for (size_t i = 0; i < p_parser->node_count; ++i) {+      SpvReflectPrvNode* p_node = &(p_parser->nodes[i]);+      if (IsNotNull(p_node->member_names)) {+        SafeFree(p_node->member_names);+      }+      if (IsNotNull(p_node->member_decorations)) {+        SafeFree(p_node->member_decorations);+      }+    }++    // Free functions+    for (size_t i = 0; i < p_parser->function_count; ++i) {+      SafeFree(p_parser->functions[i].callees);+      SafeFree(p_parser->functions[i].callee_ptrs);+      SafeFree(p_parser->functions[i].accessed_ptrs);+    }++    // Free access chains+    for (uint32_t i = 0; i < p_parser->access_chain_count; ++i) {+      SafeFree(p_parser->access_chains[i].indexes);+    }++    SafeFree(p_parser->nodes);+    SafeFree(p_parser->strings);+    SafeFree(p_parser->source_embedded);+    SafeFree(p_parser->functions);+    SafeFree(p_parser->access_chains);+    p_parser->node_count = 0;+  }+}++static SpvReflectResult ParseNodes(SpvReflectPrvParser* p_parser)+{+  assert(IsNotNull(p_parser));+  assert(IsNotNull(p_parser->spirv_code));++  uint32_t* p_spirv = p_parser->spirv_code;+  uint32_t spirv_word_index = SPIRV_STARTING_WORD_INDEX;++  // Count nodes+  uint32_t node_count = 0;+  while (spirv_word_index < p_parser->spirv_word_count) {+    uint32_t word = p_spirv[spirv_word_index];+    SpvOp op = (SpvOp)(word & 0xFFFF);+    uint32_t node_word_count = (word >> 16) & 0xFFFF;+    if (node_word_count == 0) {+      return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_INSTRUCTION;+    }+    if (op == SpvOpAccessChain) {+      ++(p_parser->access_chain_count);+    }+    spirv_word_index += node_word_count;+    ++node_count;+  }++  if (node_count == 0) {+    return SPV_REFLECT_RESULT_ERROR_SPIRV_UNEXPECTED_EOF;+  }++  // Allocate nodes+  p_parser->node_count = node_count;+  p_parser->nodes = (SpvReflectPrvNode*)calloc(p_parser->node_count, sizeof(*(p_parser->nodes)));+  if (IsNull(p_parser->nodes)) {+    return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;+  }+  // Mark all nodes with an invalid state+  for (uint32_t i = 0; i < node_count; ++i) {+    p_parser->nodes[i].op = (SpvOp)INVALID_VALUE;+    p_parser->nodes[i].storage_class = (SpvStorageClass)INVALID_VALUE;+    p_parser->nodes[i].decorations.set.value = (uint32_t)INVALID_VALUE;+    p_parser->nodes[i].decorations.binding.value = (uint32_t)INVALID_VALUE;+    p_parser->nodes[i].decorations.location.value = (uint32_t)INVALID_VALUE;+    p_parser->nodes[i].decorations.offset.value = (uint32_t)INVALID_VALUE;+    p_parser->nodes[i].decorations.uav_counter_buffer.value = (uint32_t)INVALID_VALUE;+    p_parser->nodes[i].decorations.built_in = (SpvBuiltIn)INVALID_VALUE;+  }+  // Mark source file id node+  p_parser->source_file_id = (uint32_t)INVALID_VALUE;+  p_parser->source_embedded = NULL;++  // Function node+  uint32_t function_node = (uint32_t)INVALID_VALUE;++  // Allocate access chain+  if (p_parser->access_chain_count > 0) {+    p_parser->access_chains = (SpvReflectPrvAccessChain*)calloc(p_parser->access_chain_count, sizeof(*(p_parser->access_chains)));+    if (IsNull(p_parser->access_chains)) {+      return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;+    }+  }++  // Parse nodes+  uint32_t node_index = 0;+  uint32_t access_chain_index = 0;+  spirv_word_index = SPIRV_STARTING_WORD_INDEX;+  while (spirv_word_index < p_parser->spirv_word_count) {+    uint32_t word = p_spirv[spirv_word_index];+    SpvOp op = (SpvOp)(word & 0xFFFF);+    uint32_t node_word_count = (word >> 16) & 0xFFFF;++    SpvReflectPrvNode* p_node = &(p_parser->nodes[node_index]);+    p_node->op = op;+    p_node->word_offset = spirv_word_index;+    p_node->word_count = node_word_count;++    switch (p_node->op) {+      default: break;++      case SpvOpString: {+        ++(p_parser->string_count);+      }+      break;++      case SpvOpSource: {+        CHECKED_READU32_CAST(p_parser, p_node->word_offset + 1, SpvSourceLanguage, p_parser->source_language);+        CHECKED_READU32(p_parser, p_node->word_offset + 2, p_parser->source_language_version);+        if (p_node->word_count >= 4) {+          CHECKED_READU32(p_parser, p_node->word_offset + 3, p_parser->source_file_id);+        }+        if (p_node->word_count >= 5) {+          const char* p_source = (const char*)(p_parser->spirv_code + p_node->word_offset + 4);++          const size_t source_len = strlen(p_source);+          char* p_source_temp = (char*)calloc(source_len + 1, sizeof(char*));++          if (IsNull(p_source_temp)) {+            return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;+          }++      #ifdef _WIN32+          strcpy_s(p_source_temp, source_len + 1, p_source);+      #else+          strcpy(p_source_temp, p_source);+      #endif++          p_parser->source_embedded = p_source_temp;+        }+      }+      break;++      case SpvOpSourceContinued: {+        const char* p_source = (const char*)(p_parser->spirv_code + p_node->word_offset + 1);++        const size_t source_len = strlen(p_source);+        const size_t embedded_source_len = strlen(p_parser->source_embedded); +        char* p_continued_source = (char*)calloc(source_len + embedded_source_len + 1, sizeof(char*));++        if (IsNull(p_continued_source)) {+          return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;+        }++    #ifdef _WIN32+        strcpy_s(p_continued_source, embedded_source_len + 1, p_parser->source_embedded);+        strcat_s(p_continued_source, source_len + 1, p_source);+    #else+        strcpy(p_continued_source, p_parser->source_embedded);+        strcat(p_continued_source, p_source);+    #endif++        SafeFree(p_parser->source_embedded);+        p_parser->source_embedded = p_continued_source;+      }+      break;++      case SpvOpEntryPoint: {+        ++(p_parser->entry_point_count);+      }+      break;++      case SpvOpCapability: {+        CHECKED_READU32(p_parser, p_node->word_offset + 1, p_node->capability);+        ++(p_parser->capability_count);+      }+      break;++      case SpvOpName:+      case SpvOpMemberName:+      {+        uint32_t member_offset = (p_node->op == SpvOpMemberName) ? 1 : 0;+        uint32_t name_start = p_node->word_offset + member_offset + 2;+        p_node->name = (const char*)(p_parser->spirv_code + name_start);+      }+      break;++      case SpvOpTypeStruct:+      {+        p_node->member_count = p_node->word_count - 2;+      } // Fall through+      case SpvOpTypeVoid:+      case SpvOpTypeBool:+      case SpvOpTypeInt:+      case SpvOpTypeFloat:+      case SpvOpTypeVector:+      case SpvOpTypeMatrix:+      case SpvOpTypeSampler:+      case SpvOpTypeOpaque:+      case SpvOpTypeFunction:+      case SpvOpTypeEvent:+      case SpvOpTypeDeviceEvent:+      case SpvOpTypeReserveId:+      case SpvOpTypeQueue:+      case SpvOpTypePipe:+      case SpvOpTypeAccelerationStructureKHR:+      case SpvOpTypeRayQueryKHR:+      {+        CHECKED_READU32(p_parser, p_node->word_offset + 1, p_node->result_id);+        p_node->is_type = true;+      }+      break;++      case SpvOpTypeImage: {+        CHECKED_READU32(p_parser, p_node->word_offset + 1, p_node->result_id);+        CHECKED_READU32(p_parser, p_node->word_offset + 2, p_node->image_traits.sampled_type_id);+        CHECKED_READU32(p_parser, p_node->word_offset + 3, p_node->image_traits.dim);+        CHECKED_READU32(p_parser, p_node->word_offset + 4, p_node->image_traits.depth);+        CHECKED_READU32(p_parser, p_node->word_offset + 5, p_node->image_traits.arrayed);+        CHECKED_READU32(p_parser, p_node->word_offset + 6, p_node->image_traits.ms);+        CHECKED_READU32(p_parser, p_node->word_offset + 7, p_node->image_traits.sampled);+        CHECKED_READU32(p_parser, p_node->word_offset + 8, p_node->image_traits.image_format);+        p_node->is_type = true;+      }+      break;++      case SpvOpTypeSampledImage: {+        CHECKED_READU32(p_parser, p_node->word_offset + 1, p_node->result_id);+        CHECKED_READU32(p_parser, p_node->word_offset + 2, p_node->image_type_id);+        p_node->is_type = true;+      }+      break;++      case SpvOpTypeArray:  {+        CHECKED_READU32(p_parser, p_node->word_offset + 1, p_node->result_id);+        CHECKED_READU32(p_parser, p_node->word_offset + 2, p_node->array_traits.element_type_id);+        CHECKED_READU32(p_parser, p_node->word_offset + 3, p_node->array_traits.length_id);+        p_node->is_type = true;+      }+      break;++      case SpvOpTypeRuntimeArray:  {+        CHECKED_READU32(p_parser, p_node->word_offset + 1, p_node->result_id);+        CHECKED_READU32(p_parser, p_node->word_offset + 2, p_node->array_traits.element_type_id);+        p_node->is_type = true;+      }+      break;++      case SpvOpTypePointer: {+        CHECKED_READU32(p_parser, p_node->word_offset + 1, p_node->result_id);+        CHECKED_READU32(p_parser, p_node->word_offset + 2, p_node->storage_class);+        CHECKED_READU32(p_parser, p_node->word_offset + 3, p_node->type_id);+        p_node->is_type = true;+      }+      break;++      case SpvOpTypeForwardPointer:+      {+        CHECKED_READU32(p_parser, p_node->word_offset + 1, p_node->result_id);+        CHECKED_READU32(p_parser, p_node->word_offset + 2, p_node->storage_class);+        p_node->is_type = true;+      }+      break;++      case SpvOpConstantTrue:+      case SpvOpConstantFalse:+      case SpvOpConstant:+      case SpvOpConstantComposite:+      case SpvOpConstantSampler:+      case SpvOpConstantNull: {+        CHECKED_READU32(p_parser, p_node->word_offset + 1, p_node->result_type_id);+        CHECKED_READU32(p_parser, p_node->word_offset + 2, p_node->result_id);+      }+      break;++      case SpvOpSpecConstantTrue:+      case SpvOpSpecConstantFalse:+      case SpvOpSpecConstant:+      case SpvOpSpecConstantComposite:+      case SpvOpSpecConstantOp: {+        CHECKED_READU32(p_parser, p_node->word_offset + 1, p_node->result_type_id);+        CHECKED_READU32(p_parser, p_node->word_offset + 2, p_node->result_id);+      }+      break;++      case SpvOpVariable:+      {+        CHECKED_READU32(p_parser, p_node->word_offset + 1, p_node->type_id);+        CHECKED_READU32(p_parser, p_node->word_offset + 2, p_node->result_id);+        CHECKED_READU32(p_parser, p_node->word_offset + 3, p_node->storage_class);+      }+      break;++      case SpvOpLoad:+      {+        // Only load enough so OpDecorate can reference the node, skip the remaining operands.+        CHECKED_READU32(p_parser, p_node->word_offset + 1, p_node->result_type_id);+        CHECKED_READU32(p_parser, p_node->word_offset + 2, p_node->result_id);+      }+      break;++      case SpvOpAccessChain:+      {+        SpvReflectPrvAccessChain* p_access_chain = &(p_parser->access_chains[access_chain_index]);+        CHECKED_READU32(p_parser, p_node->word_offset + 1, p_access_chain->result_type_id);+        CHECKED_READU32(p_parser, p_node->word_offset + 2, p_access_chain->result_id);+        CHECKED_READU32(p_parser, p_node->word_offset + 3, p_access_chain->base_id);+        //+        // SPIRV_ACCESS_CHAIN_INDEX_OFFSET (4) is the number of words up until the first index:+        //   [Node, Result Type Id, Result Id, Base Id, <Indexes>]+        //+        p_access_chain->index_count = (node_word_count - SPIRV_ACCESS_CHAIN_INDEX_OFFSET);+        if (p_access_chain->index_count > 0) {+          p_access_chain->indexes = (uint32_t*)calloc(p_access_chain->index_count, sizeof(*(p_access_chain->indexes)));+          if (IsNull( p_access_chain->indexes)) {+            return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;+          }+          // Parse any index values for access chain+          for (uint32_t index_index = 0; index_index < p_access_chain->index_count; ++index_index) {+            // Read index id+            uint32_t index_id = 0;+            CHECKED_READU32(p_parser, p_node->word_offset + SPIRV_ACCESS_CHAIN_INDEX_OFFSET + index_index, index_id);+            // Find OpConstant node that contains index value+            SpvReflectPrvNode* p_index_value_node = FindNode(p_parser, index_id);+            if ((p_index_value_node != NULL) && (p_index_value_node->op == SpvOpConstant)) {+              // Read index value+              uint32_t index_value = UINT32_MAX;+              CHECKED_READU32(p_parser, p_index_value_node->word_offset + 3, index_value);+              assert(index_value != UINT32_MAX);+              // Write index value to array+              p_access_chain->indexes[index_index] = index_value;+            }+          }+        }+        ++access_chain_index;+      }+      break;++      case SpvOpFunction:+      {+        CHECKED_READU32(p_parser, p_node->word_offset + 2, p_node->result_id);+        // Count function definitions, not function declarations.  To determine+        // the difference, set an in-function variable, and then if an OpLabel+        // is reached before the end of the function increment the function+        // count.+        function_node = node_index;+      }+      break;++      case SpvOpLabel:+      {+        if (function_node != (uint32_t)INVALID_VALUE) {+          SpvReflectPrvNode* p_func_node = &(p_parser->nodes[function_node]);+          CHECKED_READU32(p_parser, p_func_node->word_offset + 2, p_func_node->result_id);+          ++(p_parser->function_count);+        }+      } // Fall through++      case SpvOpFunctionEnd:+      {+        function_node = (uint32_t)INVALID_VALUE;+      }+      break;+    }++    if (p_node->is_type) {+      ++(p_parser->type_count);+    }++    spirv_word_index += node_word_count;+    ++node_index;+  }++  return SPV_REFLECT_RESULT_SUCCESS;+}++static SpvReflectResult ParseStrings(SpvReflectPrvParser* p_parser)+{+  assert(IsNotNull(p_parser));+  assert(IsNotNull(p_parser->spirv_code));+  assert(IsNotNull(p_parser->nodes));++  // Early out+  if (p_parser->string_count == 0) {+    return SPV_REFLECT_RESULT_SUCCESS;+  }++  if (IsNotNull(p_parser) && IsNotNull(p_parser->spirv_code) && IsNotNull(p_parser->nodes)) {+    // Allocate string storage+    p_parser->strings = (SpvReflectPrvString*)calloc(p_parser->string_count, sizeof(*(p_parser->strings)));  ++    uint32_t string_index = 0;+    for (size_t i = 0; i < p_parser->node_count; ++i) {+      SpvReflectPrvNode* p_node = &(p_parser->nodes[i]);+      if (p_node->op != SpvOpString) {+        continue;+      }++      // Paranoid check against string count+      assert(string_index < p_parser->string_count);+      if (string_index >= p_parser->string_count) {+        return SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH;+      }++      // Result id+      SpvReflectPrvString* p_string = &(p_parser->strings[string_index]);+      CHECKED_READU32(p_parser, p_node->word_offset + 1, p_string->result_id);++      // String+      uint32_t string_start = p_node->word_offset + 2;+      p_string->string = (const char*)(p_parser->spirv_code + string_start);++      // Increment string index+      ++string_index;+    }+  }+  +  return SPV_REFLECT_RESULT_SUCCESS;+}++static SpvReflectResult ParseSource(SpvReflectPrvParser* p_parser, SpvReflectShaderModule* p_module)+{+  assert(IsNotNull(p_parser));+  assert(IsNotNull(p_parser->spirv_code));++  if (IsNotNull(p_parser) && IsNotNull(p_parser->spirv_code)) {+    // Source file+    if (IsNotNull(p_parser->strings)) {+      for (uint32_t i = 0; i < p_parser->string_count; ++i) {+        SpvReflectPrvString* p_string = &(p_parser->strings[i]);+        if (p_string->result_id == p_parser->source_file_id) {+          p_module->source_file = p_string->string;+          break;+        }+      }+    }++    //Source code+    if (IsNotNull(p_parser->source_embedded))+    {+      const size_t source_len = strlen(p_parser->source_embedded);+      char* p_source = (char*)calloc(source_len + 1, sizeof(char*));++      if (IsNull(p_source)) {+        return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;+      }++    #ifdef _WIN32+      strcpy_s(p_source, source_len + 1, p_parser->source_embedded);+    #else+      strcpy(p_source, p_parser->source_embedded);+    #endif++      p_module->source_source = p_source;+    }+  }++  return SPV_REFLECT_RESULT_SUCCESS;+}++static SpvReflectResult ParseFunction(+  SpvReflectPrvParser*   p_parser, +  SpvReflectPrvNode*     p_func_node, +  SpvReflectPrvFunction* p_func, +  size_t                 first_label_index)+{+  p_func->id = p_func_node->result_id;++  p_func->callee_count = 0;+  p_func->accessed_ptr_count = 0;++  for (size_t i = first_label_index; i < p_parser->node_count; ++i) {+    SpvReflectPrvNode* p_node = &(p_parser->nodes[i]);+    if (p_node->op == SpvOpFunctionEnd) {+      break;+    }+    switch (p_node->op) {+      case SpvOpFunctionCall: {+        ++(p_func->callee_count);+      }+      break;+      case SpvOpLoad:+      case SpvOpAccessChain:+      case SpvOpInBoundsAccessChain:+      case SpvOpPtrAccessChain:+      case SpvOpArrayLength:+      case SpvOpGenericPtrMemSemantics:+      case SpvOpInBoundsPtrAccessChain:+      case SpvOpStore:+      case SpvOpImageTexelPointer:+      {+        ++(p_func->accessed_ptr_count);+      }+      break;+      case SpvOpCopyMemory:+      case SpvOpCopyMemorySized:+      {+        p_func->accessed_ptr_count += 2;+      }+      break;+      default: break;+    }+  }++  if (p_func->callee_count > 0) {+    p_func->callees = (uint32_t*)calloc(p_func->callee_count,+                                        sizeof(*(p_func->callees)));+    if (IsNull(p_func->callees)) {+      return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;+    }+  }++  if (p_func->accessed_ptr_count > 0) {+    p_func->accessed_ptrs = (uint32_t*)calloc(p_func->accessed_ptr_count,+                                              sizeof(*(p_func->accessed_ptrs)));+    if (IsNull(p_func->accessed_ptrs)) {+      return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;+    }+  }++  p_func->callee_count = 0;+  p_func->accessed_ptr_count = 0;+  for (size_t i = first_label_index; i < p_parser->node_count; ++i) {+    SpvReflectPrvNode* p_node = &(p_parser->nodes[i]);+    if (p_node->op == SpvOpFunctionEnd) {+      break;+    }+    switch (p_node->op) {+      case SpvOpFunctionCall: {+        CHECKED_READU32(p_parser, p_node->word_offset + 3,+                        p_func->callees[p_func->callee_count]);+        (++p_func->callee_count);+      }+      break;+      case SpvOpLoad:+      case SpvOpAccessChain:+      case SpvOpInBoundsAccessChain:+      case SpvOpPtrAccessChain:+      case SpvOpArrayLength:+      case SpvOpGenericPtrMemSemantics:+      case SpvOpInBoundsPtrAccessChain:+      case SpvOpImageTexelPointer:+      {+        CHECKED_READU32(p_parser, p_node->word_offset + 3,+                        p_func->accessed_ptrs[p_func->accessed_ptr_count]);+        (++p_func->accessed_ptr_count);+      }+      break;+      case SpvOpStore:+      {+        CHECKED_READU32(p_parser, p_node->word_offset + 2,+                        p_func->accessed_ptrs[p_func->accessed_ptr_count]);+        (++p_func->accessed_ptr_count);+      }+      break;+      case SpvOpCopyMemory:+      case SpvOpCopyMemorySized:+      {+        CHECKED_READU32(p_parser, p_node->word_offset + 2,+                        p_func->accessed_ptrs[p_func->accessed_ptr_count]);+        (++p_func->accessed_ptr_count);+        CHECKED_READU32(p_parser, p_node->word_offset + 3,+                        p_func->accessed_ptrs[p_func->accessed_ptr_count]);+        (++p_func->accessed_ptr_count);+      }+      break;+      default: break;+    }+  }++  if (p_func->callee_count > 0) {+    qsort(p_func->callees, p_func->callee_count,+          sizeof(*(p_func->callees)), SortCompareUint32);+  }+  p_func->callee_count = (uint32_t)DedupSortedUint32(p_func->callees,+                                                     p_func->callee_count);++  if (p_func->accessed_ptr_count > 0) {+    qsort(p_func->accessed_ptrs, p_func->accessed_ptr_count,+          sizeof(*(p_func->accessed_ptrs)), SortCompareUint32);+  }+  p_func->accessed_ptr_count = (uint32_t)DedupSortedUint32(p_func->accessed_ptrs,+                                                           p_func->accessed_ptr_count);++  return SPV_REFLECT_RESULT_SUCCESS;+}++static int SortCompareFunctions(+  const void* a, +  const void* b)+{+  const SpvReflectPrvFunction* af = (const SpvReflectPrvFunction*)a;+  const SpvReflectPrvFunction* bf = (const SpvReflectPrvFunction*)b;+  return (int)af->id - (int)bf->id;+}++static SpvReflectResult ParseFunctions(SpvReflectPrvParser* p_parser)+{+  assert(IsNotNull(p_parser));+  assert(IsNotNull(p_parser->spirv_code));+  assert(IsNotNull(p_parser->nodes));++  if (IsNotNull(p_parser) && IsNotNull(p_parser->spirv_code) && IsNotNull(p_parser->nodes)) {+    if (p_parser->function_count == 0) {+      return SPV_REFLECT_RESULT_SUCCESS;+    }++    p_parser->functions = (SpvReflectPrvFunction*)calloc(p_parser->function_count,+                                                         sizeof(*(p_parser->functions)));+    if (IsNull(p_parser->functions)) {+      return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;+    }++    size_t function_index = 0;+    for (size_t i = 0; i < p_parser->node_count; ++i) {+      SpvReflectPrvNode* p_node = &(p_parser->nodes[i]);+      if (p_node->op != SpvOpFunction) {+        continue;+      }++      // Skip over function declarations that aren't definitions+      bool func_definition = false;+      // Intentionally reuse i to avoid iterating over these nodes more than+      // once+      for (; i < p_parser->node_count; ++i) {+        if (p_parser->nodes[i].op == SpvOpLabel) {+          func_definition = true;+          break;+        }+        if (p_parser->nodes[i].op == SpvOpFunctionEnd) {+          break;+        }+      }+      if (!func_definition) {+        continue;+      }++      SpvReflectPrvFunction* p_function = &(p_parser->functions[function_index]);++      SpvReflectResult result = ParseFunction(p_parser, p_node, p_function, i);+      if (result != SPV_REFLECT_RESULT_SUCCESS) {+        return result;+      }++      ++function_index;+    }++    qsort(p_parser->functions, p_parser->function_count,+          sizeof(*(p_parser->functions)), SortCompareFunctions);++    // Once they're sorted, link the functions with pointers to improve graph+    // traversal efficiency+    for (size_t i = 0; i < p_parser->function_count; ++i) {+      SpvReflectPrvFunction* p_func = &(p_parser->functions[i]);+      if (p_func->callee_count == 0) {+        continue;+      }+      p_func->callee_ptrs = (SpvReflectPrvFunction**)calloc(p_func->callee_count,+                                                            sizeof(*(p_func->callee_ptrs)));+      for (size_t j = 0, k = 0; j < p_func->callee_count; ++j) {+        while (p_parser->functions[k].id != p_func->callees[j]) {+          ++k;+          if (k >= p_parser->function_count) {+            // Invalid called function ID somewhere+            return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;+          }+        }+        p_func->callee_ptrs[j] = &(p_parser->functions[k]);+      }+    }+  }++  return SPV_REFLECT_RESULT_SUCCESS;+}++static SpvReflectResult ParseMemberCounts(SpvReflectPrvParser* p_parser)+{+  assert(IsNotNull(p_parser));+  assert(IsNotNull(p_parser->spirv_code));+  assert(IsNotNull(p_parser->nodes));++  if (IsNotNull(p_parser) && IsNotNull(p_parser->spirv_code) && IsNotNull(p_parser->nodes)) {+    for (size_t i = 0; i < p_parser->node_count; ++i) {+      SpvReflectPrvNode* p_node = &(p_parser->nodes[i]);+      if ((p_node->op != SpvOpMemberName) && (p_node->op != SpvOpMemberDecorate)) {+        continue;+      }++      uint32_t target_id = 0;+      uint32_t member_index = (uint32_t)INVALID_VALUE;+      CHECKED_READU32(p_parser, p_node->word_offset + 1, target_id);+      CHECKED_READU32(p_parser, p_node->word_offset + 2, member_index);+      SpvReflectPrvNode* p_target_node = FindNode(p_parser, target_id);+      // Not all nodes get parsed, so FindNode returning NULL is expected.+      if (IsNull(p_target_node)) {+        continue;+      }++      if (member_index == INVALID_VALUE) {+        return SPV_REFLECT_RESULT_ERROR_RANGE_EXCEEDED;+      }++      p_target_node->member_count = Max(p_target_node->member_count, member_index + 1);+    }++    for (uint32_t i = 0; i < p_parser->node_count; ++i) {+      SpvReflectPrvNode* p_node = &(p_parser->nodes[i]);+      if (p_node->member_count == 0) {+        continue;+      }++      p_node->member_names = (const char **)calloc(p_node->member_count, sizeof(*(p_node->member_names)));+      if (IsNull(p_node->member_names)) {+        return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;+      }++      p_node->member_decorations = (SpvReflectPrvDecorations*)calloc(p_node->member_count, sizeof(*(p_node->member_decorations)));+      if (IsNull(p_node->member_decorations)) {+        return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;+      }+    }+  }+  return SPV_REFLECT_RESULT_SUCCESS;+}++static SpvReflectResult ParseNames(SpvReflectPrvParser* p_parser)+{+  assert(IsNotNull(p_parser));+  assert(IsNotNull(p_parser->spirv_code));+  assert(IsNotNull(p_parser->nodes));++  if (IsNotNull(p_parser) && IsNotNull(p_parser->spirv_code) && IsNotNull(p_parser->nodes)) {+    for (size_t i = 0; i < p_parser->node_count; ++i) {+      SpvReflectPrvNode* p_node = &(p_parser->nodes[i]);+      if ((p_node->op != SpvOpName) && (p_node->op != SpvOpMemberName)) {+        continue;+      }++      uint32_t target_id = 0;+      CHECKED_READU32(p_parser, p_node->word_offset + 1, target_id);+      SpvReflectPrvNode* p_target_node = FindNode(p_parser, target_id);+      // Not all nodes get parsed, so FindNode returning NULL is expected.+      if (IsNull(p_target_node)) {+        continue;+      }++      const char** pp_target_name = &(p_target_node->name);+      if (p_node->op == SpvOpMemberName) {+        uint32_t member_index = UINT32_MAX;+        CHECKED_READU32(p_parser, p_node->word_offset + 2, member_index);+        pp_target_name = &(p_target_node->member_names[member_index]);+      }++      *pp_target_name = p_node->name;+    }+  }+  return SPV_REFLECT_RESULT_SUCCESS;+}++static SpvReflectResult ParseDecorations(SpvReflectPrvParser* p_parser)+{+  for (uint32_t i = 0; i < p_parser->node_count; ++i) {+    SpvReflectPrvNode* p_node = &(p_parser->nodes[i]);++    if (((uint32_t)p_node->op != (uint32_t)SpvOpDecorate) &&+        ((uint32_t)p_node->op != (uint32_t)SpvOpMemberDecorate) &&+        ((uint32_t)p_node->op != (uint32_t)SpvReflectOpDecorateId) &&+        ((uint32_t)p_node->op != (uint32_t)SpvReflectOpDecorateStringGOOGLE) &&+        ((uint32_t)p_node->op != (uint32_t)SpvReflectOpMemberDecorateStringGOOGLE))+    {+     continue;+    }++    // Need to adjust the read offset if this is a member decoration+    uint32_t member_offset = 0;+    if (p_node->op == SpvOpMemberDecorate) {+      member_offset = 1;+    }++    // Get decoration+    uint32_t decoration = (uint32_t)INVALID_VALUE;+    CHECKED_READU32(p_parser, p_node->word_offset + member_offset + 2, decoration);++    // Filter out the decoration that do not affect reflection, otherwise+    // there will be random crashes because the nodes aren't found.+    bool skip = false;+    switch (decoration) {+      default: {+        skip = true;+      }+      break;+      case SpvDecorationRelaxedPrecision:+      case SpvDecorationBlock:+      case SpvDecorationBufferBlock:+      case SpvDecorationColMajor:+      case SpvDecorationRowMajor:+      case SpvDecorationArrayStride:+      case SpvDecorationMatrixStride:+      case SpvDecorationBuiltIn:+      case SpvDecorationNoPerspective:+      case SpvDecorationFlat:+      case SpvDecorationNonWritable:+      case SpvDecorationNonReadable:+      case SpvDecorationLocation:+      case SpvDecorationBinding:+      case SpvDecorationDescriptorSet:+      case SpvDecorationOffset:+      case SpvDecorationInputAttachmentIndex:+      case SpvReflectDecorationHlslCounterBufferGOOGLE:+      case SpvReflectDecorationHlslSemanticGOOGLE: {+        skip = false;+      }+      break;    +    }+    if (skip) {+      continue;+    }  +    +    // Find target target node +    uint32_t target_id = 0;+    CHECKED_READU32(p_parser, p_node->word_offset + 1, target_id);+    SpvReflectPrvNode* p_target_node = FindNode(p_parser, target_id);+    if (IsNull(p_target_node)) {+      if ((p_node->op == (uint32_t)SpvOpDecorate) && (decoration == SpvDecorationRelaxedPrecision)) {+        // Many OPs can be decorated that we don't care about. Ignore those.+        // See https://github.com/KhronosGroup/SPIRV-Reflect/issues/134+        continue;+      }+      return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;+    }+    // Get decorations+    SpvReflectPrvDecorations* p_target_decorations = &(p_target_node->decorations);+    // Update pointer if this is a member member decoration+    if (p_node->op == SpvOpMemberDecorate) {+      uint32_t member_index = (uint32_t)INVALID_VALUE;+      CHECKED_READU32(p_parser, p_node->word_offset + 2, member_index);+      p_target_decorations = &(p_target_node->member_decorations[member_index]);+    }++    switch (decoration) {+      default: break;++      case SpvDecorationRelaxedPrecision: {+        p_target_decorations->is_relaxed_precision = true;+      }+      break;++      case SpvDecorationBlock: {+        p_target_decorations->is_block = true;+      }+      break;++      case SpvDecorationBufferBlock: {+        p_target_decorations->is_buffer_block = true;+      }+      break;++      case SpvDecorationColMajor: {+        p_target_decorations->is_column_major = true;+      }+      break;++      case SpvDecorationRowMajor: {+        p_target_decorations->is_row_major = true;+      }+      break;++      case SpvDecorationArrayStride: {+        uint32_t word_offset = p_node->word_offset + member_offset + 3;+        CHECKED_READU32(p_parser, word_offset, p_target_decorations->array_stride);+      }+      break;++      case SpvDecorationMatrixStride: {+        uint32_t word_offset = p_node->word_offset + member_offset + 3;+        CHECKED_READU32(p_parser, word_offset, p_target_decorations->matrix_stride);+      }+      break;++      case SpvDecorationBuiltIn: {+        p_target_decorations->is_built_in = true;+        uint32_t word_offset = p_node->word_offset + member_offset + 3;+        CHECKED_READU32_CAST(p_parser, word_offset, SpvBuiltIn, p_target_decorations->built_in);+      }+      break;++      case SpvDecorationNoPerspective: {+        p_target_decorations->is_noperspective = true;+      }+      break;++      case SpvDecorationFlat: {+        p_target_decorations->is_flat = true;+      }+      break;++      case SpvDecorationNonWritable: {+        p_target_decorations->is_non_writable = true;+      }+      break;++      case SpvDecorationNonReadable: {+        p_target_decorations->is_non_readable = true;+      }+      break;++      case SpvDecorationLocation: {+        uint32_t word_offset = p_node->word_offset + member_offset + 3;+        CHECKED_READU32(p_parser, word_offset, p_target_decorations->location.value);+        p_target_decorations->location.word_offset = word_offset;+      }+      break;++      case SpvDecorationBinding: {+        uint32_t word_offset = p_node->word_offset + member_offset+ 3;+        CHECKED_READU32(p_parser, word_offset, p_target_decorations->binding.value);+        p_target_decorations->binding.word_offset = word_offset;+      }+      break;++      case SpvDecorationDescriptorSet: {+        uint32_t word_offset = p_node->word_offset + member_offset+ 3;+        CHECKED_READU32(p_parser, word_offset, p_target_decorations->set.value);+        p_target_decorations->set.word_offset = word_offset;+      }+      break;++      case SpvDecorationOffset: {+        uint32_t word_offset = p_node->word_offset + member_offset+ 3;+        CHECKED_READU32(p_parser, word_offset, p_target_decorations->offset.value);+        p_target_decorations->offset.word_offset = word_offset;+      }+      break;++      case SpvDecorationInputAttachmentIndex: {+        uint32_t word_offset = p_node->word_offset + member_offset+ 3;+        CHECKED_READU32(p_parser, word_offset, p_target_decorations->input_attachment_index.value);+        p_target_decorations->input_attachment_index.word_offset = word_offset;+      }+      break;++      case SpvReflectDecorationHlslCounterBufferGOOGLE: {+        uint32_t word_offset = p_node->word_offset + member_offset+ 3;+        CHECKED_READU32(p_parser, word_offset, p_target_decorations->uav_counter_buffer.value);+        p_target_decorations->uav_counter_buffer.word_offset = word_offset;+      }+      break;++      case SpvReflectDecorationHlslSemanticGOOGLE: {+        uint32_t word_offset = p_node->word_offset + member_offset + 3;+        p_target_decorations->semantic.value = (const char*)(p_parser->spirv_code + word_offset);+        p_target_decorations->semantic.word_offset = word_offset;+      }+      break;+    }+  }+  return SPV_REFLECT_RESULT_SUCCESS;+}++static SpvReflectResult EnumerateAllUniforms(+  SpvReflectShaderModule* p_module,+  size_t*                 p_uniform_count, +  uint32_t**              pp_uniforms+)+{+  *p_uniform_count = p_module->descriptor_binding_count;+  if (*p_uniform_count == 0) {+    return SPV_REFLECT_RESULT_SUCCESS;+  }+  *pp_uniforms = (uint32_t*)calloc(*p_uniform_count, sizeof(**pp_uniforms));++  if (IsNull(*pp_uniforms)) {+    return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;+  }++  for (size_t i = 0; i < *p_uniform_count; ++i) {+    (*pp_uniforms)[i] = p_module->descriptor_bindings[i].spirv_id;+  }+  qsort(*pp_uniforms, *p_uniform_count, sizeof(**pp_uniforms),+        SortCompareUint32);+  return SPV_REFLECT_RESULT_SUCCESS;+}++static SpvReflectResult ParseType(+  SpvReflectPrvParser*       p_parser, +  SpvReflectPrvNode*         p_node, +  SpvReflectPrvDecorations*  p_struct_member_decorations, +  SpvReflectShaderModule*    p_module, +  SpvReflectTypeDescription* p_type+)+{+  SpvReflectResult result = SPV_REFLECT_RESULT_SUCCESS;++  if (p_node->member_count > 0) {+    p_type->member_count = p_node->member_count;+    p_type->members = (SpvReflectTypeDescription*)calloc(p_type->member_count, sizeof(*(p_type->members)));+    if (IsNotNull(p_type->members)) {+      // Mark all members types with an invalid state+      for (size_t i = 0; i < p_type->members->member_count; ++i) {+        SpvReflectTypeDescription* p_member_type = &(p_type->members[i]);+        p_member_type->id = (uint32_t)INVALID_VALUE;+        p_member_type->op = (SpvOp)INVALID_VALUE;+        p_member_type->storage_class = (SpvStorageClass)INVALID_VALUE;+      }+    }+    else {+      result = SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;+    }+  }++  if (result == SPV_REFLECT_RESULT_SUCCESS) {+    // Since the parse descends on type information, these will get overwritten+    // if not guarded against assignment. Only assign if the id is invalid.+    if (p_type->id == INVALID_VALUE) {+      p_type->id = p_node->result_id;+      p_type->op = p_node->op;+      p_type->decoration_flags = 0;+    }+    // Top level types need to pick up decorations from all types below it.+    // Issue and fix here: https://github.com/chaoticbob/SPIRV-Reflect/issues/64+    p_type->decoration_flags = ApplyDecorations(&p_node->decorations);++    switch (p_node->op) {+      default: break;+      case SpvOpTypeVoid:+        p_type->type_flags |= SPV_REFLECT_TYPE_FLAG_VOID;+        break;++      case SpvOpTypeBool:+        p_type->type_flags |= SPV_REFLECT_TYPE_FLAG_BOOL;+        break;++      case SpvOpTypeInt: {+        p_type->type_flags |= SPV_REFLECT_TYPE_FLAG_INT;+        IF_READU32(result, p_parser, p_node->word_offset + 2, p_type->traits.numeric.scalar.width);+        IF_READU32(result, p_parser, p_node->word_offset + 3, p_type->traits.numeric.scalar.signedness);+      }+      break;++      case SpvOpTypeFloat: {+        p_type->type_flags |= SPV_REFLECT_TYPE_FLAG_FLOAT;+        IF_READU32(result, p_parser, p_node->word_offset + 2, p_type->traits.numeric.scalar.width);+      }+      break;++      case SpvOpTypeVector: {+        p_type->type_flags |= SPV_REFLECT_TYPE_FLAG_VECTOR;+        uint32_t component_type_id = (uint32_t)INVALID_VALUE;+        IF_READU32(result, p_parser, p_node->word_offset + 2, component_type_id);+        IF_READU32(result, p_parser, p_node->word_offset + 3, p_type->traits.numeric.vector.component_count);+        // Parse component type+        SpvReflectPrvNode* p_next_node = FindNode(p_parser, component_type_id);+        if (IsNotNull(p_next_node)) {+          result = ParseType(p_parser, p_next_node, NULL, p_module, p_type);+        }+        else {+          result = SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;+          SPV_REFLECT_ASSERT(false);+        }+      }+      break;++      case SpvOpTypeMatrix: {+        p_type->type_flags |= SPV_REFLECT_TYPE_FLAG_MATRIX;+        uint32_t column_type_id = (uint32_t)INVALID_VALUE;+        IF_READU32(result, p_parser, p_node->word_offset + 2, column_type_id);+        IF_READU32(result, p_parser, p_node->word_offset + 3, p_type->traits.numeric.matrix.column_count);+        SpvReflectPrvNode* p_next_node = FindNode(p_parser, column_type_id);+        if (IsNotNull(p_next_node)) {+          result = ParseType(p_parser, p_next_node, NULL, p_module, p_type);+        }+        else {+          result = SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;+          SPV_REFLECT_ASSERT(false);+        }+        p_type->traits.numeric.matrix.row_count = p_type->traits.numeric.vector.component_count;+        p_type->traits.numeric.matrix.stride = p_node->decorations.matrix_stride;+        // NOTE: Matrix stride is decorated using OpMemberDecoreate - not OpDecoreate.+        if (IsNotNull(p_struct_member_decorations)) {+          p_type->traits.numeric.matrix.stride = p_struct_member_decorations->matrix_stride;+        }+      }+      break;++      case SpvOpTypeImage: {+        p_type->type_flags |= SPV_REFLECT_TYPE_FLAG_EXTERNAL_IMAGE;+        uint32_t sampled_type_id = (uint32_t)INVALID_VALUE;+        IF_READU32(result, p_parser, p_node->word_offset + 2, sampled_type_id);+        SpvReflectPrvNode* p_next_node = FindNode(p_parser, sampled_type_id);+        if (IsNotNull(p_next_node)) {+          result = ParseType(p_parser, p_next_node, NULL, p_module, p_type);+        }+        else {+          result = SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;+        }+        IF_READU32_CAST(result, p_parser, p_node->word_offset + 3, SpvDim, p_type->traits.image.dim);+        IF_READU32(result, p_parser, p_node->word_offset + 4, p_type->traits.image.depth);+        IF_READU32(result, p_parser, p_node->word_offset + 5, p_type->traits.image.arrayed);+        IF_READU32(result, p_parser, p_node->word_offset + 6, p_type->traits.image.ms);+        IF_READU32(result, p_parser, p_node->word_offset + 7, p_type->traits.image.sampled);+        IF_READU32_CAST(result, p_parser, p_node->word_offset + 8, SpvImageFormat, p_type->traits.image.image_format);+      }+      break;++      case SpvOpTypeSampler: {+        p_type->type_flags |= SPV_REFLECT_TYPE_FLAG_EXTERNAL_SAMPLER;+      }+      break;++      case SpvOpTypeSampledImage: {+        p_type->type_flags |= SPV_REFLECT_TYPE_FLAG_EXTERNAL_SAMPLED_IMAGE;+        uint32_t image_type_id = (uint32_t)INVALID_VALUE;+        IF_READU32(result, p_parser, p_node->word_offset + 2, image_type_id);+        SpvReflectPrvNode* p_next_node = FindNode(p_parser, image_type_id);+        if (IsNotNull(p_next_node)) {+          result = ParseType(p_parser, p_next_node, NULL, p_module, p_type);+        }+        else {+          result = SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;          +          SPV_REFLECT_ASSERT(false);+        }+      }+      break;++      case SpvOpTypeArray: {+        p_type->type_flags |= SPV_REFLECT_TYPE_FLAG_ARRAY;+        if (result == SPV_REFLECT_RESULT_SUCCESS) {+          uint32_t element_type_id = (uint32_t)INVALID_VALUE;+          uint32_t length_id = (uint32_t)INVALID_VALUE;+          IF_READU32(result, p_parser, p_node->word_offset + 2, element_type_id);+          IF_READU32(result, p_parser, p_node->word_offset + 3, length_id);+          // NOTE: Array stride is decorated using OpDecorate instead of+          //       OpMemberDecorate, even if the array is apart of a struct.+          p_type->traits.array.stride = p_node->decorations.array_stride;+          // Get length for current dimension+          SpvReflectPrvNode* p_length_node = FindNode(p_parser, length_id);+          if (IsNotNull(p_length_node)) {+            uint32_t dim_index = p_type->traits.array.dims_count;+            if (p_length_node->op == SpvOpSpecConstant ||+                p_length_node->op == SpvOpSpecConstantOp) {+              p_type->traits.array.dims[dim_index] = 0xFFFFFFFF;+              p_type->traits.array.spec_constant_op_ids[dim_index] = length_id;+              p_type->traits.array.dims_count += 1;+            } else {+              uint32_t length = 0;+              IF_READU32(result, p_parser, p_length_node->word_offset + 3, length);+              if (result == SPV_REFLECT_RESULT_SUCCESS) {+                // Write the array dim and increment the count and offset+                p_type->traits.array.dims[dim_index] = length;+                p_type->traits.array.spec_constant_op_ids[dim_index] = 0xFFFFFFFF;+                p_type->traits.array.dims_count += 1;+              } else {+                result = SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;+                SPV_REFLECT_ASSERT(false);+              }+            }+            // Parse next dimension or element type+            SpvReflectPrvNode* p_next_node = FindNode(p_parser, element_type_id);+            if (IsNotNull(p_next_node)) {+              result = ParseType(p_parser, p_next_node, NULL, p_module, p_type);+            }+          }+          else {+            result = SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;+            SPV_REFLECT_ASSERT(false);+          }+        }+      }+      break;++      case SpvOpTypeRuntimeArray: {+        p_type->type_flags |= SPV_REFLECT_TYPE_FLAG_ARRAY;+        uint32_t element_type_id = (uint32_t)INVALID_VALUE;+        IF_READU32(result, p_parser, p_node->word_offset + 2, element_type_id);+        p_type->traits.array.stride = p_node->decorations.array_stride;+        uint32_t dim_index = p_type->traits.array.dims_count;+        p_type->traits.array.dims[dim_index] = 0;+        p_type->traits.array.spec_constant_op_ids[dim_index] = 0;+        p_type->traits.array.dims_count += 1;+        // Parse next dimension or element type+        SpvReflectPrvNode* p_next_node = FindNode(p_parser, element_type_id);+        if (IsNotNull(p_next_node)) {+          result = ParseType(p_parser, p_next_node, NULL, p_module, p_type);+        }+        else {+          result = SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;+          SPV_REFLECT_ASSERT(false);+        }+      }+      break;++      case SpvOpTypeStruct: {+        p_type->type_flags |= SPV_REFLECT_TYPE_FLAG_STRUCT;+        p_type->type_flags |= SPV_REFLECT_TYPE_FLAG_EXTERNAL_BLOCK;+        uint32_t word_index = 2;+        uint32_t member_index = 0;+        for (; word_index < p_node->word_count; ++word_index, ++member_index) {+          uint32_t member_id = (uint32_t)INVALID_VALUE;+          IF_READU32(result, p_parser, p_node->word_offset + word_index, member_id);+          // Find member node+          SpvReflectPrvNode* p_member_node = FindNode(p_parser, member_id);+          if (IsNull(p_member_node)) {+            result = SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;+            SPV_REFLECT_ASSERT(false);+            break;+          }++          // Member decorations+          SpvReflectPrvDecorations* p_member_decorations = &p_node->member_decorations[member_index];++          assert(member_index < p_type->member_count);+          // Parse member type+          SpvReflectTypeDescription* p_member_type = &(p_type->members[member_index]);+          p_member_type->id = member_id;+          p_member_type->op = p_member_node->op;+          result = ParseType(p_parser, p_member_node, p_member_decorations, p_module, p_member_type);+          if (result != SPV_REFLECT_RESULT_SUCCESS) {+            break;+          }+          // This looks wrong +          //p_member_type->type_name = p_member_node->name;+          p_member_type->struct_member_name = p_node->member_names[member_index];+        }+      }+      break;++      case SpvOpTypeOpaque: break;++      case SpvOpTypePointer: {+        IF_READU32_CAST(result, p_parser, p_node->word_offset + 2, SpvStorageClass, p_type->storage_class);+        uint32_t type_id = (uint32_t)INVALID_VALUE;+        IF_READU32(result, p_parser, p_node->word_offset + 3, type_id);+        // Parse type+        SpvReflectPrvNode* p_next_node = FindNode(p_parser, type_id);+        if (IsNotNull(p_next_node)) {+          result = ParseType(p_parser, p_next_node, NULL, p_module, p_type);+        }+        else {+          result = SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;+          SPV_REFLECT_ASSERT(false);+        }+      }+      break;++      case SpvOpTypeAccelerationStructureKHR: {+        p_type->type_flags |= SPV_REFLECT_TYPE_FLAG_EXTERNAL_ACCELERATION_STRUCTURE;+      }+      break;+    }++    if (result == SPV_REFLECT_RESULT_SUCCESS) {+      // Names get assigned on the way down. Guard against names+      // get overwritten on the way up.+      if (IsNull(p_type->type_name)) {+        p_type->type_name = p_node->name;+      }+    }+  }++  return result;+}++static SpvReflectResult ParseTypes(+  SpvReflectPrvParser*    p_parser,+  SpvReflectShaderModule* p_module)+{+  if (p_parser->type_count == 0) {+    return SPV_REFLECT_RESULT_SUCCESS;+  }++  p_module->_internal->type_description_count = p_parser->type_count;+  p_module->_internal->type_descriptions = (SpvReflectTypeDescription*)calloc(p_module->_internal->type_description_count,+                                                                              sizeof(*(p_module->_internal->type_descriptions)));+  if (IsNull(p_module->_internal->type_descriptions)) {+    return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;+  }++  // Mark all types with an invalid state+  for (size_t i = 0; i < p_module->_internal->type_description_count; ++i) {+    SpvReflectTypeDescription* p_type = &(p_module->_internal->type_descriptions[i]);+    p_type->id = (uint32_t)INVALID_VALUE;+    p_type->op = (SpvOp)INVALID_VALUE;+    p_type->storage_class = (SpvStorageClass)INVALID_VALUE;+  }++  size_t type_index = 0;+  for (size_t i = 0; i < p_parser->node_count; ++i) {+    SpvReflectPrvNode* p_node = &(p_parser->nodes[i]);+    if (! p_node->is_type) {+      continue;+    }++    SpvReflectTypeDescription* p_type = &(p_module->_internal->type_descriptions[type_index]);+    SpvReflectResult result = ParseType(p_parser, p_node, NULL, p_module, p_type);+    if (result != SPV_REFLECT_RESULT_SUCCESS) {+      return result;+    }+    ++type_index;+  }+  return SPV_REFLECT_RESULT_SUCCESS;+}++static SpvReflectResult ParseCapabilities(+    SpvReflectPrvParser* p_parser,+    SpvReflectShaderModule* p_module)+{+  if (p_parser->capability_count == 0) {+    return SPV_REFLECT_RESULT_SUCCESS;+  }++  p_module->capability_count = p_parser->capability_count;+  p_module->capabilities = (SpvReflectCapability*)calloc(p_module->capability_count,+                                                         sizeof(*(p_module->capabilities)));+  if (IsNull(p_module->capabilities)) {+    return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;+  }++  // Mark all types with an invalid state+  for (size_t i = 0; i < p_module->capability_count; ++i) {+    SpvReflectCapability* p_cap = &(p_module->capabilities[i]);+    p_cap->value = SpvCapabilityMax;+    p_cap->word_offset = (uint32_t)INVALID_VALUE;+  }++  size_t capability_index = 0;+  for (size_t i = 0; i < p_parser->node_count; ++i) {+    SpvReflectPrvNode* p_node = &(p_parser->nodes[i]);+    if (SpvOpCapability != p_node->op) {+      continue;+    }++    SpvReflectCapability* p_cap = &(p_module->capabilities[capability_index]);+    p_cap->value = p_node->capability;+    p_cap->word_offset = p_node->word_offset + 1;+    ++capability_index;+  }++  return SPV_REFLECT_RESULT_SUCCESS;+}++static int SortCompareDescriptorBinding(const void* a, const void* b)+{+  const SpvReflectDescriptorBinding* p_elem_a = (const SpvReflectDescriptorBinding*)a;+  const SpvReflectDescriptorBinding* p_elem_b = (const SpvReflectDescriptorBinding*)b;+  int value = (int)(p_elem_a->binding) - (int)(p_elem_b->binding);+  if (value == 0) {+    // use spirv-id as a tiebreaker to ensure a stable ordering, as they're guaranteed+    // unique.+    assert(p_elem_a->spirv_id != p_elem_b->spirv_id);+    value = (int)(p_elem_a->spirv_id) - (int)(p_elem_b->spirv_id);+  }+  return value;+}++static SpvReflectResult ParseDescriptorBindings(+  SpvReflectPrvParser*    p_parser,+  SpvReflectShaderModule* p_module)+{+  p_module->descriptor_binding_count = 0;+  for (size_t i = 0; i < p_parser->node_count; ++i) {+    SpvReflectPrvNode* p_node = &(p_parser->nodes[i]);+    if ((p_node->op != SpvOpVariable) ||+        ((p_node->storage_class != SpvStorageClassUniform) &&+         (p_node->storage_class != SpvStorageClassStorageBuffer) &&+         (p_node->storage_class != SpvStorageClassUniformConstant)))+    {+      continue;+    }+    if ((p_node->decorations.set.value == INVALID_VALUE) || (p_node->decorations.binding.value == INVALID_VALUE)) {+      continue;+    }++    p_module->descriptor_binding_count += 1;+  }++  if (p_module->descriptor_binding_count == 0) {+    return SPV_REFLECT_RESULT_SUCCESS;+  }++  p_module->descriptor_bindings = (SpvReflectDescriptorBinding*)calloc(p_module->descriptor_binding_count, sizeof(*(p_module->descriptor_bindings)));+  if (IsNull(p_module->descriptor_bindings)) {+    return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;+  }++  // Mark all types with an invalid state+  for (uint32_t descriptor_index = 0; descriptor_index < p_module->descriptor_binding_count; ++descriptor_index) {+    SpvReflectDescriptorBinding* p_descriptor = &(p_module->descriptor_bindings[descriptor_index]);+    p_descriptor->binding = (uint32_t)INVALID_VALUE;+    p_descriptor->input_attachment_index = (uint32_t)INVALID_VALUE;+    p_descriptor->set = (uint32_t)INVALID_VALUE;+    p_descriptor->descriptor_type = (SpvReflectDescriptorType)INVALID_VALUE;+    p_descriptor->uav_counter_id = (uint32_t)INVALID_VALUE;+  }++  size_t descriptor_index = 0;+  for (size_t i = 0; i < p_parser->node_count; ++i) {+    SpvReflectPrvNode* p_node = &(p_parser->nodes[i]);+    if ((p_node->op != SpvOpVariable) ||+        ((p_node->storage_class != SpvStorageClassUniform) &&+         (p_node->storage_class != SpvStorageClassStorageBuffer) &&+         (p_node->storage_class != SpvStorageClassUniformConstant)))+    {+      continue;+    }+    if ((p_node->decorations.set.value == INVALID_VALUE) || (p_node->decorations.binding.value == INVALID_VALUE)) {+      continue;+    }++    SpvReflectTypeDescription* p_type = FindType(p_module, p_node->type_id);+    if (IsNull(p_type)) {+      return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;+    }+    // If the type is a pointer, resolve it. We need to retain the storage class+    // from the pointer so that we can use it to deduce deescriptor types.+    SpvStorageClass pointer_storage_class = SpvStorageClassMax;+    if (p_type->op == SpvOpTypePointer) {+      pointer_storage_class = p_type->storage_class;+      // Find the type's node+      SpvReflectPrvNode* p_type_node = FindNode(p_parser, p_type->id);+      if (IsNull(p_type_node)) {+        return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;+      }+      // Should be the resolved type+      p_type = FindType(p_module, p_type_node->type_id);+      if (IsNull(p_type)) {+        return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;+      }+    }++    SpvReflectDescriptorBinding* p_descriptor = &p_module->descriptor_bindings[descriptor_index];+    p_descriptor->spirv_id = p_node->result_id;+    p_descriptor->name = p_node->name;+    p_descriptor->binding = p_node->decorations.binding.value;+    p_descriptor->input_attachment_index = p_node->decorations.input_attachment_index.value;+    p_descriptor->set = p_node->decorations.set.value;+    p_descriptor->count = 1;+    p_descriptor->uav_counter_id = p_node->decorations.uav_counter_buffer.value;+    p_descriptor->type_description = p_type;+    p_descriptor->decoration_flags = ApplyDecorations(&p_node->decorations);++    // If this is in the StorageBuffer storage class, it's for sure a storage+    // buffer descriptor. We need to handle this case earlier because in SPIR-V+    // there are two ways to indicate a storage buffer:+    // 1) Uniform storage class + BufferBlock decoration, or+    // 2) StorageBuffer storage class + Buffer decoration.+    // The 1) way is deprecated since SPIR-V v1.3. But the Buffer decoration is+    // also used together with Uniform storage class to mean uniform buffer..+    // We'll handle the pre-v1.3 cases in ParseDescriptorType().+    if (pointer_storage_class == SpvStorageClassStorageBuffer) {+      p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER;+    }++    // Copy image traits+    if ((p_type->type_flags & SPV_REFLECT_TYPE_FLAG_EXTERNAL_MASK) == SPV_REFLECT_TYPE_FLAG_EXTERNAL_IMAGE) {+      memcpy(&p_descriptor->image, &p_type->traits.image, sizeof(p_descriptor->image));+    }++    // This is a workaround for: https://github.com/KhronosGroup/glslang/issues/1096+    {+      const uint32_t resource_mask = SPV_REFLECT_TYPE_FLAG_EXTERNAL_SAMPLED_IMAGE | SPV_REFLECT_TYPE_FLAG_EXTERNAL_IMAGE;+      if ((p_type->type_flags & resource_mask) == resource_mask) {+        memcpy(&p_descriptor->image, &p_type->traits.image, sizeof(p_descriptor->image));+      }+    }++    // Copy array traits+    if (p_type->traits.array.dims_count > 0) {+      p_descriptor->array.dims_count = p_type->traits.array.dims_count;+      for (uint32_t dim_index = 0; dim_index < p_type->traits.array.dims_count; ++dim_index) {+        uint32_t dim_value = p_type->traits.array.dims[dim_index];+        p_descriptor->array.dims[dim_index] = dim_value;+        p_descriptor->count *= dim_value;+      }+    }++    // Count+++    p_descriptor->word_offset.binding = p_node->decorations.binding.word_offset;+    p_descriptor->word_offset.set = p_node->decorations.set.word_offset;++    ++descriptor_index;+  }++  if (p_module->descriptor_binding_count > 0) {+    qsort(p_module->descriptor_bindings,+          p_module->descriptor_binding_count,+          sizeof(*(p_module->descriptor_bindings)),+          SortCompareDescriptorBinding);+  }++  return SPV_REFLECT_RESULT_SUCCESS;+}++static SpvReflectResult ParseDescriptorType(SpvReflectShaderModule* p_module)+{+  if (p_module->descriptor_binding_count == 0) {+    return SPV_REFLECT_RESULT_SUCCESS;+  }++  for (uint32_t descriptor_index = 0; descriptor_index < p_module->descriptor_binding_count; ++descriptor_index) {+    SpvReflectDescriptorBinding* p_descriptor = &(p_module->descriptor_bindings[descriptor_index]);+    SpvReflectTypeDescription* p_type = p_descriptor->type_description;++    if ((int)p_descriptor->descriptor_type == (int)INVALID_VALUE) {+      switch (p_type->type_flags & SPV_REFLECT_TYPE_FLAG_EXTERNAL_MASK) {+        default: assert(false && "unknown type flag"); break;++        case SPV_REFLECT_TYPE_FLAG_EXTERNAL_IMAGE: {+          if (p_descriptor->image.dim == SpvDimBuffer) {+            switch (p_descriptor->image.sampled) {+              default: assert(false && "unknown texel buffer sampled value"); break;+              case IMAGE_SAMPLED: p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; break;+              case IMAGE_STORAGE: p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; break;+            }+          }+          else if(p_descriptor->image.dim == SpvDimSubpassData) {+            p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;+          }+          else {+            switch (p_descriptor->image.sampled) {+              default: assert(false && "unknown image sampled value"); break;+              case IMAGE_SAMPLED: p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_SAMPLED_IMAGE; break;+              case IMAGE_STORAGE: p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_IMAGE; break;+            }+          }+        }+        break;++        case SPV_REFLECT_TYPE_FLAG_EXTERNAL_SAMPLER: {+          p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_SAMPLER;+        }+        break;++        case (SPV_REFLECT_TYPE_FLAG_EXTERNAL_SAMPLED_IMAGE | SPV_REFLECT_TYPE_FLAG_EXTERNAL_IMAGE): {+          // This is a workaround for: https://github.com/KhronosGroup/glslang/issues/1096+          if (p_descriptor->image.dim == SpvDimBuffer) {+            switch (p_descriptor->image.sampled) {+              default: assert(false && "unknown texel buffer sampled value"); break;+              case IMAGE_SAMPLED: p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; break;+              case IMAGE_STORAGE: p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; break;+            }+          }+          else {+            p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;+          }+        }+        break;++        case SPV_REFLECT_TYPE_FLAG_EXTERNAL_BLOCK: {+          if (p_type->decoration_flags & SPV_REFLECT_DECORATION_BLOCK) {+            p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_BUFFER;+          }+          else if (p_type->decoration_flags & SPV_REFLECT_DECORATION_BUFFER_BLOCK) {+            p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER;+          }+          else {+            assert(false && "unknown struct");+          }+        }+        break;++        case SPV_REFLECT_TYPE_FLAG_EXTERNAL_ACCELERATION_STRUCTURE: {+          p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR;+        }+        break;+      }+    }++    switch (p_descriptor->descriptor_type) {+      case SPV_REFLECT_DESCRIPTOR_TYPE_SAMPLER                    : p_descriptor->resource_type = SPV_REFLECT_RESOURCE_FLAG_SAMPLER; break;+      case SPV_REFLECT_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER     : p_descriptor->resource_type = (SpvReflectResourceType)(SPV_REFLECT_RESOURCE_FLAG_SAMPLER | SPV_REFLECT_RESOURCE_FLAG_SRV); break;+      case SPV_REFLECT_DESCRIPTOR_TYPE_SAMPLED_IMAGE              : p_descriptor->resource_type = SPV_REFLECT_RESOURCE_FLAG_SRV; break;+      case SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_IMAGE              : p_descriptor->resource_type = SPV_REFLECT_RESOURCE_FLAG_UAV; break;+      case SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER       : p_descriptor->resource_type = SPV_REFLECT_RESOURCE_FLAG_SRV; break;+      case SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER       : p_descriptor->resource_type = SPV_REFLECT_RESOURCE_FLAG_UAV; break;+      case SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_BUFFER             : p_descriptor->resource_type = SPV_REFLECT_RESOURCE_FLAG_CBV; break;+      case SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC     : p_descriptor->resource_type = SPV_REFLECT_RESOURCE_FLAG_CBV; break;+      case SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER             : p_descriptor->resource_type = SPV_REFLECT_RESOURCE_FLAG_UAV; break;+      case SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC     : p_descriptor->resource_type = SPV_REFLECT_RESOURCE_FLAG_UAV; break;+      case SPV_REFLECT_DESCRIPTOR_TYPE_INPUT_ATTACHMENT           : break;+      case SPV_REFLECT_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR : p_descriptor->resource_type = SPV_REFLECT_RESOURCE_FLAG_SRV; break;+    }+  }++  return SPV_REFLECT_RESULT_SUCCESS;+}++static SpvReflectResult ParseUAVCounterBindings(SpvReflectShaderModule* p_module)+{+  char name[MAX_NODE_NAME_LENGTH];+  const char* k_count_tag = "@count";++  for (uint32_t descriptor_index = 0; descriptor_index < p_module->descriptor_binding_count; ++descriptor_index) {+    SpvReflectDescriptorBinding* p_descriptor = &(p_module->descriptor_bindings[descriptor_index]);++    if (p_descriptor->descriptor_type != SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER) {+      continue;+    }++    SpvReflectDescriptorBinding* p_counter_descriptor = NULL;+    // Use UAV counter buffer id if present...+    if (p_descriptor->uav_counter_id != UINT32_MAX) {+      for (uint32_t counter_descriptor_index = 0; counter_descriptor_index < p_module->descriptor_binding_count; ++counter_descriptor_index) {+        SpvReflectDescriptorBinding* p_test_counter_descriptor = &(p_module->descriptor_bindings[counter_descriptor_index]);+        if (p_test_counter_descriptor->descriptor_type != SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER) {+          continue;+        }+        if (p_descriptor->uav_counter_id == p_test_counter_descriptor->spirv_id) {+          p_counter_descriptor = p_test_counter_descriptor;+          break;+        }+      }+    }+    // ...otherwise use old @count convention.+    else {+      const size_t descriptor_name_length = p_descriptor->name? strlen(p_descriptor->name): 0;++      memset(name, 0, MAX_NODE_NAME_LENGTH);    +      memcpy(name, p_descriptor->name, descriptor_name_length);+#if defined(_WIN32)+      strcat_s(name, MAX_NODE_NAME_LENGTH, k_count_tag);+#else+      strcat(name, k_count_tag);+#endif++      for (uint32_t counter_descriptor_index = 0; counter_descriptor_index < p_module->descriptor_binding_count; ++counter_descriptor_index) {+        SpvReflectDescriptorBinding* p_test_counter_descriptor = &(p_module->descriptor_bindings[counter_descriptor_index]);+        if (p_test_counter_descriptor->descriptor_type != SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER) {+          continue;+        }+        if (p_test_counter_descriptor->name && strcmp(name, p_test_counter_descriptor->name) == 0) {+          p_counter_descriptor = p_test_counter_descriptor;+          break;+        }+      }+    }++    if (p_counter_descriptor != NULL) {+      p_descriptor->uav_counter_binding = p_counter_descriptor;+    }+  }++  return SPV_REFLECT_RESULT_SUCCESS;+}++static SpvReflectResult ParseDescriptorBlockVariable(+  SpvReflectPrvParser*        p_parser, +  SpvReflectShaderModule*     p_module, +  SpvReflectTypeDescription*  p_type, +  SpvReflectBlockVariable*    p_var+)+{+  bool has_non_writable = false;++  if (IsNotNull(p_type->members) && (p_type->member_count > 0)) {+    p_var->member_count = p_type->member_count;+    p_var->members = (SpvReflectBlockVariable*)calloc(p_var->member_count, sizeof(*p_var->members));+    if (IsNull(p_var->members)) {+      return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;+    }++    SpvReflectPrvNode* p_type_node = FindNode(p_parser, p_type->id);+    if (IsNull(p_type_node)) {+      return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;+    }+    // Resolve to element type if current type is array or run time array+    while (p_type_node->op == SpvOpTypeArray || p_type_node->op == SpvOpTypeRuntimeArray) {+      if (p_type_node->op == SpvOpTypeArray) {+        p_type_node = FindNode(p_parser, p_type_node->array_traits.element_type_id);+      }+      else {+        // Element type description+        SpvReflectTypeDescription* p_type_temp = FindType(p_module, p_type_node->array_traits.element_type_id);+        if (IsNull(p_type_temp)) {+          return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;+        }+        // Element type node+        p_type_node = FindNode(p_parser, p_type_temp->id);+      }+      if (IsNull(p_type_node)) {+        return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;+      }+    }+    +    // Parse members+    for (uint32_t member_index = 0; member_index < p_type->member_count; ++member_index) {+      SpvReflectTypeDescription* p_member_type = &p_type->members[member_index];+      SpvReflectBlockVariable* p_member_var = &p_var->members[member_index];+      bool is_struct = (p_member_type->type_flags & SPV_REFLECT_TYPE_FLAG_STRUCT) == SPV_REFLECT_TYPE_FLAG_STRUCT;+      if (is_struct) {+        SpvReflectResult result = ParseDescriptorBlockVariable(p_parser, p_module, p_member_type, p_member_var);+        if (result != SPV_REFLECT_RESULT_SUCCESS) {+          return result;+        }+      }++      p_member_var->name = p_type_node->member_names[member_index];+      p_member_var->offset = p_type_node->member_decorations[member_index].offset.value;+      p_member_var->decoration_flags = ApplyDecorations(&p_type_node->member_decorations[member_index]);+      p_member_var->flags |= SPV_REFLECT_VARIABLE_FLAGS_UNUSED;+      if (!has_non_writable && (p_member_var->decoration_flags & SPV_REFLECT_DECORATION_NON_WRITABLE)) {+        has_non_writable = true;+      }+      ApplyNumericTraits(p_member_type, &p_member_var->numeric);+      if (p_member_type->op == SpvOpTypeArray) {+        ApplyArrayTraits(p_member_type, &p_member_var->array);+      }++      p_member_var->type_description = p_member_type;+    }+  }++  p_var->name = p_type->type_name;+  p_var->type_description = p_type;+  if (has_non_writable) {+    p_var->decoration_flags |= SPV_REFLECT_DECORATION_NON_WRITABLE;+  }++  return SPV_REFLECT_RESULT_SUCCESS;+}++static SpvReflectResult ParseDescriptorBlockVariableSizes(+  SpvReflectPrvParser*     p_parser, +  SpvReflectShaderModule*  p_module, +  bool                     is_parent_root, +  bool                     is_parent_aos, +  bool                     is_parent_rta, +  SpvReflectBlockVariable* p_var+)+{+  if (p_var->member_count == 0) {+    return SPV_REFLECT_RESULT_SUCCESS;+  }++  // Absolute offsets+  for (uint32_t member_index = 0; member_index < p_var->member_count; ++member_index) {+    SpvReflectBlockVariable* p_member_var = &p_var->members[member_index];+    if (is_parent_root) {+      p_member_var->absolute_offset = p_member_var->offset;+    }+    else {+      p_member_var->absolute_offset = is_parent_aos ? 0 : p_member_var->offset + p_var->absolute_offset;+    }+  }++  // Size+  for (uint32_t member_index = 0; member_index < p_var->member_count; ++member_index) {+    SpvReflectBlockVariable* p_member_var = &p_var->members[member_index];+    SpvReflectTypeDescription* p_member_type = p_member_var->type_description;++    switch (p_member_type->op) {+      case SpvOpTypeBool: {+        p_member_var->size = SPIRV_WORD_SIZE;+      }+      break;++      case SpvOpTypeInt:+      case SpvOpTypeFloat: {+        p_member_var->size = p_member_type->traits.numeric.scalar.width / SPIRV_BYTE_WIDTH;+      }+      break;++      case SpvOpTypeVector: {+        uint32_t size = p_member_type->traits.numeric.vector.component_count *+                        (p_member_type->traits.numeric.scalar.width / SPIRV_BYTE_WIDTH);+        p_member_var->size = size;+      }+      break;++      case SpvOpTypeMatrix: {+        if (p_member_var->decoration_flags & SPV_REFLECT_DECORATION_COLUMN_MAJOR) {+          p_member_var->size = p_member_var->numeric.matrix.column_count * p_member_var->numeric.matrix.stride;+        }+        else if (p_member_var->decoration_flags & SPV_REFLECT_DECORATION_ROW_MAJOR) {+          p_member_var->size = p_member_var->numeric.matrix.row_count * p_member_var->numeric.matrix.stride;+        }+      }+      break;++      case SpvOpTypeArray: {+        // If array of structs, parse members first...+        bool is_struct = (p_member_type->type_flags & SPV_REFLECT_TYPE_FLAG_STRUCT) == SPV_REFLECT_TYPE_FLAG_STRUCT;+        if (is_struct) {+          SpvReflectResult result = ParseDescriptorBlockVariableSizes(p_parser, p_module, false, true, is_parent_rta, p_member_var);+          if (result != SPV_REFLECT_RESULT_SUCCESS) {+            return result;+          }+        }+        // ...then array+        uint32_t element_count = (p_member_var->array.dims_count > 0 ? 1 : 0);+        for (uint32_t i = 0; i < p_member_var->array.dims_count; ++i) {+          element_count *= p_member_var->array.dims[i];+        }+        p_member_var->size = element_count * p_member_var->array.stride;+      }+      break;++      case SpvOpTypeRuntimeArray: {+        bool is_struct = (p_member_type->type_flags & SPV_REFLECT_TYPE_FLAG_STRUCT) == SPV_REFLECT_TYPE_FLAG_STRUCT;+        if (is_struct) {+          SpvReflectResult result = ParseDescriptorBlockVariableSizes(p_parser, p_module, false, true, true, p_member_var);+          if (result != SPV_REFLECT_RESULT_SUCCESS) {+            return result;+          }+        }+      }+      break;++      case SpvOpTypeStruct: {+        SpvReflectResult result = ParseDescriptorBlockVariableSizes(p_parser, p_module, false, is_parent_aos, is_parent_rta, p_member_var);+        if (result != SPV_REFLECT_RESULT_SUCCESS) {+          return result;+        }+      }+      break;++      default:+        break;+    }+  }++  // Parse padded size using offset difference for all member except for the last entry...+  for (uint32_t member_index = 0; member_index < (p_var->member_count - 1); ++member_index) {+    SpvReflectBlockVariable* p_member_var = &p_var->members[member_index];+    SpvReflectBlockVariable* p_next_member_var = &p_var->members[member_index + 1];+    p_member_var->padded_size = p_next_member_var->offset - p_member_var->offset;+    if (p_member_var->size > p_member_var->padded_size) {+      p_member_var->size = p_member_var->padded_size;+    }+    if (is_parent_rta) {+      p_member_var->padded_size = p_member_var->size;+    }+  }+  // ...last entry just gets rounded up to near multiple of SPIRV_DATA_ALIGNMENT, which is 16 and+  // subtract the offset.+  if (p_var->member_count > 0) {+    SpvReflectBlockVariable* p_member_var = &p_var->members[p_var->member_count - 1];+    p_member_var->padded_size = RoundUp(p_member_var->offset  + p_member_var->size, SPIRV_DATA_ALIGNMENT) - p_member_var->offset;+    if (p_member_var->size > p_member_var->padded_size) {+      p_member_var->size = p_member_var->padded_size;+    }+    if (is_parent_rta) {+      p_member_var->padded_size = p_member_var->size;+    }+  }++  // @TODO validate this with assertion+  p_var->size = p_var->members[p_var->member_count - 1].offset ++                p_var->members[p_var->member_count - 1].padded_size;+  p_var->padded_size = p_var->size;++  return SPV_REFLECT_RESULT_SUCCESS;+}++static void MarkSelfAndAllMemberVarsAsUsed(SpvReflectBlockVariable* p_var)+{+  // Clear the current variable's USED flag+  p_var->flags &= ~SPV_REFLECT_VARIABLE_FLAGS_UNUSED;++  SpvOp op_type = p_var->type_description->op;+  switch (op_type) {+    default: break;++    case SpvOpTypeArray: {+    }+    break;++    case SpvOpTypeStruct: {+      for (uint32_t i = 0; i < p_var->member_count; ++i) {+        SpvReflectBlockVariable* p_member_var = &p_var->members[i];+        MarkSelfAndAllMemberVarsAsUsed(p_member_var);+      }+    }+    break;+  }+}++static SpvReflectResult ParseDescriptorBlockVariableUsage(+  SpvReflectPrvParser*      p_parser,+  SpvReflectShaderModule*   p_module,+  SpvReflectPrvAccessChain* p_access_chain,+  uint32_t                  index_index,+  SpvOp                     override_op_type,+  SpvReflectBlockVariable*  p_var+)+{+  (void)p_parser;+  (void)p_access_chain;+  (void)p_var;++  // Clear the current variable's UNUSED flag+  p_var->flags &= ~SPV_REFLECT_VARIABLE_FLAGS_UNUSED;+  +  // Parsing arrays requires overriding the op type for+  // for the lowest dim's element type.+  SpvOp op_type = p_var->type_description->op;+  if (override_op_type != (SpvOp)INVALID_VALUE) {+    op_type = override_op_type;+  }++  switch (op_type) {+    default: break;++    case SpvOpTypeArray: {+      // Parse through array's type hierarchy to find the actual/non-array element type+      SpvReflectTypeDescription* p_type = p_var->type_description;+      while ((p_type->op == SpvOpTypeArray) && (index_index < p_access_chain->index_count)) {+        // Find the array element type id+        SpvReflectPrvNode* p_node = FindNode(p_parser, p_type->id);+        if (p_node == NULL) {+          return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;+        }+        uint32_t element_type_id = p_node->array_traits.element_type_id;+        // Get the array element type+        p_type = FindType(p_module, element_type_id);+        if (p_type == NULL) {+          return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;+        }+        // Next access chain index+        index_index += 1;+      }+      +      // Only continue parsing if there's remaining indices in the access+      // chain. If the end of the access chain has been reach then all+      // remaining variables (including those in struct hierarchies)+      // are considered USED.+      //+      // See: https://github.com/KhronosGroup/SPIRV-Reflect/issues/78+      //  +      if (index_index < p_access_chain->index_count) {+        // Parse current var again with a type override and advanced index index+        SpvReflectResult result = ParseDescriptorBlockVariableUsage(+          p_parser,+          p_module,+          p_access_chain,+          index_index,+          p_type->op,+          p_var);+        if (result != SPV_REFLECT_RESULT_SUCCESS) {+          return result;+        }+      }+      else {+        // Clear UNUSED flag for remaining variables+        MarkSelfAndAllMemberVarsAsUsed(p_var);+      }+    }+    break;++    case SpvOpTypeStruct: {+      assert(p_var->member_count > 0);+      if (p_var->member_count == 0) {+        return SPV_REFLECT_RESULT_ERROR_SPIRV_UNEXPECTED_BLOCK_DATA;+      }+      // Get member variable at the access's chain current index+      uint32_t index = p_access_chain->indexes[index_index];+      if (index >= p_var->member_count) {+        return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_BLOCK_MEMBER_REFERENCE;+      }+      SpvReflectBlockVariable* p_member_var = &p_var->members[index];++      // Next access chain index+      index_index += 1;++      // Only continue parsing if there's remaining indices in the access+      // chain. If the end of the access chain has been reach then all+      // remaining variables (including those in struct hierarchies)+      // are considered USED.+      //+      // See: https://github.com/KhronosGroup/SPIRV-Reflect/issues/78+      //+      if (index_index < p_access_chain->index_count) {+         SpvReflectResult result = ParseDescriptorBlockVariableUsage(+           p_parser,+           p_module,+           p_access_chain,+           index_index,+           (SpvOp)INVALID_VALUE,+           p_member_var);+         if (result != SPV_REFLECT_RESULT_SUCCESS) {+           return result;+         }+      }+      else {+        // Clear UNUSED flag for remaining variables+        MarkSelfAndAllMemberVarsAsUsed(p_member_var);+      }+      //SpvReflectBlockVariable* p_member_var = &p_var->members[index];+      //if (index_index < p_access_chain->index_count) {+      //  SpvReflectResult result = ParseDescriptorBlockVariableUsage(+      //    p_parser,+      //    p_module,+      //    p_access_chain,+      //    index_index + 1,+      //    (SpvOp)INVALID_VALUE,+      //    p_member_var);+      //  if (result != SPV_REFLECT_RESULT_SUCCESS) {+      //    return result;+      //  }+      //}+    }+    break;+  }++  return SPV_REFLECT_RESULT_SUCCESS;+}++static SpvReflectResult ParseDescriptorBlocks(+  SpvReflectPrvParser*    p_parser, +  SpvReflectShaderModule* p_module)+{+  if (p_module->descriptor_binding_count == 0) {+    return SPV_REFLECT_RESULT_SUCCESS;+  }++  for (uint32_t descriptor_index = 0; descriptor_index < p_module->descriptor_binding_count; ++descriptor_index) {+    SpvReflectDescriptorBinding* p_descriptor = &(p_module->descriptor_bindings[descriptor_index]);+    SpvReflectTypeDescription* p_type = p_descriptor->type_description;+    if ((p_descriptor->descriptor_type != SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_BUFFER) &&+        (p_descriptor->descriptor_type != SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER) )+    {+      continue;+    }++    // Mark UNUSED+    p_descriptor->block.flags |= SPV_REFLECT_VARIABLE_FLAGS_UNUSED;+    // Parse descriptor block +    SpvReflectResult result = ParseDescriptorBlockVariable(p_parser, p_module, p_type, &p_descriptor->block);+    if (result != SPV_REFLECT_RESULT_SUCCESS) {+      return result;+    }++    for (uint32_t access_chain_index = 0; access_chain_index < p_parser->access_chain_count; ++access_chain_index) {+      SpvReflectPrvAccessChain* p_access_chain = &(p_parser->access_chains[access_chain_index]);+      // Skip any access chains that aren't touching this descriptor block+      if (p_descriptor->spirv_id != p_access_chain->base_id) {+        continue;+      }+      result = ParseDescriptorBlockVariableUsage(+        p_parser,+        p_module,+        p_access_chain,+        0,+        (SpvOp)INVALID_VALUE,+        &p_descriptor->block);+      if (result != SPV_REFLECT_RESULT_SUCCESS) {+        return result;+      }+    }+    +    p_descriptor->block.name = p_descriptor->name;++    bool is_parent_rta = (p_descriptor->descriptor_type == SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER);+    result = ParseDescriptorBlockVariableSizes(p_parser, p_module, true, false, is_parent_rta, &p_descriptor->block);+    if (result != SPV_REFLECT_RESULT_SUCCESS) {+      return result;+    }++    if (is_parent_rta) {+      p_descriptor->block.size = 0;+      p_descriptor->block.padded_size = 0;+    }+  }++  return SPV_REFLECT_RESULT_SUCCESS;+}++static SpvReflectResult ParseFormat(+  const SpvReflectTypeDescription*  p_type,+  SpvReflectFormat*                 p_format+)+{+  SpvReflectResult result = SPV_REFLECT_RESULT_ERROR_INTERNAL_ERROR;+  bool signedness = (p_type->traits.numeric.scalar.signedness != 0);+  uint32_t bit_width = p_type->traits.numeric.scalar.width;+  if (p_type->type_flags & SPV_REFLECT_TYPE_FLAG_VECTOR) {+    uint32_t component_count = p_type->traits.numeric.vector.component_count;+    if (p_type->type_flags & SPV_REFLECT_TYPE_FLAG_FLOAT) {+      switch (bit_width) {+        case 32: {+          switch (component_count) {+            case 2: *p_format = SPV_REFLECT_FORMAT_R32G32_SFLOAT; break;+            case 3: *p_format = SPV_REFLECT_FORMAT_R32G32B32_SFLOAT; break;+            case 4: *p_format = SPV_REFLECT_FORMAT_R32G32B32A32_SFLOAT; break;+          }+        }+        break;+        +        case 64: {+          switch (component_count) {+            case 2: *p_format = SPV_REFLECT_FORMAT_R64G64_SFLOAT; break;+            case 3: *p_format = SPV_REFLECT_FORMAT_R64G64B64_SFLOAT; break;+            case 4: *p_format = SPV_REFLECT_FORMAT_R64G64B64A64_SFLOAT; break;+          }+        }+      }+      result = SPV_REFLECT_RESULT_SUCCESS;+    }+    else if (p_type->type_flags & (SPV_REFLECT_TYPE_FLAG_INT | SPV_REFLECT_TYPE_FLAG_BOOL)) {+      switch (bit_width) {+        case 32: {+          switch (component_count) {+            case 2: *p_format = signedness ? SPV_REFLECT_FORMAT_R32G32_SINT : SPV_REFLECT_FORMAT_R32G32_UINT; break;+            case 3: *p_format = signedness ? SPV_REFLECT_FORMAT_R32G32B32_SINT : SPV_REFLECT_FORMAT_R32G32B32_UINT; break;+            case 4: *p_format = signedness ? SPV_REFLECT_FORMAT_R32G32B32A32_SINT : SPV_REFLECT_FORMAT_R32G32B32A32_UINT; break;+          }+        }+        break;+        +        case 64: {+          switch (component_count) {+            case 2: *p_format = signedness ? SPV_REFLECT_FORMAT_R64G64_SINT : SPV_REFLECT_FORMAT_R64G64_UINT; break;+            case 3: *p_format = signedness ? SPV_REFLECT_FORMAT_R64G64B64_SINT : SPV_REFLECT_FORMAT_R64G64B64_UINT; break;+            case 4: *p_format = signedness ? SPV_REFLECT_FORMAT_R64G64B64A64_SINT : SPV_REFLECT_FORMAT_R64G64B64A64_UINT; break;+          }+        }+      }+      result = SPV_REFLECT_RESULT_SUCCESS;+    }+  }+  else if (p_type->type_flags & SPV_REFLECT_TYPE_FLAG_FLOAT) {+    switch(bit_width) {+      case 32:+        *p_format = SPV_REFLECT_FORMAT_R32_SFLOAT;+        break;+      case 64:+        *p_format = SPV_REFLECT_FORMAT_R64_SFLOAT;+        break;+    }+    result = SPV_REFLECT_RESULT_SUCCESS;+  }+  else if (p_type->type_flags & (SPV_REFLECT_TYPE_FLAG_INT | SPV_REFLECT_TYPE_FLAG_BOOL)) {+    switch(bit_width) {+      case 32:+        *p_format = signedness ? SPV_REFLECT_FORMAT_R32_SINT : SPV_REFLECT_FORMAT_R32_UINT; break;+        break;+      case 64:+        *p_format = signedness ? SPV_REFLECT_FORMAT_R64_SINT : SPV_REFLECT_FORMAT_R64_UINT; break;+    }        +    result = SPV_REFLECT_RESULT_SUCCESS;+  }+  else if (p_type->type_flags & SPV_REFLECT_TYPE_FLAG_STRUCT) {+    *p_format = SPV_REFLECT_FORMAT_UNDEFINED;+    result = SPV_REFLECT_RESULT_SUCCESS;+  }+  return result;+}++static SpvReflectResult ParseInterfaceVariable(+  SpvReflectPrvParser*            p_parser,+  const SpvReflectPrvDecorations* p_var_node_decorations,+  const SpvReflectPrvDecorations* p_type_node_decorations,+  SpvReflectShaderModule*         p_module,+  SpvReflectTypeDescription*      p_type,+  SpvReflectInterfaceVariable*    p_var,+  bool*                           p_has_built_in+)+{+  SpvReflectPrvNode* p_type_node = FindNode(p_parser, p_type->id);+  if (IsNull(p_type_node)) {+    return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;+  }++  if (p_type->member_count > 0) {+    p_var->member_count = p_type->member_count;+    p_var->members = (SpvReflectInterfaceVariable*)calloc(p_var->member_count, sizeof(*p_var->members));+    if (IsNull(p_var->members)) {+      return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;+    }++    for (uint32_t member_index = 0; member_index < p_type_node->member_count; ++member_index) {+      SpvReflectPrvDecorations* p_member_decorations = &p_type_node->member_decorations[member_index];+      SpvReflectTypeDescription* p_member_type = &p_type->members[member_index];+      SpvReflectInterfaceVariable* p_member_var = &p_var->members[member_index];+      SpvReflectResult result = ParseInterfaceVariable(p_parser, NULL, p_member_decorations, p_module, p_member_type, p_member_var, p_has_built_in);+      if (result != SPV_REFLECT_RESULT_SUCCESS) {+        SPV_REFLECT_ASSERT(false);+        return result;+      }+    }+  }++  p_var->name = p_type_node->name;+  p_var->decoration_flags = ApplyDecorations(p_type_node_decorations);+  if (p_var_node_decorations != NULL) {+    p_var->decoration_flags |= ApplyDecorations(p_var_node_decorations);+  }+  p_var->built_in = p_type_node_decorations->built_in;+  ApplyNumericTraits(p_type, &p_var->numeric);+  if (p_type->op == SpvOpTypeArray) {+    ApplyArrayTraits(p_type, &p_var->array);+  }++  p_var->type_description = p_type;++  *p_has_built_in |= p_type_node_decorations->is_built_in;++  // Only parse format for interface variables that are input or output+  if ((p_var->storage_class == SpvStorageClassInput) || (p_var->storage_class == SpvStorageClassOutput)) {+    SpvReflectResult result = ParseFormat(p_var->type_description, &p_var->format);+    if (result != SPV_REFLECT_RESULT_SUCCESS) {+      SPV_REFLECT_ASSERT(false);+      return result;+    }+  }++  return SPV_REFLECT_RESULT_SUCCESS;+}++static SpvReflectResult ParseInterfaceVariables(+  SpvReflectPrvParser*    p_parser,+  SpvReflectShaderModule* p_module,+  SpvReflectEntryPoint*   p_entry,+  uint32_t                interface_variable_count,+  uint32_t*               p_interface_variable_ids+)+{+  if (interface_variable_count == 0) {+    return SPV_REFLECT_RESULT_SUCCESS;+  }++  p_entry->interface_variable_count = interface_variable_count;+  p_entry->input_variable_count = 0;+  p_entry->output_variable_count = 0;  +  for (size_t i = 0; i < interface_variable_count; ++i) {+    uint32_t var_result_id = *(p_interface_variable_ids + i);+    SpvReflectPrvNode* p_node = FindNode(p_parser, var_result_id);+    if (IsNull(p_node)) {+      return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;+    }+ +    if (p_node->storage_class == SpvStorageClassInput) {+      p_entry->input_variable_count += 1;+    }+    else if (p_node->storage_class == SpvStorageClassOutput) {+      p_entry->output_variable_count += 1;+    }+ }+ + if (p_entry->input_variable_count > 0) {+   p_entry->input_variables = (SpvReflectInterfaceVariable**)calloc(p_entry->input_variable_count, sizeof(*(p_entry->input_variables)));+   if (IsNull(p_entry->input_variables)) {+     return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;+   }+ }+ + if (p_entry->output_variable_count > 0) {+   p_entry->output_variables = (SpvReflectInterfaceVariable**)calloc(p_entry->output_variable_count, sizeof(*(p_entry->output_variables)));+   if (IsNull(p_entry->output_variables)) {+     return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;+   }+ }++  if (p_entry->interface_variable_count > 0) {+    p_entry->interface_variables = (SpvReflectInterfaceVariable*)calloc(p_entry->interface_variable_count, sizeof(*(p_entry->interface_variables)));+    if (IsNull(p_entry->interface_variables)) {+      return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;+    }+  }++  size_t input_index = 0;+  size_t output_index = 0;+  for (size_t i = 0; i < interface_variable_count; ++i) {+    uint32_t var_result_id = *(p_interface_variable_ids + i);+    SpvReflectPrvNode* p_node = FindNode(p_parser, var_result_id);+    if (IsNull(p_node)) {+      return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;+    }++    SpvReflectTypeDescription* p_type = FindType(p_module, p_node->type_id);+    if (IsNull(p_node)) {+      return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;+    }+    // If the type is a pointer, resolve it+    if (p_type->op == SpvOpTypePointer) {+      // Find the type's node+      SpvReflectPrvNode* p_type_node = FindNode(p_parser, p_type->id);+      if (IsNull(p_type_node)) {+        return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;+      }+      // Should be the resolved type+      p_type = FindType(p_module, p_type_node->type_id);+      if (IsNull(p_type)) {+        return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;+      }+    }++    SpvReflectPrvNode* p_type_node = FindNode(p_parser, p_type->id);+    if (IsNull(p_type_node)) {+      return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;+    }++    SpvReflectInterfaceVariable* p_var = &(p_entry->interface_variables[i]);+    p_var->storage_class  = p_node->storage_class;++    bool has_built_in = p_node->decorations.is_built_in;+    SpvReflectResult result = ParseInterfaceVariable(+      p_parser,+      &p_node->decorations,+      &p_type_node->decorations,+      p_module,+      p_type,+      p_var,+      &has_built_in);+    if (result != SPV_REFLECT_RESULT_SUCCESS) {+      SPV_REFLECT_ASSERT(false);+      return result;+    }++    // Input and output variables+    if (p_var->storage_class == SpvStorageClassInput) {+      p_entry->input_variables[input_index] = p_var;+       ++input_index;+    }+    else if (p_node->storage_class == SpvStorageClassOutput) {+      p_entry->output_variables[output_index] = p_var;+      ++output_index;+    }++    // SPIR-V result id+    p_var->spirv_id = p_node->result_id;+    // Name+    p_var->name = p_node->name;+    // Semantic+    p_var->semantic = p_node->decorations.semantic.value;++    // Decorate with built-in if any member is built-in+    if (has_built_in) {+      p_var->decoration_flags |= SPV_REFLECT_DECORATION_BUILT_IN;+    }++    // Location is decorated on OpVariable node, not the type node.+    p_var->location = p_node->decorations.location.value;+    p_var->word_offset.location = p_node->decorations.location.word_offset;++    // Built in+    if (p_node->decorations.is_built_in) {+      p_var->built_in = p_node->decorations.built_in;+    }+  }++  return SPV_REFLECT_RESULT_SUCCESS;+}++static SpvReflectResult EnumerateAllPushConstants(+  SpvReflectShaderModule* p_module,+  size_t*                 p_push_constant_count,+  uint32_t**              p_push_constants+)+{+  *p_push_constant_count = p_module->push_constant_block_count;+  if (*p_push_constant_count == 0) {+    return SPV_REFLECT_RESULT_SUCCESS;+  }+  *p_push_constants = (uint32_t*)calloc(*p_push_constant_count, sizeof(**p_push_constants));++  if (IsNull(*p_push_constants)) {+    return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;+  }++  for (size_t i = 0; i < *p_push_constant_count; ++i) {+    (*p_push_constants)[i] = p_module->push_constant_blocks[i].spirv_id;+  }+  qsort(*p_push_constants, *p_push_constant_count, sizeof(**p_push_constants),+        SortCompareUint32);+  return SPV_REFLECT_RESULT_SUCCESS;+}++static SpvReflectResult TraverseCallGraph(+  SpvReflectPrvParser*   p_parser,+  SpvReflectPrvFunction* p_func,+  size_t*                p_func_count,+  uint32_t*              p_func_ids,+  uint32_t               depth+)+{+  if (depth > p_parser->function_count) {+    // Vulkan does not permit recursion (Vulkan spec Appendix A):+    //   "Recursion: The static function-call graph for an entry point must not+    //    contain cycles."+    return SPV_REFLECT_RESULT_ERROR_SPIRV_RECURSION;+  }+  if (IsNotNull(p_func_ids)) {+    p_func_ids[(*p_func_count)++] = p_func->id;+  } else {+    ++*p_func_count;+  }+  for (size_t i = 0; i < p_func->callee_count; ++i) {+    SpvReflectResult result = TraverseCallGraph(+        p_parser, p_func->callee_ptrs[i], p_func_count, p_func_ids, depth + 1);+    if (result != SPV_REFLECT_RESULT_SUCCESS) {+      return result;+    }+  }+  return SPV_REFLECT_RESULT_SUCCESS;+}++static SpvReflectResult ParseStaticallyUsedResources(+  SpvReflectPrvParser*    p_parser,+  SpvReflectShaderModule* p_module,+  SpvReflectEntryPoint*   p_entry,+  size_t                  uniform_count,+  uint32_t*               uniforms,+  size_t                  push_constant_count,+  uint32_t*               push_constants+)+{+  // Find function with the right id+  SpvReflectPrvFunction* p_func = NULL;+  for (size_t i = 0; i < p_parser->function_count; ++i) {+    if (p_parser->functions[i].id == p_entry->id) {+      p_func = &(p_parser->functions[i]);+      break;+    }+  }+  if (p_func == NULL) {+    return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;+  }++  size_t called_function_count = 0;+  SpvReflectResult result = TraverseCallGraph(+    p_parser,+    p_func,+    &called_function_count,+    NULL,+    0);+  if (result != SPV_REFLECT_RESULT_SUCCESS) {+    return result;+  }++  uint32_t* p_called_functions = NULL;+  if (called_function_count > 0) {+    p_called_functions = (uint32_t*)calloc(called_function_count, sizeof(*p_called_functions));+    if (IsNull(p_called_functions)) {+      return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;+    }+  }++  called_function_count = 0;+  result = TraverseCallGraph(+    p_parser,+    p_func,+    &called_function_count,+    p_called_functions,+    0);+  if (result != SPV_REFLECT_RESULT_SUCCESS) {+    return result;+  }++  if (called_function_count > 0) {+    qsort(+      p_called_functions, +      called_function_count, +      sizeof(*p_called_functions),+      SortCompareUint32);+  }+  called_function_count = DedupSortedUint32(p_called_functions, called_function_count);++  uint32_t used_variable_count = 0;+  for (size_t i = 0, j = 0; i < called_function_count; ++i) {+    // No need to bounds check j because a missing ID issue would have been+    // found during TraverseCallGraph+    while (p_parser->functions[j].id != p_called_functions[i]) {+      ++j;+    }+    used_variable_count += p_parser->functions[j].accessed_ptr_count;+  }+  uint32_t* used_variables = NULL;+  if (used_variable_count > 0) {+    used_variables = (uint32_t*)calloc(used_variable_count,+                                       sizeof(*used_variables));+    if (IsNull(used_variables)) {+      SafeFree(p_called_functions);+      return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;+    }+  }+  used_variable_count = 0;+  for (size_t i = 0, j = 0; i < called_function_count; ++i) {+    while (p_parser->functions[j].id != p_called_functions[i]) {+      ++j;+    }++    memcpy(&used_variables[used_variable_count],+           p_parser->functions[j].accessed_ptrs,+           p_parser->functions[j].accessed_ptr_count * sizeof(*used_variables));+    used_variable_count += p_parser->functions[j].accessed_ptr_count;+  }+  SafeFree(p_called_functions);++  if (used_variable_count > 0) {+    qsort(used_variables, used_variable_count, sizeof(*used_variables),+          SortCompareUint32);+  }+  used_variable_count = (uint32_t)DedupSortedUint32(used_variables, +                                                    used_variable_count);++  // Do set intersection to find the used uniform and push constants+  size_t used_uniform_count = 0;+  //+  SpvReflectResult result0 = IntersectSortedUint32(+    used_variables,+    used_variable_count,+    uniforms, +    uniform_count,+    &p_entry->used_uniforms,+    &used_uniform_count);++  size_t used_push_constant_count = 0;+  //+  SpvReflectResult result1 = IntersectSortedUint32(+    used_variables, +    used_variable_count,+    push_constants, +    push_constant_count,+    &p_entry->used_push_constants,+    &used_push_constant_count);++  for (uint32_t j = 0; j < p_module->descriptor_binding_count; ++j) {+    SpvReflectDescriptorBinding* p_binding = &p_module->descriptor_bindings[j];+    bool found = SearchSortedUint32(+      used_variables,+      used_variable_count,+      p_binding->spirv_id);+    if (found) {+      p_binding->accessed = 1;+    }+  }++  SafeFree(used_variables);+  if (result0 != SPV_REFLECT_RESULT_SUCCESS) {+    return result0;+  }+  if (result1 != SPV_REFLECT_RESULT_SUCCESS) {+    return result1;+  }++  p_entry->used_uniform_count = (uint32_t)used_uniform_count;+  p_entry->used_push_constant_count = (uint32_t)used_push_constant_count;++  return SPV_REFLECT_RESULT_SUCCESS;+}++static SpvReflectResult ParseEntryPoints(+  SpvReflectPrvParser*    p_parser, +  SpvReflectShaderModule* p_module)+{+  if (p_parser->entry_point_count == 0) {+    return SPV_REFLECT_RESULT_SUCCESS;+  }++  p_module->entry_point_count = p_parser->entry_point_count;+  p_module->entry_points = (SpvReflectEntryPoint*)calloc(p_module->entry_point_count,+                                                         sizeof(*(p_module->entry_points)));+  if (IsNull(p_module->entry_points)) {+    return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;+  }++  SpvReflectResult result;+  size_t uniform_count = 0;+  uint32_t* uniforms = NULL;+  if ((result = EnumerateAllUniforms(p_module, &uniform_count, &uniforms)) !=+       SPV_REFLECT_RESULT_SUCCESS) {+    return result;+  }+  size_t push_constant_count = 0;+  uint32_t* push_constants = NULL;+  if ((result = EnumerateAllPushConstants(p_module, &push_constant_count, &push_constants)) !=+       SPV_REFLECT_RESULT_SUCCESS) {+    return result;+  }++  size_t entry_point_index = 0;+  for (size_t i = 0; entry_point_index < p_parser->entry_point_count && i < p_parser->node_count; ++i) {+    SpvReflectPrvNode* p_node = &(p_parser->nodes[i]);+    if (p_node->op != SpvOpEntryPoint) {+      continue;+    }++    SpvReflectEntryPoint* p_entry_point = &(p_module->entry_points[entry_point_index]);+    CHECKED_READU32_CAST(p_parser, p_node->word_offset + 1, SpvExecutionModel, p_entry_point->spirv_execution_model);+    CHECKED_READU32(p_parser, p_node->word_offset + 2, p_entry_point->id);++    switch (p_entry_point->spirv_execution_model) {+      default: break;+      case SpvExecutionModelVertex                 : p_entry_point->shader_stage = SPV_REFLECT_SHADER_STAGE_VERTEX_BIT; break;+      case SpvExecutionModelTessellationControl    : p_entry_point->shader_stage = SPV_REFLECT_SHADER_STAGE_TESSELLATION_CONTROL_BIT; break;+      case SpvExecutionModelTessellationEvaluation : p_entry_point->shader_stage = SPV_REFLECT_SHADER_STAGE_TESSELLATION_EVALUATION_BIT; break;+      case SpvExecutionModelGeometry               : p_entry_point->shader_stage = SPV_REFLECT_SHADER_STAGE_GEOMETRY_BIT; break;+      case SpvExecutionModelFragment               : p_entry_point->shader_stage = SPV_REFLECT_SHADER_STAGE_FRAGMENT_BIT; break;+      case SpvExecutionModelGLCompute              : p_entry_point->shader_stage = SPV_REFLECT_SHADER_STAGE_COMPUTE_BIT; break;+      case SpvExecutionModelTaskNV                 : p_entry_point->shader_stage = SPV_REFLECT_SHADER_STAGE_TASK_BIT_NV; break;+      case SpvExecutionModelMeshNV                 : p_entry_point->shader_stage = SPV_REFLECT_SHADER_STAGE_MESH_BIT_NV; break;+      case SpvExecutionModelRayGenerationKHR       : p_entry_point->shader_stage = SPV_REFLECT_SHADER_STAGE_RAYGEN_BIT_KHR; break;+      case SpvExecutionModelIntersectionKHR        : p_entry_point->shader_stage = SPV_REFLECT_SHADER_STAGE_INTERSECTION_BIT_KHR; break;+      case SpvExecutionModelAnyHitKHR              : p_entry_point->shader_stage = SPV_REFLECT_SHADER_STAGE_ANY_HIT_BIT_KHR; break;+      case SpvExecutionModelClosestHitKHR          : p_entry_point->shader_stage = SPV_REFLECT_SHADER_STAGE_CLOSEST_HIT_BIT_KHR; break;+      case SpvExecutionModelMissKHR                : p_entry_point->shader_stage = SPV_REFLECT_SHADER_STAGE_MISS_BIT_KHR; break;+      case SpvExecutionModelCallableKHR            : p_entry_point->shader_stage = SPV_REFLECT_SHADER_STAGE_CALLABLE_BIT_KHR; break;+    }++    ++entry_point_index;++    // Name length is required to calculate next operand+    uint32_t name_start_word_offset = 3;+    uint32_t name_length_with_terminator = 0;+    result = ReadStr(p_parser, p_node->word_offset + name_start_word_offset, 0, p_node->word_count, &name_length_with_terminator, NULL);+    if (result != SPV_REFLECT_RESULT_SUCCESS) {+      return result;+    }+    p_entry_point->name = (const char*)(p_parser->spirv_code + p_node->word_offset + name_start_word_offset);++    uint32_t name_word_count = RoundUp(name_length_with_terminator, SPIRV_WORD_SIZE) / SPIRV_WORD_SIZE;+    uint32_t interface_variable_count = (p_node->word_count - (name_start_word_offset + name_word_count));+    uint32_t* p_interface_variables = NULL;+    if (interface_variable_count > 0) {+      p_interface_variables = (uint32_t*)calloc(interface_variable_count, sizeof(*(p_interface_variables)));+      if (IsNull(p_interface_variables)) {+        return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;+      }+    }++    for (uint32_t var_index = 0; var_index < interface_variable_count; ++var_index) {+      uint32_t var_result_id = (uint32_t)INVALID_VALUE;+      uint32_t offset = name_start_word_offset + name_word_count + var_index;+      CHECKED_READU32(p_parser, p_node->word_offset + offset, var_result_id);+      p_interface_variables[var_index] = var_result_id;+    }++    result = ParseInterfaceVariables(+      p_parser,+      p_module,+      p_entry_point,+      interface_variable_count,+      p_interface_variables);+    if (result != SPV_REFLECT_RESULT_SUCCESS) {+      return result;+    }+    SafeFree(p_interface_variables);++    result = ParseStaticallyUsedResources(+      p_parser,+      p_module,+      p_entry_point,+      uniform_count,+      uniforms,+      push_constant_count,+      push_constants);+    if (result != SPV_REFLECT_RESULT_SUCCESS) {+      return result;+    }+  }++  SafeFree(uniforms);+  SafeFree(push_constants);++  return SPV_REFLECT_RESULT_SUCCESS;+}++static SpvReflectResult ParseExecutionModes(+  SpvReflectPrvParser*    p_parser,+  SpvReflectShaderModule* p_module)+{+  assert(IsNotNull(p_parser));+  assert(IsNotNull(p_parser->nodes));+  assert(IsNotNull(p_module));++  if (IsNotNull(p_parser) && IsNotNull(p_parser->spirv_code) && IsNotNull(p_parser->nodes)) {+    for (size_t node_idx = 0; node_idx < p_parser->node_count; ++node_idx) {+      SpvReflectPrvNode* p_node = &(p_parser->nodes[node_idx]);+      if (p_node->op != SpvOpExecutionMode) {+        continue;+      }++      // Read entry point id+      uint32_t entry_point_id = 0;+      CHECKED_READU32(p_parser, p_node->word_offset + 1, entry_point_id);++      // Find entry point+      SpvReflectEntryPoint* p_entry_point = NULL;+      for (size_t entry_point_idx = 0; entry_point_idx < p_module->entry_point_count; ++entry_point_idx) {+        if (p_module->entry_points[entry_point_idx].id == entry_point_id) {+          p_entry_point = &p_module->entry_points[entry_point_idx];+          break;+        }+      }+      // Bail if entry point is null+      if (IsNull(p_entry_point)) {+        return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ENTRY_POINT;+      }++      // Read execution mode+      uint32_t execution_mode = (uint32_t)INVALID_VALUE;+      CHECKED_READU32(p_parser, p_node->word_offset + 2, execution_mode);++      // Parse execution mode+      switch (execution_mode) {+        default: {+          return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_EXECUTION_MODE;+        }+        break;++        case SpvExecutionModeInvocations: {+          CHECKED_READU32(p_parser, p_node->word_offset + 3, p_entry_point->invocations);+        }+        break;++        case SpvExecutionModeSpacingEqual:+        case SpvExecutionModeSpacingFractionalEven:+        case SpvExecutionModeSpacingFractionalOdd:+        case SpvExecutionModeVertexOrderCw:+        case SpvExecutionModeVertexOrderCcw:+        case SpvExecutionModePixelCenterInteger:+        case SpvExecutionModeOriginUpperLeft:+        case SpvExecutionModeOriginLowerLeft:+        case SpvExecutionModeEarlyFragmentTests:+        case SpvExecutionModePointMode:+        case SpvExecutionModeXfb:+        case SpvExecutionModeDepthReplacing:+        case SpvExecutionModeDepthGreater:+        case SpvExecutionModeDepthLess:+        case SpvExecutionModeDepthUnchanged:+          break;++        case SpvExecutionModeLocalSize: {+          CHECKED_READU32(p_parser, p_node->word_offset + 3, p_entry_point->local_size.x);+          CHECKED_READU32(p_parser, p_node->word_offset + 4, p_entry_point->local_size.y);+          CHECKED_READU32(p_parser, p_node->word_offset + 5, p_entry_point->local_size.z);+        }+        break;++        case SpvExecutionModeLocalSizeHint:+        case SpvExecutionModeInputPoints:+        case SpvExecutionModeInputLines:+        case SpvExecutionModeInputLinesAdjacency:+        case SpvExecutionModeTriangles:+        case SpvExecutionModeInputTrianglesAdjacency:+        case SpvExecutionModeQuads:+        case SpvExecutionModeIsolines:+        case SpvExecutionModeOutputVertices: {+          CHECKED_READU32(p_parser, p_node->word_offset + 3, p_entry_point->output_vertices);+        }+        break;++        case SpvExecutionModeOutputPoints:+        case SpvExecutionModeOutputLineStrip:+        case SpvExecutionModeOutputTriangleStrip:+        case SpvExecutionModeVecTypeHint:+        case SpvExecutionModeContractionOff:+        case SpvExecutionModeInitializer:+        case SpvExecutionModeFinalizer:+        case SpvExecutionModeSubgroupSize:+        case SpvExecutionModeSubgroupsPerWorkgroup:+        case SpvExecutionModeSubgroupsPerWorkgroupId:+        case SpvExecutionModeLocalSizeId:+        case SpvExecutionModeLocalSizeHintId:+        case SpvExecutionModePostDepthCoverage:+        case SpvExecutionModeDenormPreserve:+        case SpvExecutionModeDenormFlushToZero:+        case SpvExecutionModeSignedZeroInfNanPreserve:+        case SpvExecutionModeRoundingModeRTE:+        case SpvExecutionModeRoundingModeRTZ:+        case SpvExecutionModeStencilRefReplacingEXT:+        case SpvExecutionModeOutputLinesNV:+        case SpvExecutionModeOutputPrimitivesNV:+        case SpvExecutionModeOutputTrianglesNV:+          break;+      }+      p_entry_point->execution_mode_count++;+    }+    uint32_t* indices = (uint32_t*)calloc(p_module->entry_point_count, sizeof(indices));+    if (IsNull(indices)) {+      return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;+    }+    for (size_t entry_point_idx = 0; entry_point_idx < p_module->entry_point_count; ++entry_point_idx) {+      SpvReflectEntryPoint* p_entry_point = &p_module->entry_points[entry_point_idx];+      p_entry_point->execution_modes =+          (SpvExecutionMode*)calloc(p_entry_point->execution_mode_count, sizeof(*p_entry_point->execution_modes));+      if (IsNull(p_entry_point->execution_modes)) {+        SafeFree(indices);+        return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;+      }+    }++    for (size_t node_idx = 0; node_idx < p_parser->node_count; ++node_idx) {+      SpvReflectPrvNode* p_node = &(p_parser->nodes[node_idx]);+      if (p_node->op != SpvOpExecutionMode) {+        continue;+      }++      // Read entry point id+      uint32_t entry_point_id = 0;+      CHECKED_READU32(p_parser, p_node->word_offset + 1, entry_point_id);++      // Find entry point+      SpvReflectEntryPoint* p_entry_point = NULL;+      uint32_t* idx = NULL;+      for (size_t entry_point_idx = 0; entry_point_idx < p_module->entry_point_count; ++entry_point_idx) {+        if (p_module->entry_points[entry_point_idx].id == entry_point_id) {+          p_entry_point = &p_module->entry_points[entry_point_idx];+          idx = &indices[entry_point_idx];+          break;+        }+      }++      // Read execution mode+      uint32_t execution_mode = (uint32_t)INVALID_VALUE;+      CHECKED_READU32(p_parser, p_node->word_offset + 2, execution_mode);+      p_entry_point->execution_modes[(*idx)++] = (SpvExecutionMode)execution_mode;+    }+    SafeFree(indices);+  }+  return SPV_REFLECT_RESULT_SUCCESS;+}++static SpvReflectResult ParsePushConstantBlocks(+  SpvReflectPrvParser*    p_parser, +  SpvReflectShaderModule* p_module)+{+  for (size_t i = 0; i < p_parser->node_count; ++i) {+    SpvReflectPrvNode* p_node = &(p_parser->nodes[i]);+    if ((p_node->op != SpvOpVariable) || (p_node->storage_class != SpvStorageClassPushConstant)) {+      continue;+    }++    p_module->push_constant_block_count += 1;+  }++  if (p_module->push_constant_block_count == 0) {+    return SPV_REFLECT_RESULT_SUCCESS;+  }++  p_module->push_constant_blocks = (SpvReflectBlockVariable*)calloc(p_module->push_constant_block_count, sizeof(*p_module->push_constant_blocks));+  if (IsNull(p_module->push_constant_blocks)) {+    return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;+  }++  uint32_t push_constant_index = 0;+  for (size_t i = 0; i < p_parser->node_count; ++i) {+    SpvReflectPrvNode* p_node = &(p_parser->nodes[i]);+    if ((p_node->op != SpvOpVariable) || (p_node->storage_class != SpvStorageClassPushConstant)) {+      continue;+    }++    SpvReflectTypeDescription* p_type = FindType(p_module, p_node->type_id);+    if (IsNull(p_node)) {+      return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;+    }+    // If the type is a pointer, resolve it+    if (p_type->op == SpvOpTypePointer) {+      // Find the type's node+      SpvReflectPrvNode* p_type_node = FindNode(p_parser, p_type->id);+      if (IsNull(p_type_node)) {+        return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;+      }+      // Should be the resolved type+      p_type = FindType(p_module, p_type_node->type_id);+      if (IsNull(p_type)) {+        return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;+      }+    }++    SpvReflectPrvNode* p_type_node = FindNode(p_parser, p_type->id);+    if (IsNull(p_type_node)) {+      return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;+    }++    SpvReflectBlockVariable* p_push_constant = &p_module->push_constant_blocks[push_constant_index];+    p_push_constant->spirv_id = p_node->result_id;+    SpvReflectResult result = ParseDescriptorBlockVariable(p_parser, p_module, p_type, p_push_constant);+    if (result != SPV_REFLECT_RESULT_SUCCESS) {+      return result;+    }+    result = ParseDescriptorBlockVariableSizes(p_parser, p_module, true, false, false, p_push_constant);+    if (result != SPV_REFLECT_RESULT_SUCCESS) {+      return result;+    }++    ++push_constant_index;+  }++  return SPV_REFLECT_RESULT_SUCCESS;+}++static int SortCompareDescriptorSet(const void* a, const void* b)+{+  const SpvReflectDescriptorSet* p_elem_a = (const SpvReflectDescriptorSet*)a;+  const SpvReflectDescriptorSet* p_elem_b = (const SpvReflectDescriptorSet*)b;+  int value = (int)(p_elem_a->set) - (int)(p_elem_b->set);+  // We should never see duplicate descriptor set numbers in a shader; if so, a tiebreaker+  // would be needed here.+  assert(value != 0);+  return value;+}++static SpvReflectResult ParseEntrypointDescriptorSets(SpvReflectShaderModule* p_module) {+  // Update the entry point's sets+  for (uint32_t i = 0; i < p_module->entry_point_count; ++i) {+    SpvReflectEntryPoint* p_entry = &p_module->entry_points[i];+    for (uint32_t j = 0; j < p_entry->descriptor_set_count; ++j) {+      SafeFree(p_entry->descriptor_sets[j].bindings);+    }+    SafeFree(p_entry->descriptor_sets);+    p_entry->descriptor_set_count = 0;+    for (uint32_t j = 0; j < p_module->descriptor_set_count; ++j) {+      const SpvReflectDescriptorSet* p_set = &p_module->descriptor_sets[j];+      for (uint32_t k = 0; k < p_set->binding_count; ++k) {+        bool found = SearchSortedUint32(+          p_entry->used_uniforms,+          p_entry->used_uniform_count,+          p_set->bindings[k]->spirv_id);+        if (found) {+          ++p_entry->descriptor_set_count;+          break;+        }+      }+    }++    p_entry->descriptor_sets = NULL;+    if (p_entry->descriptor_set_count > 0) {+      p_entry->descriptor_sets = (SpvReflectDescriptorSet*)calloc(p_entry->descriptor_set_count,+                                                                  sizeof(*p_entry->descriptor_sets));+      if (IsNull(p_entry->descriptor_sets)) {+        return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;+      }+    }+    p_entry->descriptor_set_count = 0;+    for (uint32_t j = 0; j < p_module->descriptor_set_count; ++j) {+      const SpvReflectDescriptorSet* p_set = &p_module->descriptor_sets[j];+      uint32_t count = 0;+      for (uint32_t k = 0; k < p_set->binding_count; ++k) {+        bool found = SearchSortedUint32(+          p_entry->used_uniforms,+          p_entry->used_uniform_count,+          p_set->bindings[k]->spirv_id);+        if (found) {+          ++count;+        }+      }+      if (count == 0) {+        continue;+      }+      SpvReflectDescriptorSet* p_entry_set = &p_entry->descriptor_sets[+          p_entry->descriptor_set_count++];+      p_entry_set->set = p_set->set;+      p_entry_set->bindings = (SpvReflectDescriptorBinding**)calloc(count,+                                                                    sizeof(*p_entry_set->bindings));+      if (IsNull(p_entry_set->bindings)) {+        return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;+      }+      for (uint32_t k = 0; k < p_set->binding_count; ++k) {+        bool found = SearchSortedUint32(+          p_entry->used_uniforms,+          p_entry->used_uniform_count,+          p_set->bindings[k]->spirv_id);+        if (found) {+          p_entry_set->bindings[p_entry_set->binding_count++] = p_set->bindings[k];+        }+      }+    }+  }++  return SPV_REFLECT_RESULT_SUCCESS;+}++static SpvReflectResult ParseDescriptorSets(SpvReflectShaderModule* p_module)+{+  // Count the descriptors in each set+  for (uint32_t i = 0; i < p_module->descriptor_binding_count; ++i) {+    SpvReflectDescriptorBinding* p_descriptor = &(p_module->descriptor_bindings[i]);++    // Look for a target set using the descriptor's set number+    SpvReflectDescriptorSet* p_target_set = NULL;+    for (uint32_t j = 0; j < SPV_REFLECT_MAX_DESCRIPTOR_SETS; ++j) {+      SpvReflectDescriptorSet* p_set = &p_module->descriptor_sets[j];+      if (p_set->set == p_descriptor->set) {+        p_target_set = p_set;+        break;+      }+    }++    // If a target set isn't found, find the first available one.+    if (IsNull(p_target_set)) {+      for (uint32_t j = 0; j < SPV_REFLECT_MAX_DESCRIPTOR_SETS; ++j) {+        SpvReflectDescriptorSet* p_set = &p_module->descriptor_sets[j];+        if (p_set->set == (uint32_t)INVALID_VALUE) {+          p_target_set = p_set;+          p_target_set->set = p_descriptor->set;+          break;+        }+      }+    }++    if (IsNull(p_target_set)) {+      return SPV_REFLECT_RESULT_ERROR_INTERNAL_ERROR;+    }++    p_target_set->binding_count += 1;+  }++  // Count the descriptor sets+  for (uint32_t i = 0; i < SPV_REFLECT_MAX_DESCRIPTOR_SETS; ++i) {+    const SpvReflectDescriptorSet* p_set = &p_module->descriptor_sets[i];+    if (p_set->set != (uint32_t)INVALID_VALUE) {+      p_module->descriptor_set_count += 1;+    }+  }++  // Sort the descriptor sets based on numbers+  if (p_module->descriptor_set_count > 0) {+    qsort(p_module->descriptor_sets,+          p_module->descriptor_set_count,+          sizeof(*(p_module->descriptor_sets)),+          SortCompareDescriptorSet);+  }++  // Build descriptor pointer array+  for (uint32_t i = 0; i <p_module->descriptor_set_count; ++i) {+    SpvReflectDescriptorSet* p_set = &(p_module->descriptor_sets[i]);+    p_set->bindings = (SpvReflectDescriptorBinding **)calloc(p_set->binding_count, sizeof(*(p_set->bindings)));++    uint32_t descriptor_index = 0;+    for (uint32_t j = 0; j < p_module->descriptor_binding_count; ++j) {+      SpvReflectDescriptorBinding* p_descriptor = &(p_module->descriptor_bindings[j]);+      if (p_descriptor->set == p_set->set) {+        assert(descriptor_index < p_set->binding_count);+        p_set->bindings[descriptor_index] = p_descriptor;+        ++descriptor_index;+      }+    }+  }++  return ParseEntrypointDescriptorSets(p_module);+}++static SpvReflectResult DisambiguateStorageBufferSrvUav(SpvReflectShaderModule* p_module)+{+  if (p_module->descriptor_binding_count == 0) {+    return SPV_REFLECT_RESULT_SUCCESS;+  }++  for (uint32_t descriptor_index = 0; descriptor_index < p_module->descriptor_binding_count; ++descriptor_index) {+    SpvReflectDescriptorBinding* p_descriptor = &(p_module->descriptor_bindings[descriptor_index]);+    // Skip everything that isn't a STORAGE_BUFFER descriptor+    if (p_descriptor->descriptor_type != SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER) {+      continue;+    }++    //+    // Vulkan doesn't disambiguate between SRVs and UAVs so they+    // come back as STORAGE_BUFFER. The block parsing process will+    // mark a block as non-writable should any member of the block+    // or its descendants are non-writable.+    //+    if (p_descriptor->block.decoration_flags & SPV_REFLECT_DECORATION_NON_WRITABLE) {+      p_descriptor->resource_type = SPV_REFLECT_RESOURCE_FLAG_SRV;+    }+  }++  return SPV_REFLECT_RESULT_SUCCESS;+}++static SpvReflectResult SynchronizeDescriptorSets(SpvReflectShaderModule* p_module)+{+  // Free and reset all descriptor set numbers+  for (uint32_t i = 0; i < SPV_REFLECT_MAX_DESCRIPTOR_SETS; ++i) {+    SpvReflectDescriptorSet* p_set = &p_module->descriptor_sets[i];+    SafeFree(p_set->bindings);+    p_set->binding_count = 0;+    p_set->set = (uint32_t)INVALID_VALUE;+  }+  // Set descriptor set count to zero+  p_module->descriptor_set_count = 0;++  SpvReflectResult result = ParseDescriptorSets(p_module);+  return result;+}++static SpvReflectResult CreateShaderModule(+  uint32_t                 flags,+  size_t                   size,+  const void*              p_code,+  SpvReflectShaderModule*  p_module+)+{+  // Initialize all module fields to zero+  memset(p_module, 0, sizeof(*p_module));++  // Allocate module internals+#ifdef __cplusplus+  p_module->_internal = (SpvReflectShaderModule::Internal*)calloc(1, sizeof(*(p_module->_internal)));+#else+  p_module->_internal = calloc(1, sizeof(*(p_module->_internal)));+#endif+  if (IsNull(p_module->_internal)) {+    return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;+  }+  // Copy flags+  p_module->_internal->module_flags = flags;+  // Figure out if we need to copy the SPIR-V code or not+  if (flags & SPV_REFLECT_MODULE_FLAG_NO_COPY) {+    // Set internal size and pointer to args passed in+    p_module->_internal->spirv_size = size;+#if defined(__cplusplus)+    p_module->_internal->spirv_code = const_cast<uint32_t*>(static_cast<const uint32_t*>(p_code)); // cast that const away+#else+    p_module->_internal->spirv_code = (void*)p_code; // cast that const away+#endif+    p_module->_internal->spirv_word_count = (uint32_t)(size / SPIRV_WORD_SIZE);+  }+  else {+    // Allocate SPIR-V code storage+    p_module->_internal->spirv_size = size;+    p_module->_internal->spirv_code = (uint32_t*)calloc(1, p_module->_internal->spirv_size);+    p_module->_internal->spirv_word_count = (uint32_t)(size / SPIRV_WORD_SIZE);+    if (IsNull(p_module->_internal->spirv_code)) {+      SafeFree(p_module->_internal);+      return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;+    }+    // Copy SPIR-V to code storage+    memcpy(p_module->_internal->spirv_code, p_code, size);+  }++  SpvReflectPrvParser parser = { 0 };+  SpvReflectResult result = CreateParser(p_module->_internal->spirv_size,+                                         p_module->_internal->spirv_code,+                                         &parser);++  // Generator+  {+    const uint32_t* p_ptr = (const uint32_t*)p_module->_internal->spirv_code;+    p_module->generator = (SpvReflectGenerator)((*(p_ptr + 2) & 0xFFFF0000) >> 16);+  }++  if (result == SPV_REFLECT_RESULT_SUCCESS) {+    result = ParseNodes(&parser);+    SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS);+  }+  if (result == SPV_REFLECT_RESULT_SUCCESS) {+    result = ParseStrings(&parser);+    SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS);+  }+  if (result == SPV_REFLECT_RESULT_SUCCESS) {+    result = ParseSource(&parser, p_module);+    SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS);+  }+  if (result == SPV_REFLECT_RESULT_SUCCESS) {+    result = ParseFunctions(&parser);+    SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS);+  }+  if (result == SPV_REFLECT_RESULT_SUCCESS) {+    result = ParseMemberCounts(&parser);+    SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS);+  }+  if (result == SPV_REFLECT_RESULT_SUCCESS) {+    result = ParseNames(&parser);+    SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS);+  }+  if (result == SPV_REFLECT_RESULT_SUCCESS) {+    result = ParseDecorations(&parser);+    SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS);+  }++  // Start of reflection data parsing+  if (result == SPV_REFLECT_RESULT_SUCCESS) {+    p_module->source_language = parser.source_language;+    p_module->source_language_version = parser.source_language_version;++    // Zero out descriptor set data+    p_module->descriptor_set_count = 0;+    memset(p_module->descriptor_sets, 0, SPV_REFLECT_MAX_DESCRIPTOR_SETS * sizeof(*p_module->descriptor_sets));+    // Initialize descriptor set numbers+    for (uint32_t set_number = 0; set_number < SPV_REFLECT_MAX_DESCRIPTOR_SETS; ++set_number) {+      p_module->descriptor_sets[set_number].set = (uint32_t)INVALID_VALUE;+    }+  }+  if (result == SPV_REFLECT_RESULT_SUCCESS) {+    result = ParseTypes(&parser, p_module);+    SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS);+  }+  if (result == SPV_REFLECT_RESULT_SUCCESS) {+    result = ParseDescriptorBindings(&parser, p_module);+    SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS);+  }+  if (result == SPV_REFLECT_RESULT_SUCCESS) {+    result = ParseDescriptorType(p_module);+    SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS);+  }+  if (result == SPV_REFLECT_RESULT_SUCCESS) {+    result = ParseUAVCounterBindings(p_module);+    SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS);+  }+  if (result == SPV_REFLECT_RESULT_SUCCESS) {+    result = ParseDescriptorBlocks(&parser, p_module);+    SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS);+  }+  if (result == SPV_REFLECT_RESULT_SUCCESS) {+    result = ParsePushConstantBlocks(&parser, p_module);+    SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS);+  }+  if (result == SPV_REFLECT_RESULT_SUCCESS) {+    result = ParseEntryPoints(&parser, p_module);+    SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS);+  }+  if (result == SPV_REFLECT_RESULT_SUCCESS) {+    result = ParseCapabilities(&parser, p_module);+    SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS);+  }+  if (result == SPV_REFLECT_RESULT_SUCCESS && p_module->entry_point_count > 0) {+    SpvReflectEntryPoint* p_entry = &(p_module->entry_points[0]);+    p_module->entry_point_name = p_entry->name;+    p_module->entry_point_id = p_entry->id;+    p_module->spirv_execution_model = p_entry->spirv_execution_model;+    p_module->shader_stage = p_entry->shader_stage;+    p_module->input_variable_count = p_entry->input_variable_count;+    p_module->input_variables = p_entry->input_variables;+    p_module->output_variable_count = p_entry->output_variable_count;+    p_module->output_variables = p_entry->output_variables;+    p_module->interface_variable_count = p_entry->interface_variable_count;+    p_module->interface_variables = p_entry->interface_variables;+  }+  if (result == SPV_REFLECT_RESULT_SUCCESS) {+    result = DisambiguateStorageBufferSrvUav(p_module);+    SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS);+  }+  if (result == SPV_REFLECT_RESULT_SUCCESS) {+    result = SynchronizeDescriptorSets(p_module);+    SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS);+  }+  if (result == SPV_REFLECT_RESULT_SUCCESS) {+    result = ParseExecutionModes(&parser, p_module);+    SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS);+  }++  // Destroy module if parse was not successful+  if (result != SPV_REFLECT_RESULT_SUCCESS) {+    spvReflectDestroyShaderModule(p_module);+  }++  DestroyParser(&parser);++  return result;+}++SpvReflectResult spvReflectCreateShaderModule(+  size_t                   size,+  const void*              p_code,+  SpvReflectShaderModule*  p_module+)+{+    return CreateShaderModule(0, size, p_code, p_module);+}++SpvReflectResult spvReflectCreateShaderModule2(+  uint32_t                 flags,+  size_t                   size,+  const void*              p_code,+  SpvReflectShaderModule*  p_module+)+{+  return CreateShaderModule(flags, size, p_code, p_module);+}++SpvReflectResult spvReflectGetShaderModule(+  size_t                   size,+  const void*              p_code,+  SpvReflectShaderModule*  p_module+)+{+    return spvReflectCreateShaderModule(size, p_code, p_module);+}++static void SafeFreeTypes(SpvReflectTypeDescription* p_type)+{+  if (IsNull(p_type)) {+    return;+  }++  if (IsNotNull(p_type->members)) {+    for (size_t i = 0; i < p_type->member_count; ++i) {+      SpvReflectTypeDescription* p_member = &p_type->members[i];+      SafeFreeTypes(p_member);+    }++    SafeFree(p_type->members);+    p_type->members = NULL;+  }+}++static void SafeFreeBlockVariables(SpvReflectBlockVariable* p_block)+{+  if (IsNull(p_block)) {+    return;+  }++  if (IsNotNull(p_block->members)) {+    for (size_t i = 0; i < p_block->member_count; ++i) {+      SpvReflectBlockVariable* p_member = &p_block->members[i];+      SafeFreeBlockVariables(p_member);+    }++    SafeFree(p_block->members);+    p_block->members = NULL;+  }+}++static void SafeFreeInterfaceVariable(SpvReflectInterfaceVariable* p_interface)+{+  if (IsNull(p_interface)) {+    return;+  }++  if (IsNotNull(p_interface->members)) {+    for (size_t i = 0; i < p_interface->member_count; ++i) {+      SpvReflectInterfaceVariable* p_member = &p_interface->members[i];+      SafeFreeInterfaceVariable(p_member);+    }++    SafeFree(p_interface->members);+    p_interface->members = NULL;+  }+}++void spvReflectDestroyShaderModule(SpvReflectShaderModule* p_module)+{+  if (IsNull(p_module->_internal)) {+    return;+  }++  SafeFree(p_module->source_source);++  // Descriptor set bindings+  for (size_t i = 0; i < p_module->descriptor_set_count; ++i) {+    SpvReflectDescriptorSet* p_set = &p_module->descriptor_sets[i];+    free(p_set->bindings);+  }++  // Descriptor binding blocks+  for (size_t i = 0; i < p_module->descriptor_binding_count; ++i) {+    SpvReflectDescriptorBinding* p_descriptor = &p_module->descriptor_bindings[i];+    SafeFreeBlockVariables(&p_descriptor->block);+  }+  SafeFree(p_module->descriptor_bindings);++  // Entry points+  for (size_t i = 0; i < p_module->entry_point_count; ++i) {+    SpvReflectEntryPoint* p_entry = &p_module->entry_points[i];+    for (size_t j = 0; j < p_entry->interface_variable_count; j++) {+      SafeFreeInterfaceVariable(&p_entry->interface_variables[j]);+    }+    for (uint32_t j = 0; j < p_entry->descriptor_set_count; ++j) {+      SafeFree(p_entry->descriptor_sets[j].bindings);+    }+    SafeFree(p_entry->descriptor_sets);+    SafeFree(p_entry->input_variables);+    SafeFree(p_entry->output_variables);+    SafeFree(p_entry->interface_variables);+    SafeFree(p_entry->used_uniforms);+    SafeFree(p_entry->used_push_constants);+    SafeFree(p_entry->execution_modes);+  }+  SafeFree(p_module->capabilities);+  SafeFree(p_module->entry_points);++  // Push constants+  for (size_t i = 0; i < p_module->push_constant_block_count; ++i) {+    SafeFreeBlockVariables(&p_module->push_constant_blocks[i]);+  }+  SafeFree(p_module->push_constant_blocks);++  // Type infos+  for (size_t i = 0; i < p_module->_internal->type_description_count; ++i) {+    SpvReflectTypeDescription* p_type = &p_module->_internal->type_descriptions[i];+    if (IsNotNull(p_type->members)) {+      SafeFreeTypes(p_type);+    }+    SafeFree(p_type->members);+  }+  SafeFree(p_module->_internal->type_descriptions);++  // Free SPIR-V code if there was a copy+  if ((p_module->_internal->module_flags & SPV_REFLECT_MODULE_FLAG_NO_COPY) == 0) {+    SafeFree(p_module->_internal->spirv_code);+  }+  // Free internal+  SafeFree(p_module->_internal);+}++uint32_t spvReflectGetCodeSize(const SpvReflectShaderModule* p_module)+{+  if (IsNull(p_module)) {+    return 0;+  }++  return (uint32_t)(p_module->_internal->spirv_size);+}++const uint32_t* spvReflectGetCode(const SpvReflectShaderModule* p_module)+{+  if (IsNull(p_module)) {+    return NULL;+  }++  return p_module->_internal->spirv_code;+}++const SpvReflectEntryPoint* spvReflectGetEntryPoint(+  const SpvReflectShaderModule* p_module,+  const char*                   entry_point+) {+  if (IsNull(p_module) || IsNull(entry_point)) {+    return NULL;+  }++  for (uint32_t i = 0; i < p_module->entry_point_count; ++i) {+    if (strcmp(p_module->entry_points[i].name, entry_point) == 0) {+      return &p_module->entry_points[i];+    }+  }+  return NULL;+}++SpvReflectResult spvReflectEnumerateDescriptorBindings(+  const SpvReflectShaderModule*  p_module,+  uint32_t*                      p_count,+  SpvReflectDescriptorBinding**  pp_bindings+)+{+  if (IsNull(p_module)) {+    return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;+  }+  if (IsNull(p_count)) {+    return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;+  }++  if (IsNotNull(pp_bindings)) {+    if (*p_count != p_module->descriptor_binding_count) {+      return SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH;+    }++    for (uint32_t index = 0; index < *p_count; ++index) {+      SpvReflectDescriptorBinding* p_bindings = (SpvReflectDescriptorBinding*)&p_module->descriptor_bindings[index];+      pp_bindings[index] = p_bindings;+    }+  }+  else {+    *p_count = p_module->descriptor_binding_count;+  }++  return SPV_REFLECT_RESULT_SUCCESS;+}++SpvReflectResult spvReflectEnumerateEntryPointDescriptorBindings(+  const SpvReflectShaderModule*  p_module,+  const char*                    entry_point,+  uint32_t*                      p_count,+  SpvReflectDescriptorBinding**  pp_bindings+)+{+  if (IsNull(p_module)) {+    return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;+  }+  if (IsNull(p_count)) {+    return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;+  }++  const SpvReflectEntryPoint* p_entry =+      spvReflectGetEntryPoint(p_module, entry_point);+  if (IsNull(p_entry)) {+    return SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND;+  }++  uint32_t count = 0;+  for (uint32_t i = 0; i < p_module->descriptor_binding_count; ++i) {+    bool found = SearchSortedUint32(+      p_entry->used_uniforms,+      p_entry->used_uniform_count,+      p_module->descriptor_bindings[i].spirv_id);+    if (found) {+      if (IsNotNull(pp_bindings)) {+        if (count >= *p_count) {+          return SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH;+        }+        pp_bindings[count++] = (SpvReflectDescriptorBinding*)&p_module->descriptor_bindings[i];+      } else {+        ++count;+      }+    }+  }+  if (IsNotNull(pp_bindings)) {+    if (count != *p_count) {+      return SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH;+    }+  } else {+    *p_count = count;+  }+  return SPV_REFLECT_RESULT_SUCCESS;+}++SpvReflectResult spvReflectEnumerateDescriptorSets(+  const SpvReflectShaderModule* p_module,+  uint32_t*                     p_count,+  SpvReflectDescriptorSet**     pp_sets+)+{+  if (IsNull(p_module)) {+    return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;+  }+  if (IsNull(p_count)) {+    return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;+  }++  if (IsNotNull(pp_sets)) {+    if (*p_count != p_module->descriptor_set_count) {+      return SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH;+    }++    for (uint32_t index = 0; index < *p_count; ++index) {+      SpvReflectDescriptorSet* p_set = (SpvReflectDescriptorSet*)&p_module->descriptor_sets[index];+      pp_sets[index] = p_set;+    }+  }+  else {+    *p_count = p_module->descriptor_set_count;+  }++  return SPV_REFLECT_RESULT_SUCCESS;+}++SpvReflectResult spvReflectEnumerateEntryPointDescriptorSets(+  const SpvReflectShaderModule* p_module,+  const char*                   entry_point,+  uint32_t*                     p_count,+  SpvReflectDescriptorSet**     pp_sets+)+{+  if (IsNull(p_module)) {+    return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;+  }+  if (IsNull(p_count)) {+    return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;+  }++  const SpvReflectEntryPoint* p_entry =+      spvReflectGetEntryPoint(p_module, entry_point);+  if (IsNull(p_entry)) {+    return SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND;+  }++  if (IsNotNull(pp_sets)) {+    if (*p_count != p_entry->descriptor_set_count) {+      return SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH;+    }++    for (uint32_t index = 0; index < *p_count; ++index) {+      SpvReflectDescriptorSet* p_set = (SpvReflectDescriptorSet*)&p_entry->descriptor_sets[index];+      pp_sets[index] = p_set;+    }+  }+  else {+    *p_count = p_entry->descriptor_set_count;+  }++  return SPV_REFLECT_RESULT_SUCCESS;+}++SpvReflectResult spvReflectEnumerateInterfaceVariables(+  const SpvReflectShaderModule* p_module,+  uint32_t*                     p_count,+  SpvReflectInterfaceVariable** pp_variables+)+{+  if (IsNull(p_module)) {+    return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;+  }+  if (IsNull(p_count)) {+    return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;+  }++  if (IsNotNull(pp_variables)) {+    if (*p_count != p_module->interface_variable_count) {+      return SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH;+    }++    for (uint32_t index = 0; index < *p_count; ++index) {+      SpvReflectInterfaceVariable* p_var = &p_module->interface_variables[index];+      pp_variables[index] = p_var;+    }+  }+  else {+    *p_count = p_module->interface_variable_count;+  }++  return SPV_REFLECT_RESULT_SUCCESS;+}++SpvReflectResult spvReflectEnumerateEntryPointInterfaceVariables(+  const SpvReflectShaderModule* p_module,+  const char*                   entry_point,+  uint32_t*                     p_count,+  SpvReflectInterfaceVariable** pp_variables+)+{+  if (IsNull(p_module)) {+    return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;+  }+  if (IsNull(p_count)) {+    return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;+  }++  const SpvReflectEntryPoint* p_entry =+      spvReflectGetEntryPoint(p_module, entry_point);+  if (IsNull(p_entry)) {+    return SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND;+  }++  if (IsNotNull(pp_variables)) {+    if (*p_count != p_entry->interface_variable_count) {+      return SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH;+    }++    for (uint32_t index = 0; index < *p_count; ++index) {+      SpvReflectInterfaceVariable* p_var = &p_entry->interface_variables[index];+      pp_variables[index] = p_var;+    }+  }+  else {+    *p_count = p_entry->interface_variable_count;+  }++  return SPV_REFLECT_RESULT_SUCCESS;+}++SpvReflectResult spvReflectEnumerateInputVariables(+  const SpvReflectShaderModule* p_module,+  uint32_t*                     p_count,+  SpvReflectInterfaceVariable** pp_variables+)+{+  if (IsNull(p_module)) {+    return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;+  }+  if (IsNull(p_count)) {+    return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;+  }++  if (IsNotNull(pp_variables)) {+    if (*p_count != p_module->input_variable_count) {+      return SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH;+    }++    for (uint32_t index = 0; index < *p_count; ++index) {+      SpvReflectInterfaceVariable* p_var = p_module->input_variables[index];+      pp_variables[index] = p_var;+    }+  }+  else {+    *p_count = p_module->input_variable_count;+  }++  return SPV_REFLECT_RESULT_SUCCESS;+}++SpvReflectResult spvReflectEnumerateEntryPointInputVariables(+  const SpvReflectShaderModule* p_module,+  const char*                   entry_point,+  uint32_t*                     p_count,+  SpvReflectInterfaceVariable** pp_variables+)+{+  if (IsNull(p_module)) {+    return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;+  }+  if (IsNull(p_count)) {+    return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;+  }++  const SpvReflectEntryPoint* p_entry =+      spvReflectGetEntryPoint(p_module, entry_point);+  if (IsNull(p_entry)) {+    return SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND;+  }++  if (IsNotNull(pp_variables)) {+    if (*p_count != p_entry->input_variable_count) {+      return SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH;+    }++    for (uint32_t index = 0; index < *p_count; ++index) {+      SpvReflectInterfaceVariable* p_var = p_entry->input_variables[index];+      pp_variables[index] = p_var;+    }+  }+  else {+    *p_count = p_entry->input_variable_count;+  }++  return SPV_REFLECT_RESULT_SUCCESS;+}++SpvReflectResult spvReflectEnumerateOutputVariables(+  const SpvReflectShaderModule* p_module,+  uint32_t*                     p_count,+  SpvReflectInterfaceVariable** pp_variables+)+{+  if (IsNull(p_module)) {+    return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;+  }+  if (IsNull(p_count)) {+    return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;+  }++  if (IsNotNull(pp_variables)) {+    if (*p_count != p_module->output_variable_count) {+      return SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH;+    }++    for (uint32_t index = 0; index < *p_count; ++index) {+      SpvReflectInterfaceVariable* p_var = p_module->output_variables[index];+      pp_variables[index] = p_var;+    }+  }+  else {+    *p_count = p_module->output_variable_count;+  }++  return SPV_REFLECT_RESULT_SUCCESS;+}++SpvReflectResult spvReflectEnumerateEntryPointOutputVariables(+  const SpvReflectShaderModule* p_module,+  const char*                   entry_point,+  uint32_t*                     p_count,+  SpvReflectInterfaceVariable** pp_variables+)+{+  if (IsNull(p_module)) {+    return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;+  }+  if (IsNull(p_count)) {+    return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;+  }++  const SpvReflectEntryPoint* p_entry =+      spvReflectGetEntryPoint(p_module, entry_point);+  if (IsNull(p_entry)) {+    return SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND;+  }++  if (IsNotNull(pp_variables)) {+    if (*p_count != p_entry->output_variable_count) {+      return SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH;+    }++    for (uint32_t index = 0; index < *p_count; ++index) {+      SpvReflectInterfaceVariable* p_var = p_entry->output_variables[index];+      pp_variables[index] = p_var;+    }+  }+  else {+    *p_count = p_entry->output_variable_count;+  }++  return SPV_REFLECT_RESULT_SUCCESS;+}++SpvReflectResult spvReflectEnumeratePushConstantBlocks(+  const SpvReflectShaderModule* p_module,+  uint32_t*                     p_count,+  SpvReflectBlockVariable**     pp_blocks+)+{+  if (IsNull(p_module)) {+    return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;+  }+  if (IsNull(p_count)) {+    return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;+  }++  if (pp_blocks != NULL) {+    if (*p_count != p_module->push_constant_block_count) {+      return SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH;+    }++    for (uint32_t index = 0; index < *p_count; ++index) {+      SpvReflectBlockVariable* p_push_constant_blocks = (SpvReflectBlockVariable*)&p_module->push_constant_blocks[index];+      pp_blocks[index] = p_push_constant_blocks;+    }+  }+  else {+    *p_count = p_module->push_constant_block_count;+  }++  return SPV_REFLECT_RESULT_SUCCESS;+}+SpvReflectResult spvReflectEnumeratePushConstants(+  const SpvReflectShaderModule* p_module,+  uint32_t*                     p_count,+  SpvReflectBlockVariable**     pp_blocks+)+{+  return spvReflectEnumeratePushConstantBlocks(p_module, p_count, pp_blocks);+}++SpvReflectResult spvReflectEnumerateEntryPointPushConstantBlocks(+  const SpvReflectShaderModule* p_module,+  const char*                   entry_point,+  uint32_t*                     p_count,+  SpvReflectBlockVariable**     pp_blocks+)+{+  if (IsNull(p_module)) {+    return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;+  }+  if (IsNull(p_count)) {+    return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;+  }+++  const SpvReflectEntryPoint* p_entry =+      spvReflectGetEntryPoint(p_module, entry_point);+  if (IsNull(p_entry)) {+    return SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND;+  }++  uint32_t count = 0;+  for (uint32_t i = 0; i < p_module->push_constant_block_count; ++i) {+    bool found = SearchSortedUint32(p_entry->used_push_constants,+                           p_entry->used_push_constant_count,+                           p_module->push_constant_blocks[i].spirv_id);+    if (found) {+      if (IsNotNull(pp_blocks)) {+        if (count >= *p_count) {+          return SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH;+        }+        pp_blocks[count++] = (SpvReflectBlockVariable*)&p_module->push_constant_blocks[i];+      } else {+        ++count;+      }+    }+  }+  if (IsNotNull(pp_blocks)) {+    if (count != *p_count) {+      return SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH;+    }+  } else {+    *p_count = count;+  }+  return SPV_REFLECT_RESULT_SUCCESS;+}++const SpvReflectDescriptorBinding* spvReflectGetDescriptorBinding(+  const SpvReflectShaderModule* p_module,+  uint32_t                      binding_number,+  uint32_t                      set_number,+  SpvReflectResult*             p_result+)+{+  const SpvReflectDescriptorBinding* p_descriptor = NULL;+  if (IsNotNull(p_module)) {+    for (uint32_t index = 0; index < p_module->descriptor_binding_count; ++index) {+      const SpvReflectDescriptorBinding* p_potential = &p_module->descriptor_bindings[index];+      if ((p_potential->binding == binding_number) && (p_potential->set == set_number)) {+        p_descriptor = p_potential;+        break;+      }+    }+  }+  if (IsNotNull(p_result)) {+    *p_result = IsNotNull(p_descriptor)+        ?  SPV_REFLECT_RESULT_SUCCESS+        : (IsNull(p_module) ? SPV_REFLECT_RESULT_ERROR_NULL_POINTER+                            : SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND);+  }+  return p_descriptor;+}++const SpvReflectDescriptorBinding* spvReflectGetEntryPointDescriptorBinding(+  const SpvReflectShaderModule* p_module,+  const char*                   entry_point,+  uint32_t                      binding_number,+  uint32_t                      set_number,+  SpvReflectResult*             p_result+)+{+  const SpvReflectEntryPoint* p_entry =+      spvReflectGetEntryPoint(p_module, entry_point);+  if (IsNull(p_entry)) {+    if (IsNotNull(p_result)) {+      *p_result = SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND;+    }+    return NULL;+  }+  const SpvReflectDescriptorBinding* p_descriptor = NULL;+  if (IsNotNull(p_module)) {+    for (uint32_t index = 0; index < p_module->descriptor_binding_count; ++index) {+      const SpvReflectDescriptorBinding* p_potential = &p_module->descriptor_bindings[index];+      bool found = SearchSortedUint32(+        p_entry->used_uniforms, +        p_entry->used_uniform_count,+        p_potential->spirv_id);+      if ((p_potential->binding == binding_number) && (p_potential->set == set_number) && found) {+        p_descriptor = p_potential;+        break;+      }+    }+  }+  if (IsNotNull(p_result)) {+    *p_result = IsNotNull(p_descriptor)+        ?  SPV_REFLECT_RESULT_SUCCESS+        : (IsNull(p_module) ? SPV_REFLECT_RESULT_ERROR_NULL_POINTER+                            : SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND);+  }+  return p_descriptor;+}++const SpvReflectDescriptorSet* spvReflectGetDescriptorSet(+  const SpvReflectShaderModule* p_module,+  uint32_t                      set_number,+  SpvReflectResult*             p_result+)+{+  const SpvReflectDescriptorSet* p_set = NULL;+  if (IsNotNull(p_module)) {+    for (uint32_t index = 0; index < p_module->descriptor_set_count; ++index) {+      const SpvReflectDescriptorSet* p_potential = &p_module->descriptor_sets[index];+      if (p_potential->set == set_number) {+        p_set = p_potential;+      }+    }+  }+  if (IsNotNull(p_result)) {+    *p_result = IsNotNull(p_set)+        ?  SPV_REFLECT_RESULT_SUCCESS+        : (IsNull(p_module) ? SPV_REFLECT_RESULT_ERROR_NULL_POINTER+                            : SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND);+  }+  return p_set;+}++const SpvReflectDescriptorSet* spvReflectGetEntryPointDescriptorSet(+  const SpvReflectShaderModule* p_module,+  const char*                   entry_point,+  uint32_t                      set_number,+  SpvReflectResult*             p_result)+{+  const SpvReflectDescriptorSet* p_set = NULL;+  if (IsNotNull(p_module)) {+    const SpvReflectEntryPoint* p_entry = spvReflectGetEntryPoint(p_module, entry_point);+    if (IsNull(p_entry)) {+      if (IsNotNull(p_result)) {+        *p_result = SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND;+      }+      return NULL;+    }+    for (uint32_t index = 0; index < p_entry->descriptor_set_count; ++index) {+      const SpvReflectDescriptorSet* p_potential = &p_entry->descriptor_sets[index];+      if (p_potential->set == set_number) {+        p_set = p_potential;+      }+    }+  }+  if (IsNotNull(p_result)) {+    *p_result = IsNotNull(p_set)+        ?  SPV_REFLECT_RESULT_SUCCESS+        : (IsNull(p_module) ? SPV_REFLECT_RESULT_ERROR_NULL_POINTER+                            : SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND);+  }+  return p_set;+}+++const SpvReflectInterfaceVariable* spvReflectGetInputVariableByLocation(+  const SpvReflectShaderModule* p_module,+  uint32_t                      location,+  SpvReflectResult*             p_result+)+{+  if (location == INVALID_VALUE) {+    if (IsNotNull(p_result)) {+      *p_result = SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND;+    }+    return NULL;+  }+  const SpvReflectInterfaceVariable* p_var = NULL;+  if (IsNotNull(p_module)) {+    for (uint32_t index = 0; index < p_module->input_variable_count; ++index) {+      const SpvReflectInterfaceVariable* p_potential = p_module->input_variables[index];+      if (p_potential->location == location) {+        p_var = p_potential;+      }+    }+  }+  if (IsNotNull(p_result)) {+    *p_result = IsNotNull(p_var)+        ?  SPV_REFLECT_RESULT_SUCCESS+        : (IsNull(p_module) ? SPV_REFLECT_RESULT_ERROR_NULL_POINTER+                            : SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND);+  }+  return p_var;+}+const SpvReflectInterfaceVariable* spvReflectGetInputVariable(+  const SpvReflectShaderModule* p_module,+  uint32_t                      location,+  SpvReflectResult*             p_result+)+{+  return spvReflectGetInputVariableByLocation(p_module, location, p_result);+}++const SpvReflectInterfaceVariable* spvReflectGetEntryPointInputVariableByLocation(+  const SpvReflectShaderModule* p_module,+  const char*                   entry_point,+  uint32_t                      location,+  SpvReflectResult*             p_result+)+{+  if (location == INVALID_VALUE) {+    if (IsNotNull(p_result)) {+      *p_result = SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND;+    }+    return NULL;+  }++  const SpvReflectInterfaceVariable* p_var = NULL;+  if (IsNotNull(p_module)) {+    const SpvReflectEntryPoint* p_entry =+        spvReflectGetEntryPoint(p_module, entry_point);+    if (IsNull(p_entry)) {+      if (IsNotNull(p_result)) {+        *p_result = SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND;+      }+      return NULL;+    }+    for (uint32_t index = 0; index < p_entry->input_variable_count; ++index) {+      const SpvReflectInterfaceVariable* p_potential = p_entry->input_variables[index];+      if (p_potential->location == location) {+        p_var = p_potential;+      }+    }+  }+  if (IsNotNull(p_result)) {+    *p_result = IsNotNull(p_var)+        ?  SPV_REFLECT_RESULT_SUCCESS+        : (IsNull(p_module) ? SPV_REFLECT_RESULT_ERROR_NULL_POINTER+                            : SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND);+  }+  return p_var;+}++const SpvReflectInterfaceVariable* spvReflectGetInputVariableBySemantic(+  const SpvReflectShaderModule* p_module,+  const char*                   semantic,+  SpvReflectResult*             p_result+)+{+  if (IsNull(semantic)) {+    if (IsNotNull(p_result)) {+      *p_result = SPV_REFLECT_RESULT_ERROR_NULL_POINTER;+    }+    return NULL;+  }+  if (semantic[0] == '\0') {+    if (IsNotNull(p_result)) {+      *p_result = SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND;+    }+    return NULL;+  }+  const SpvReflectInterfaceVariable* p_var = NULL;+  if (IsNotNull(p_module)) {+    for (uint32_t index = 0; index < p_module->input_variable_count; ++index) {+      const SpvReflectInterfaceVariable* p_potential = p_module->input_variables[index];+      if (p_potential->semantic != NULL && strcmp(p_potential->semantic, semantic) == 0) {+        p_var = p_potential;+      }+    }+  }+  if (IsNotNull(p_result)) {+    *p_result = IsNotNull(p_var)+      ?  SPV_REFLECT_RESULT_SUCCESS+      : (IsNull(p_module) ? SPV_REFLECT_RESULT_ERROR_NULL_POINTER+        : SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND);+  }+  return p_var;+}++const SpvReflectInterfaceVariable* spvReflectGetEntryPointInputVariableBySemantic(+  const SpvReflectShaderModule* p_module,+  const char*                   entry_point,+  const char*                   semantic,+  SpvReflectResult*             p_result+)+{+  if (IsNull(semantic)) {+    if (IsNotNull(p_result)) {+      *p_result = SPV_REFLECT_RESULT_ERROR_NULL_POINTER;+    }+    return NULL;+  }+  if (semantic[0] == '\0') {+    if (IsNotNull(p_result)) {+      *p_result = SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND;+    }+    return NULL;+  }+  const SpvReflectInterfaceVariable* p_var = NULL;+  if (IsNotNull(p_module)) {+    const SpvReflectEntryPoint* p_entry = spvReflectGetEntryPoint(p_module, entry_point);+    if (IsNull(p_entry)) {+      if (IsNotNull(p_result)) {+        *p_result = SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND;+      }+      return NULL;+    }+    for (uint32_t index = 0; index < p_entry->input_variable_count; ++index) {+      const SpvReflectInterfaceVariable* p_potential = p_entry->input_variables[index];+      if (p_potential->semantic != NULL && strcmp(p_potential->semantic, semantic) == 0) {+        p_var = p_potential;+      }+    }+  }+  if (IsNotNull(p_result)) {+    *p_result = IsNotNull(p_var)+      ?  SPV_REFLECT_RESULT_SUCCESS+      : (IsNull(p_module) ? SPV_REFLECT_RESULT_ERROR_NULL_POINTER+        : SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND);+  }+  return p_var;+}++const SpvReflectInterfaceVariable* spvReflectGetOutputVariableByLocation(+  const SpvReflectShaderModule*  p_module,+  uint32_t                       location,+  SpvReflectResult*              p_result+)+{+  if (location == INVALID_VALUE) {+    if (IsNotNull(p_result)) {+      *p_result = SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND;+    }+    return NULL;+  }+  const SpvReflectInterfaceVariable* p_var = NULL;+  if (IsNotNull(p_module)) {+    for (uint32_t index = 0; index < p_module->output_variable_count; ++index) {+      const SpvReflectInterfaceVariable* p_potential = p_module->output_variables[index];+      if (p_potential->location == location) {+        p_var = p_potential;+      }+    }+  }+  if (IsNotNull(p_result)) {+    *p_result = IsNotNull(p_var)+        ?  SPV_REFLECT_RESULT_SUCCESS+        : (IsNull(p_module) ? SPV_REFLECT_RESULT_ERROR_NULL_POINTER+                            : SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND);+  }+  return p_var;+}+const SpvReflectInterfaceVariable* spvReflectGetOutputVariable(+  const SpvReflectShaderModule*  p_module,+  uint32_t                       location,+  SpvReflectResult*              p_result+)+{+  return spvReflectGetOutputVariableByLocation(p_module, location, p_result);+}++const SpvReflectInterfaceVariable* spvReflectGetEntryPointOutputVariableByLocation(+  const SpvReflectShaderModule* p_module,+  const char*                   entry_point,+  uint32_t                      location,+  SpvReflectResult*             p_result+)+{+  if (location == INVALID_VALUE) {+    if (IsNotNull(p_result)) {+      *p_result = SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND;+    }+    return NULL;+  }++  const SpvReflectInterfaceVariable* p_var = NULL;+  if (IsNotNull(p_module)) {+    const SpvReflectEntryPoint* p_entry = spvReflectGetEntryPoint(p_module, entry_point);+    if (IsNull(p_entry)) {+      if (IsNotNull(p_result)) {+        *p_result = SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND;+      }+      return NULL;+    }+    for (uint32_t index = 0; index < p_entry->output_variable_count; ++index) {+      const SpvReflectInterfaceVariable* p_potential = p_entry->output_variables[index];+      if (p_potential->location == location) {+        p_var = p_potential;+      }+    }+  }+  if (IsNotNull(p_result)) {+    *p_result = IsNotNull(p_var)+        ?  SPV_REFLECT_RESULT_SUCCESS+        : (IsNull(p_module) ? SPV_REFLECT_RESULT_ERROR_NULL_POINTER+                            : SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND);+  }+  return p_var;+}++const SpvReflectInterfaceVariable* spvReflectGetOutputVariableBySemantic(+  const SpvReflectShaderModule*  p_module,+  const char*                    semantic,+  SpvReflectResult*              p_result+)+{+  if (IsNull(semantic)) {+    if (IsNotNull(p_result)) {+      *p_result = SPV_REFLECT_RESULT_ERROR_NULL_POINTER;+    }+    return NULL;+  }+  if (semantic[0] == '\0') {+    if (IsNotNull(p_result)) {+      *p_result = SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND;+    }+    return NULL;+  }+  const SpvReflectInterfaceVariable* p_var = NULL;+  if (IsNotNull(p_module)) {+    for (uint32_t index = 0; index < p_module->output_variable_count; ++index) {+      const SpvReflectInterfaceVariable* p_potential = p_module->output_variables[index];+      if (p_potential->semantic != NULL && strcmp(p_potential->semantic, semantic) == 0) {+        p_var = p_potential;+      }+    }+  }+  if (IsNotNull(p_result)) {+    *p_result = IsNotNull(p_var)+        ?  SPV_REFLECT_RESULT_SUCCESS+        : (IsNull(p_module) ? SPV_REFLECT_RESULT_ERROR_NULL_POINTER+                            : SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND);+  }+  return p_var;+}++const SpvReflectInterfaceVariable* spvReflectGetEntryPointOutputVariableBySemantic(+  const SpvReflectShaderModule* p_module,+  const char*                   entry_point,+  const char*                   semantic,+  SpvReflectResult*             p_result)+{+  if (IsNull(semantic)) {+    if (IsNotNull(p_result)) {+      *p_result = SPV_REFLECT_RESULT_ERROR_NULL_POINTER;+    }+    return NULL;+  }+  if (semantic[0] == '\0') {+    if (IsNotNull(p_result)) {+      *p_result = SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND;+    }+    return NULL;+  }+  const SpvReflectInterfaceVariable* p_var = NULL;+  if (IsNotNull(p_module)) {+    const SpvReflectEntryPoint* p_entry = spvReflectGetEntryPoint(p_module, entry_point);+    if (IsNull(p_entry)) {+      if (IsNotNull(p_result)) {+        *p_result = SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND;+      }+      return NULL;+    }+    for (uint32_t index = 0; index < p_entry->output_variable_count; ++index) {+      const SpvReflectInterfaceVariable* p_potential = p_entry->output_variables[index];+      if (p_potential->semantic != NULL && strcmp(p_potential->semantic, semantic) == 0) {+        p_var = p_potential;+      }+    }+  }+  if (IsNotNull(p_result)) {+    *p_result = IsNotNull(p_var)+      ?  SPV_REFLECT_RESULT_SUCCESS+      : (IsNull(p_module) ? SPV_REFLECT_RESULT_ERROR_NULL_POINTER+        : SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND);+  }+  return p_var;+}++const SpvReflectBlockVariable* spvReflectGetPushConstantBlock(+  const SpvReflectShaderModule* p_module,+  uint32_t                      index,+  SpvReflectResult*             p_result+)+{+  const SpvReflectBlockVariable* p_push_constant = NULL;+  if (IsNotNull(p_module)) {+    if (index < p_module->push_constant_block_count) {+      p_push_constant = &p_module->push_constant_blocks[index];+    }+  }+  if (IsNotNull(p_result)) {+    *p_result = IsNotNull(p_push_constant)+        ?  SPV_REFLECT_RESULT_SUCCESS+        : (IsNull(p_module) ? SPV_REFLECT_RESULT_ERROR_NULL_POINTER+                            : SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND);+  }+  return p_push_constant;+}+const SpvReflectBlockVariable* spvReflectGetPushConstant(+  const SpvReflectShaderModule* p_module,+  uint32_t                      index,+  SpvReflectResult*             p_result+)+{+  return spvReflectGetPushConstantBlock(p_module, index, p_result);+}++const SpvReflectBlockVariable* spvReflectGetEntryPointPushConstantBlock(+  const SpvReflectShaderModule*  p_module,+  const char*                    entry_point,+  SpvReflectResult*              p_result)+{+  const SpvReflectBlockVariable* p_push_constant = NULL;+  if (IsNotNull(p_module)) {+    const SpvReflectEntryPoint* p_entry =+        spvReflectGetEntryPoint(p_module, entry_point);+    if (IsNull(p_entry)) {+      if (IsNotNull(p_result)) {+        *p_result = SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND;+      }+      return NULL;+    }+    for (uint32_t i = 0; i < p_module->push_constant_block_count; ++i) {+      bool found = SearchSortedUint32(+        p_entry->used_push_constants,+        p_entry->used_push_constant_count,+        p_module->push_constant_blocks[i].spirv_id);+      if (found) {+        p_push_constant = &p_module->push_constant_blocks[i];+        break;+      }+    }+  }+  if (IsNotNull(p_result)) {+    *p_result = IsNotNull(p_push_constant)+        ?  SPV_REFLECT_RESULT_SUCCESS+        : (IsNull(p_module) ? SPV_REFLECT_RESULT_ERROR_NULL_POINTER+                            : SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND);+  }+  return p_push_constant;+}++SpvReflectResult spvReflectChangeDescriptorBindingNumbers(+  SpvReflectShaderModule*            p_module,+  const SpvReflectDescriptorBinding* p_binding,+  uint32_t                           new_binding_number,+  uint32_t                           new_set_binding+)+{+  if (IsNull(p_module)) {+    return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;+  }+  if (IsNull(p_binding)) {+    return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;+  }++  SpvReflectDescriptorBinding* p_target_descriptor = NULL;+  for (uint32_t index = 0; index < p_module->descriptor_binding_count; ++index) {+    if(&p_module->descriptor_bindings[index] == p_binding) {+      p_target_descriptor = &p_module->descriptor_bindings[index];+      break;+    }+  }++  if (IsNotNull(p_target_descriptor)) {+    if (p_target_descriptor->word_offset.binding > (p_module->_internal->spirv_word_count - 1)) {+      return SPV_REFLECT_RESULT_ERROR_RANGE_EXCEEDED;+    }+    // Binding number+    if (new_binding_number != (uint32_t)SPV_REFLECT_BINDING_NUMBER_DONT_CHANGE) {+      uint32_t* p_code = p_module->_internal->spirv_code + p_target_descriptor->word_offset.binding;+      *p_code = new_binding_number;+      p_target_descriptor->binding = new_binding_number;+    }+    // Set number+    if (new_set_binding != (uint32_t)SPV_REFLECT_SET_NUMBER_DONT_CHANGE) {+      uint32_t* p_code = p_module->_internal->spirv_code + p_target_descriptor->word_offset.set;+      *p_code = new_set_binding;+      p_target_descriptor->set = new_set_binding;+    }+  }++  SpvReflectResult result = SPV_REFLECT_RESULT_SUCCESS;+  if (new_set_binding != (uint32_t)SPV_REFLECT_SET_NUMBER_DONT_CHANGE) {+    result = SynchronizeDescriptorSets(p_module);+  }+  return result;+}+SpvReflectResult spvReflectChangeDescriptorBindingNumber(+  SpvReflectShaderModule*            p_module,+  const SpvReflectDescriptorBinding* p_descriptor_binding,+  uint32_t                           new_binding_number,+  uint32_t                           optional_new_set_number+)+{+  return spvReflectChangeDescriptorBindingNumbers(+    p_module,p_descriptor_binding, +    new_binding_number, +    optional_new_set_number);+}++SpvReflectResult spvReflectChangeDescriptorSetNumber(+  SpvReflectShaderModule*        p_module,+  const SpvReflectDescriptorSet* p_set,+  uint32_t                       new_set_number+)+{+  if (IsNull(p_module)) {+    return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;+  }+  if (IsNull(p_set)) {+    return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;+  }+  SpvReflectDescriptorSet* p_target_set = NULL;+  for (uint32_t index = 0; index < SPV_REFLECT_MAX_DESCRIPTOR_SETS; ++index) {+    // The descriptor sets for specific entry points might not be in this set,+    // so just match on set index.+    if (p_module->descriptor_sets[index].set == p_set->set) {+      p_target_set = (SpvReflectDescriptorSet*)p_set;+      break;+    }+  }++  SpvReflectResult result = SPV_REFLECT_RESULT_SUCCESS;+  if (IsNotNull(p_target_set) && new_set_number != (uint32_t)SPV_REFLECT_SET_NUMBER_DONT_CHANGE) {+    for (uint32_t index = 0; index < p_target_set->binding_count; ++index) {+      SpvReflectDescriptorBinding* p_descriptor = p_target_set->bindings[index];+      if (p_descriptor->word_offset.set > (p_module->_internal->spirv_word_count - 1)) {+        return SPV_REFLECT_RESULT_ERROR_RANGE_EXCEEDED;+      }++      uint32_t* p_code = p_module->_internal->spirv_code + p_descriptor->word_offset.set;+      *p_code = new_set_number;+      p_descriptor->set = new_set_number;+    }++    result = SynchronizeDescriptorSets(p_module);+  }++  return result;+}++static SpvReflectResult ChangeVariableLocation(+  SpvReflectShaderModule*      p_module,+  SpvReflectInterfaceVariable* p_variable,+  uint32_t                     new_location+)+{+  if (p_variable->word_offset.location > (p_module->_internal->spirv_word_count - 1)) {+    return SPV_REFLECT_RESULT_ERROR_RANGE_EXCEEDED;+  }+  uint32_t* p_code = p_module->_internal->spirv_code + p_variable->word_offset.location;+  *p_code = new_location;+  p_variable->location = new_location;+  return SPV_REFLECT_RESULT_SUCCESS;+}++SpvReflectResult spvReflectChangeInputVariableLocation(+  SpvReflectShaderModule*            p_module,+  const SpvReflectInterfaceVariable* p_input_variable,+  uint32_t                           new_location+)+{+  if (IsNull(p_module)) {+    return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;+  }+  if (IsNull(p_input_variable)) {+    return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;+  }+  for (uint32_t index = 0; index < p_module->input_variable_count; ++index) {+    if(p_module->input_variables[index] == p_input_variable) {+      return ChangeVariableLocation(p_module, p_module->input_variables[index], new_location);+    }+  }+  return SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND;+}++SpvReflectResult spvReflectChangeOutputVariableLocation(+  SpvReflectShaderModule*             p_module,+  const SpvReflectInterfaceVariable*  p_output_variable,+  uint32_t                            new_location+)+{+  if (IsNull(p_module)) {+    return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;+  }+  if (IsNull(p_output_variable)) {+    return SPV_REFLECT_RESULT_ERROR_NULL_POINTER;+  }+  for (uint32_t index = 0; index < p_module->output_variable_count; ++index) {+    if(p_module->output_variables[index] == p_output_variable) {+      return ChangeVariableLocation(p_module, p_module->output_variables[index], new_location);+    }+  }+  return SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND;+}++const char* spvReflectSourceLanguage(SpvSourceLanguage source_lang)+{+  switch (source_lang) {+    case SpvSourceLanguageUnknown        : return "Unknown";+    case SpvSourceLanguageESSL           : return "ESSL";+    case SpvSourceLanguageGLSL           : return "GLSL";+    case SpvSourceLanguageOpenCL_C       : return "OpenCL_C";+    case SpvSourceLanguageOpenCL_CPP     : return "OpenCL_CPP";+    case SpvSourceLanguageHLSL           : return "HLSL";+    case SpvSourceLanguageCPP_for_OpenCL : return "CPP_for_OpenCL";+    case SpvSourceLanguageSYCL           : return "SYCL";+    case SpvSourceLanguageMax:+      break;+  }+  return "";+}++const char* spvReflectBlockVariableTypeName(+  const SpvReflectBlockVariable* p_var+)+{+    if (p_var == NULL) {+        return NULL;+    }+    return p_var->type_description->type_name;+}
+ cbits/spirv_reflect.h view
@@ -0,0 +1,2292 @@+/*+ Copyright 2017-2022 Google Inc.++ Licensed under the Apache License, Version 2.0 (the "License");+ you may not use this file except in compliance with the License.+ You may obtain a copy of the License at++ http://www.apache.org/licenses/LICENSE-2.0++ Unless required by applicable law or agreed to in writing, software+ distributed under the License is distributed on an "AS IS" BASIS,+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+ See the License for the specific language governing permissions and+ limitations under the License.+*/++/*++VERSION HISTORY++  1.0   (2018-03-27) Initial public release++*/++/*!++ @file spirv_reflect.h++*/+#ifndef SPIRV_REFLECT_H+#define SPIRV_REFLECT_H++#if defined(SPIRV_REFLECT_USE_SYSTEM_SPIRV_H)+#include <spirv/unified1/spirv.h>+#else+#include "./include/spirv/unified1/spirv.h"+#endif+++#include <stdint.h>+#include <string.h>++#ifdef _MSC_VER+  #define SPV_REFLECT_DEPRECATED(msg_str) __declspec(deprecated("This symbol is deprecated. Details: " msg_str))+#elif defined(__clang__)+  #define SPV_REFLECT_DEPRECATED(msg_str) __attribute__((deprecated(msg_str)))+#elif defined(__GNUC__)+  #if GCC_VERSION >= 40500+    #define SPV_REFLECT_DEPRECATED(msg_str) __attribute__((deprecated(msg_str)))+  #else+    #define SPV_REFLECT_DEPRECATED(msg_str) __attribute__((deprecated))+  #endif+#else+  #define SPV_REFLECT_DEPRECATED(msg_str)+#endif++/*! @enum SpvReflectResult++*/+typedef enum SpvReflectResult {+  SPV_REFLECT_RESULT_SUCCESS,+  SPV_REFLECT_RESULT_NOT_READY,+  SPV_REFLECT_RESULT_ERROR_PARSE_FAILED,+  SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED,+  SPV_REFLECT_RESULT_ERROR_RANGE_EXCEEDED,+  SPV_REFLECT_RESULT_ERROR_NULL_POINTER,+  SPV_REFLECT_RESULT_ERROR_INTERNAL_ERROR,+  SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH,+  SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND,+  SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_CODE_SIZE,+  SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_MAGIC_NUMBER,+  SPV_REFLECT_RESULT_ERROR_SPIRV_UNEXPECTED_EOF,+  SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE,+  SPV_REFLECT_RESULT_ERROR_SPIRV_SET_NUMBER_OVERFLOW,+  SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_STORAGE_CLASS,+  SPV_REFLECT_RESULT_ERROR_SPIRV_RECURSION,+  SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_INSTRUCTION,+  SPV_REFLECT_RESULT_ERROR_SPIRV_UNEXPECTED_BLOCK_DATA,+  SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_BLOCK_MEMBER_REFERENCE,+  SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ENTRY_POINT,+  SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_EXECUTION_MODE,+} SpvReflectResult;++/*! @enum SpvReflectModuleFlagBits++SPV_REFLECT_MODULE_FLAG_NO_COPY - Disables copying of SPIR-V code +  when a SPIRV-Reflect shader module is created. It is the +  responsibility of the calling program to ensure that the pointer+  remains valid and the memory it's pointing to is not freed while+  SPIRV-Reflect operations are taking place. Freeing the backing +  memory will cause undefined behavior or most likely a crash.+  This is flag is intended for cases where the memory overhead of+  storing the copied SPIR-V is undesirable.++*/+typedef enum SpvReflectModuleFlagBits {+  SPV_REFLECT_MODULE_FLAG_NONE    = 0x00000000,+  SPV_REFLECT_MODULE_FLAG_NO_COPY = 0x00000001,+} SpvReflectModuleFlagBits;++typedef uint32_t SpvReflectModuleFlags;++/*! @enum SpvReflectTypeFlagBits++*/+typedef enum SpvReflectTypeFlagBits {+  SPV_REFLECT_TYPE_FLAG_UNDEFINED                       = 0x00000000,+  SPV_REFLECT_TYPE_FLAG_VOID                            = 0x00000001,+  SPV_REFLECT_TYPE_FLAG_BOOL                            = 0x00000002,+  SPV_REFLECT_TYPE_FLAG_INT                             = 0x00000004,+  SPV_REFLECT_TYPE_FLAG_FLOAT                           = 0x00000008,+  SPV_REFLECT_TYPE_FLAG_VECTOR                          = 0x00000100,+  SPV_REFLECT_TYPE_FLAG_MATRIX                          = 0x00000200,+  SPV_REFLECT_TYPE_FLAG_EXTERNAL_IMAGE                  = 0x00010000,+  SPV_REFLECT_TYPE_FLAG_EXTERNAL_SAMPLER                = 0x00020000,+  SPV_REFLECT_TYPE_FLAG_EXTERNAL_SAMPLED_IMAGE          = 0x00040000,+  SPV_REFLECT_TYPE_FLAG_EXTERNAL_BLOCK                  = 0x00080000,+  SPV_REFLECT_TYPE_FLAG_EXTERNAL_ACCELERATION_STRUCTURE = 0x00100000,+  SPV_REFLECT_TYPE_FLAG_EXTERNAL_MASK                   = 0x00FF0000,+  SPV_REFLECT_TYPE_FLAG_STRUCT                          = 0x10000000,+  SPV_REFLECT_TYPE_FLAG_ARRAY                           = 0x20000000,+} SpvReflectTypeFlagBits;++typedef uint32_t SpvReflectTypeFlags;++/*! @enum SpvReflectDecorationBits++NOTE: HLSL row_major and column_major decorations are reversed+      in SPIR-V. Meaning that matrices declrations with row_major+      will get reflected as column_major and vice versa. The+      row and column decorations get appied during the compilation.+      SPIRV-Reflect reads the data as is and does not make any+      attempt to correct it to match what's in the source.++*/+typedef enum SpvReflectDecorationFlagBits {+  SPV_REFLECT_DECORATION_NONE                   = 0x00000000,+  SPV_REFLECT_DECORATION_BLOCK                  = 0x00000001,+  SPV_REFLECT_DECORATION_BUFFER_BLOCK           = 0x00000002,+  SPV_REFLECT_DECORATION_ROW_MAJOR              = 0x00000004,+  SPV_REFLECT_DECORATION_COLUMN_MAJOR           = 0x00000008,+  SPV_REFLECT_DECORATION_BUILT_IN               = 0x00000010,+  SPV_REFLECT_DECORATION_NOPERSPECTIVE          = 0x00000020,+  SPV_REFLECT_DECORATION_FLAT                   = 0x00000040,+  SPV_REFLECT_DECORATION_NON_WRITABLE           = 0x00000080,+  SPV_REFLECT_DECORATION_RELAXED_PRECISION      = 0x00000100,+  SPV_REFLECT_DECORATION_NON_READABLE           = 0x00000200,+} SpvReflectDecorationFlagBits;++typedef uint32_t SpvReflectDecorationFlags;++/*! @enum SpvReflectResourceType++*/+typedef enum SpvReflectResourceType {+  SPV_REFLECT_RESOURCE_FLAG_UNDEFINED           = 0x00000000,+  SPV_REFLECT_RESOURCE_FLAG_SAMPLER             = 0x00000001,+  SPV_REFLECT_RESOURCE_FLAG_CBV                 = 0x00000002,+  SPV_REFLECT_RESOURCE_FLAG_SRV                 = 0x00000004,+  SPV_REFLECT_RESOURCE_FLAG_UAV                 = 0x00000008,+} SpvReflectResourceType;++/*! @enum SpvReflectFormat++*/+typedef enum SpvReflectFormat {+  SPV_REFLECT_FORMAT_UNDEFINED           =   0, // = VK_FORMAT_UNDEFINED+  SPV_REFLECT_FORMAT_R32_UINT            =  98, // = VK_FORMAT_R32_UINT+  SPV_REFLECT_FORMAT_R32_SINT            =  99, // = VK_FORMAT_R32_SINT+  SPV_REFLECT_FORMAT_R32_SFLOAT          = 100, // = VK_FORMAT_R32_SFLOAT+  SPV_REFLECT_FORMAT_R32G32_UINT         = 101, // = VK_FORMAT_R32G32_UINT+  SPV_REFLECT_FORMAT_R32G32_SINT         = 102, // = VK_FORMAT_R32G32_SINT+  SPV_REFLECT_FORMAT_R32G32_SFLOAT       = 103, // = VK_FORMAT_R32G32_SFLOAT+  SPV_REFLECT_FORMAT_R32G32B32_UINT      = 104, // = VK_FORMAT_R32G32B32_UINT+  SPV_REFLECT_FORMAT_R32G32B32_SINT      = 105, // = VK_FORMAT_R32G32B32_SINT+  SPV_REFLECT_FORMAT_R32G32B32_SFLOAT    = 106, // = VK_FORMAT_R32G32B32_SFLOAT+  SPV_REFLECT_FORMAT_R32G32B32A32_UINT   = 107, // = VK_FORMAT_R32G32B32A32_UINT+  SPV_REFLECT_FORMAT_R32G32B32A32_SINT   = 108, // = VK_FORMAT_R32G32B32A32_SINT+  SPV_REFLECT_FORMAT_R32G32B32A32_SFLOAT = 109, // = VK_FORMAT_R32G32B32A32_SFLOAT+  SPV_REFLECT_FORMAT_R64_UINT            = 110, // = VK_FORMAT_R64_UINT+  SPV_REFLECT_FORMAT_R64_SINT            = 111, // = VK_FORMAT_R64_SINT+  SPV_REFLECT_FORMAT_R64_SFLOAT          = 112, // = VK_FORMAT_R64_SFLOAT+  SPV_REFLECT_FORMAT_R64G64_UINT         = 113, // = VK_FORMAT_R64G64_UINT+  SPV_REFLECT_FORMAT_R64G64_SINT         = 114, // = VK_FORMAT_R64G64_SINT+  SPV_REFLECT_FORMAT_R64G64_SFLOAT       = 115, // = VK_FORMAT_R64G64_SFLOAT+  SPV_REFLECT_FORMAT_R64G64B64_UINT      = 116, // = VK_FORMAT_R64G64B64_UINT+  SPV_REFLECT_FORMAT_R64G64B64_SINT      = 117, // = VK_FORMAT_R64G64B64_SINT+  SPV_REFLECT_FORMAT_R64G64B64_SFLOAT    = 118, // = VK_FORMAT_R64G64B64_SFLOAT+  SPV_REFLECT_FORMAT_R64G64B64A64_UINT   = 119, // = VK_FORMAT_R64G64B64A64_UINT+  SPV_REFLECT_FORMAT_R64G64B64A64_SINT   = 120, // = VK_FORMAT_R64G64B64A64_SINT+  SPV_REFLECT_FORMAT_R64G64B64A64_SFLOAT = 121, // = VK_FORMAT_R64G64B64A64_SFLOAT+} SpvReflectFormat;++/*! @enum SpvReflectVariableFlagBits++*/+enum SpvReflectVariableFlagBits{+  SPV_REFLECT_VARIABLE_FLAGS_NONE   = 0x00000000,+  SPV_REFLECT_VARIABLE_FLAGS_UNUSED = 0x00000001,+};++typedef uint32_t SpvReflectVariableFlags;++/*! @enum SpvReflectDescriptorType++*/+typedef enum SpvReflectDescriptorType {+  SPV_REFLECT_DESCRIPTOR_TYPE_SAMPLER                    =  0,        // = VK_DESCRIPTOR_TYPE_SAMPLER+  SPV_REFLECT_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER     =  1,        // = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER+  SPV_REFLECT_DESCRIPTOR_TYPE_SAMPLED_IMAGE              =  2,        // = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE+  SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_IMAGE              =  3,        // = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE+  SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER       =  4,        // = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER+  SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER       =  5,        // = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER+  SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_BUFFER             =  6,        // = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER+  SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER             =  7,        // = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER+  SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC     =  8,        // = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC+  SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC     =  9,        // = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC+  SPV_REFLECT_DESCRIPTOR_TYPE_INPUT_ATTACHMENT           = 10,        // = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT+  SPV_REFLECT_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR = 1000150000 // = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR+} SpvReflectDescriptorType;++/*! @enum SpvReflectShaderStageFlagBits++*/+typedef enum SpvReflectShaderStageFlagBits {+  SPV_REFLECT_SHADER_STAGE_VERTEX_BIT                  = 0x00000001, // = VK_SHADER_STAGE_VERTEX_BIT+  SPV_REFLECT_SHADER_STAGE_TESSELLATION_CONTROL_BIT    = 0x00000002, // = VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT+  SPV_REFLECT_SHADER_STAGE_TESSELLATION_EVALUATION_BIT = 0x00000004, // = VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT+  SPV_REFLECT_SHADER_STAGE_GEOMETRY_BIT                = 0x00000008, // = VK_SHADER_STAGE_GEOMETRY_BIT+  SPV_REFLECT_SHADER_STAGE_FRAGMENT_BIT                = 0x00000010, // = VK_SHADER_STAGE_FRAGMENT_BIT+  SPV_REFLECT_SHADER_STAGE_COMPUTE_BIT                 = 0x00000020, // = VK_SHADER_STAGE_COMPUTE_BIT+  SPV_REFLECT_SHADER_STAGE_TASK_BIT_NV                 = 0x00000040, // = VK_SHADER_STAGE_TASK_BIT_NV+  SPV_REFLECT_SHADER_STAGE_MESH_BIT_NV                 = 0x00000080, // = VK_SHADER_STAGE_MESH_BIT_NV+  SPV_REFLECT_SHADER_STAGE_RAYGEN_BIT_KHR              = 0x00000100, // = VK_SHADER_STAGE_RAYGEN_BIT_KHR+  SPV_REFLECT_SHADER_STAGE_ANY_HIT_BIT_KHR             = 0x00000200, // = VK_SHADER_STAGE_ANY_HIT_BIT_KHR+  SPV_REFLECT_SHADER_STAGE_CLOSEST_HIT_BIT_KHR         = 0x00000400, // = VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR+  SPV_REFLECT_SHADER_STAGE_MISS_BIT_KHR                = 0x00000800, // = VK_SHADER_STAGE_MISS_BIT_KHR+  SPV_REFLECT_SHADER_STAGE_INTERSECTION_BIT_KHR        = 0x00001000, // = VK_SHADER_STAGE_INTERSECTION_BIT_KHR+  SPV_REFLECT_SHADER_STAGE_CALLABLE_BIT_KHR            = 0x00002000, // = VK_SHADER_STAGE_CALLABLE_BIT_KHR++} SpvReflectShaderStageFlagBits;++/*! @enum SpvReflectGenerator++*/+typedef enum SpvReflectGenerator {+  SPV_REFLECT_GENERATOR_KHRONOS_LLVM_SPIRV_TRANSLATOR         = 6,+  SPV_REFLECT_GENERATOR_KHRONOS_SPIRV_TOOLS_ASSEMBLER         = 7,+  SPV_REFLECT_GENERATOR_KHRONOS_GLSLANG_REFERENCE_FRONT_END   = 8,+  SPV_REFLECT_GENERATOR_GOOGLE_SHADERC_OVER_GLSLANG           = 13,+  SPV_REFLECT_GENERATOR_GOOGLE_SPIREGG                        = 14,+  SPV_REFLECT_GENERATOR_GOOGLE_RSPIRV                         = 15,+  SPV_REFLECT_GENERATOR_X_LEGEND_MESA_MESAIR_SPIRV_TRANSLATOR = 16,+  SPV_REFLECT_GENERATOR_KHRONOS_SPIRV_TOOLS_LINKER            = 17,+  SPV_REFLECT_GENERATOR_WINE_VKD3D_SHADER_COMPILER            = 18,+  SPV_REFLECT_GENERATOR_CLAY_CLAY_SHADER_COMPILER             = 19,+} SpvReflectGenerator;++enum {+  SPV_REFLECT_MAX_ARRAY_DIMS                    = 32,+  SPV_REFLECT_MAX_DESCRIPTOR_SETS               = 64,+};++enum {+  SPV_REFLECT_BINDING_NUMBER_DONT_CHANGE        = ~0,+  SPV_REFLECT_SET_NUMBER_DONT_CHANGE            = ~0+};++typedef struct SpvReflectNumericTraits {+  struct Scalar {+    uint32_t                        width;+    uint32_t                        signedness;+  } scalar;++  struct Vector {+    uint32_t                        component_count;+  } vector;++  struct Matrix {+    uint32_t                        column_count;+    uint32_t                        row_count;+    uint32_t                        stride; // Measured in bytes+  } matrix;+} SpvReflectNumericTraits;++typedef struct SpvReflectImageTraits {+  SpvDim                            dim;+  uint32_t                          depth;+  uint32_t                          arrayed;+  uint32_t                          ms; // 0: single-sampled; 1: multisampled+  uint32_t                          sampled;+  SpvImageFormat                    image_format;+} SpvReflectImageTraits;++typedef struct SpvReflectArrayTraits {+  uint32_t                          dims_count;+  // Each entry is: 0xFFFFFFFF for a specialization constant dimension,+  // 0 for a runtime array dimension, and the array length otherwise.+  uint32_t                          dims[SPV_REFLECT_MAX_ARRAY_DIMS];+  // Stores Ids for dimensions that are specialization constants+  uint32_t                          spec_constant_op_ids[SPV_REFLECT_MAX_ARRAY_DIMS];+  uint32_t                          stride; // Measured in bytes+} SpvReflectArrayTraits;++typedef struct SpvReflectBindingArrayTraits {+  uint32_t                          dims_count;+  uint32_t                          dims[SPV_REFLECT_MAX_ARRAY_DIMS];+} SpvReflectBindingArrayTraits;++/*! @struct SpvReflectTypeDescription++*/+typedef struct SpvReflectTypeDescription {+  uint32_t                          id;+  SpvOp                             op;+  const char*                       type_name;+  const char*                       struct_member_name;+  SpvStorageClass                   storage_class;+  SpvReflectTypeFlags               type_flags;+  SpvReflectDecorationFlags         decoration_flags;++  struct Traits {+    SpvReflectNumericTraits         numeric;+    SpvReflectImageTraits           image;+    SpvReflectArrayTraits           array;+  } traits;++  uint32_t                          member_count;+  struct SpvReflectTypeDescription* members;+} SpvReflectTypeDescription;+++/*! @struct SpvReflectInterfaceVariable++*/+typedef struct SpvReflectInterfaceVariable {+  uint32_t                            spirv_id;+  const char*                         name;+  uint32_t                            location;+  SpvStorageClass                     storage_class;+  const char*                         semantic;+  SpvReflectDecorationFlags           decoration_flags;+  SpvBuiltIn                          built_in;+  SpvReflectNumericTraits             numeric;+  SpvReflectArrayTraits               array;++  uint32_t                            member_count;+  struct SpvReflectInterfaceVariable* members;++  SpvReflectFormat                    format;++  // NOTE: SPIR-V shares type references for variables+  //       that have the same underlying type. This means+  //       that the same type name will appear for multiple+  //       variables.+  SpvReflectTypeDescription*          type_description;++  struct {+    uint32_t                          location;+  } word_offset;+} SpvReflectInterfaceVariable;++/*! @struct SpvReflectBlockVariable++*/+typedef struct SpvReflectBlockVariable {+  uint32_t                          spirv_id;+  const char*                       name;+  uint32_t                          offset;           // Measured in bytes+  uint32_t                          absolute_offset;  // Measured in bytes+  uint32_t                          size;             // Measured in bytes+  uint32_t                          padded_size;      // Measured in bytes+  SpvReflectDecorationFlags         decoration_flags;+  SpvReflectNumericTraits           numeric;+  SpvReflectArrayTraits             array;+  SpvReflectVariableFlags           flags;++  uint32_t                          member_count;+  struct SpvReflectBlockVariable*   members;++  SpvReflectTypeDescription*        type_description;+} SpvReflectBlockVariable;++/*! @struct SpvReflectDescriptorBinding++*/+typedef struct SpvReflectDescriptorBinding {+  uint32_t                            spirv_id;+  const char*                         name;+  uint32_t                            binding;+  uint32_t                            input_attachment_index;+  uint32_t                            set;+  SpvReflectDescriptorType            descriptor_type;+  SpvReflectResourceType              resource_type;+  SpvReflectImageTraits               image;+  SpvReflectBlockVariable             block;+  SpvReflectBindingArrayTraits        array;+  uint32_t                            count;+  uint32_t                            accessed;+  uint32_t                            uav_counter_id;+  struct SpvReflectDescriptorBinding* uav_counter_binding;++  SpvReflectTypeDescription*          type_description;++  struct {+    uint32_t                          binding;+    uint32_t                          set;+  } word_offset;++  SpvReflectDecorationFlags           decoration_flags;+} SpvReflectDescriptorBinding;++/*! @struct SpvReflectDescriptorSet++*/+typedef struct SpvReflectDescriptorSet {+  uint32_t                          set;+  uint32_t                          binding_count;+  SpvReflectDescriptorBinding**     bindings;+} SpvReflectDescriptorSet;++/*! @struct SpvReflectEntryPoint++ */+typedef struct SpvReflectEntryPoint {+  const char*                       name;+  uint32_t                          id;++  SpvExecutionModel                 spirv_execution_model;+  SpvReflectShaderStageFlagBits     shader_stage;++  uint32_t                          input_variable_count;  +  SpvReflectInterfaceVariable**     input_variables;       +  uint32_t                          output_variable_count; +  SpvReflectInterfaceVariable**     output_variables;      +  uint32_t                          interface_variable_count;+  SpvReflectInterfaceVariable*      interface_variables;++  uint32_t                          descriptor_set_count;+  SpvReflectDescriptorSet*          descriptor_sets;++  uint32_t                          used_uniform_count;+  uint32_t*                         used_uniforms;+  uint32_t                          used_push_constant_count;+  uint32_t*                         used_push_constants;++  uint32_t                          execution_mode_count;+  SpvExecutionMode*                 execution_modes;++  struct LocalSize {+    uint32_t                        x;+    uint32_t                        y;+    uint32_t                        z;+  } local_size;+  uint32_t                          invocations; // valid for geometry+  uint32_t                          output_vertices; // valid for geometry, tesselation+} SpvReflectEntryPoint;++/*! @struct SpvReflectCapability++*/+typedef struct SpvReflectCapability {+  SpvCapability                     value;+  uint32_t                          word_offset;+} SpvReflectCapability;++/*! @struct SpvReflectShaderModule++*/+typedef struct SpvReflectShaderModule {+  SpvReflectGenerator               generator;+  const char*                       entry_point_name;+  uint32_t                          entry_point_id;+  uint32_t                          entry_point_count;+  SpvReflectEntryPoint*             entry_points;+  SpvSourceLanguage                 source_language;+  uint32_t                          source_language_version;+  const char*                       source_file;+  const char*                       source_source;+  uint32_t                          capability_count;+  SpvReflectCapability*             capabilities;+  SpvExecutionModel                 spirv_execution_model;                            // Uses value(s) from first entry point+  SpvReflectShaderStageFlagBits     shader_stage;                                     // Uses value(s) from first entry point+  uint32_t                          descriptor_binding_count;                         // Uses value(s) from first entry point+  SpvReflectDescriptorBinding*      descriptor_bindings;                              // Uses value(s) from first entry point+  uint32_t                          descriptor_set_count;                             // Uses value(s) from first entry point+  SpvReflectDescriptorSet           descriptor_sets[SPV_REFLECT_MAX_DESCRIPTOR_SETS]; // Uses value(s) from first entry point+  uint32_t                          input_variable_count;                             // Uses value(s) from first entry point+  SpvReflectInterfaceVariable**     input_variables;                                  // Uses value(s) from first entry point+  uint32_t                          output_variable_count;                            // Uses value(s) from first entry point+  SpvReflectInterfaceVariable**     output_variables;                                 // Uses value(s) from first entry point+  uint32_t                          interface_variable_count;                         // Uses value(s) from first entry point+  SpvReflectInterfaceVariable*      interface_variables;                              // Uses value(s) from first entry point+  uint32_t                          push_constant_block_count;                        // Uses value(s) from first entry point+  SpvReflectBlockVariable*          push_constant_blocks;                             // Uses value(s) from first entry point++  struct Internal {+    SpvReflectModuleFlags           module_flags;+    size_t                          spirv_size;+    uint32_t*                       spirv_code;+    uint32_t                        spirv_word_count;++    size_t                          type_description_count;+    SpvReflectTypeDescription*      type_descriptions;+  } * _internal;++} SpvReflectShaderModule;++#if defined(__cplusplus)+extern "C" {+#endif++/*! @fn spvReflectCreateShaderModule++ @param  size      Size in bytes of SPIR-V code.+ @param  p_code    Pointer to SPIR-V code.+ @param  p_module  Pointer to an instance of SpvReflectShaderModule.+ @return           SPV_REFLECT_RESULT_SUCCESS on success.++*/+SpvReflectResult spvReflectCreateShaderModule(+  size_t                   size,+  const void*              p_code,+  SpvReflectShaderModule*  p_module+);++/*! @fn spvReflectCreateShaderModule2++ @param  flags     Flags for module creations.+ @param  size      Size in bytes of SPIR-V code.+ @param  p_code    Pointer to SPIR-V code.+ @param  p_module  Pointer to an instance of SpvReflectShaderModule.+ @return           SPV_REFLECT_RESULT_SUCCESS on success.++*/+SpvReflectResult spvReflectCreateShaderModule2(+  SpvReflectModuleFlags    flags,+  size_t                   size,+  const void*              p_code,+  SpvReflectShaderModule*  p_module+);++SPV_REFLECT_DEPRECATED("renamed to spvReflectCreateShaderModule")+SpvReflectResult spvReflectGetShaderModule(+  size_t                   size,+  const void*              p_code,+  SpvReflectShaderModule*  p_module+);+++/*! @fn spvReflectDestroyShaderModule++ @param  p_module  Pointer to an instance of SpvReflectShaderModule.++*/+void spvReflectDestroyShaderModule(SpvReflectShaderModule* p_module);+++/*! @fn spvReflectGetCodeSize++ @param  p_module  Pointer to an instance of SpvReflectShaderModule.+ @return           Returns the size of the SPIR-V in bytes++*/+uint32_t spvReflectGetCodeSize(const SpvReflectShaderModule* p_module);+++/*! @fn spvReflectGetCode++ @param  p_module  Pointer to an instance of SpvReflectShaderModule.+ @return           Returns a const pointer to the compiled SPIR-V bytecode.++*/+const uint32_t* spvReflectGetCode(const SpvReflectShaderModule* p_module);++/*! @fn spvReflectGetEntryPoint++ @param  p_module     Pointer to an instance of SpvReflectShaderModule.+ @param  entry_point  Name of the requested entry point.+ @return              Returns a const pointer to the requested entry point,+                      or NULL if it's not found.+*/+const SpvReflectEntryPoint* spvReflectGetEntryPoint(+  const SpvReflectShaderModule* p_module,+  const char*                   entry_point+);++/*! @fn spvReflectEnumerateDescriptorBindings++ @param  p_module     Pointer to an instance of SpvReflectShaderModule.+ @param  p_count      If pp_bindings is NULL, the module's descriptor binding+                      count (across all descriptor sets) will be stored here.+                      If pp_bindings is not NULL, *p_count must contain the+                      module's descriptor binding count.+ @param  pp_bindings  If NULL, the module's total descriptor binding count+                      will be written to *p_count.+                      If non-NULL, pp_bindings must point to an array with+                      *p_count entries, where pointers to the module's+                      descriptor bindings will be written. The caller must not+                      free the binding pointers written to this array.+ @return              If successful, returns SPV_REFLECT_RESULT_SUCCESS.+                      Otherwise, the error code indicates the cause of the+                      failure.++*/+SpvReflectResult spvReflectEnumerateDescriptorBindings(+  const SpvReflectShaderModule*  p_module,+  uint32_t*                      p_count,+  SpvReflectDescriptorBinding**  pp_bindings+);++/*! @fn spvReflectEnumerateEntryPointDescriptorBindings+ @brief  Creates a listing of all descriptor bindings that are used in the+         static call tree of the given entry point.+ @param  p_module     Pointer to an instance of SpvReflectShaderModule.+ @param  entry_point  The name of the entry point to get the descriptor bindings for.+ @param  p_count      If pp_bindings is NULL, the entry point's descriptor binding+                      count (across all descriptor sets) will be stored here.+                      If pp_bindings is not NULL, *p_count must contain the+                      entry points's descriptor binding count.+ @param  pp_bindings  If NULL, the entry point's total descriptor binding count+                      will be written to *p_count.+                      If non-NULL, pp_bindings must point to an array with+                      *p_count entries, where pointers to the entry point's+                      descriptor bindings will be written. The caller must not+                      free the binding pointers written to this array.+ @return              If successful, returns SPV_REFLECT_RESULT_SUCCESS.+                      Otherwise, the error code indicates the cause of the+                      failure.++*/+SpvReflectResult spvReflectEnumerateEntryPointDescriptorBindings(+  const SpvReflectShaderModule* p_module,+  const char*                   entry_point,+  uint32_t*                     p_count,+  SpvReflectDescriptorBinding** pp_bindings+);++/*! @fn spvReflectEnumerateDescriptorSets++ @param  p_module  Pointer to an instance of SpvReflectShaderModule.+ @param  p_count   If pp_sets is NULL, the module's descriptor set+                   count will be stored here.+                   If pp_sets is not NULL, *p_count must contain the+                   module's descriptor set count.+ @param  pp_sets   If NULL, the module's total descriptor set count+                   will be written to *p_count.+                   If non-NULL, pp_sets must point to an array with+                   *p_count entries, where pointers to the module's+                   descriptor sets will be written. The caller must not+                   free the descriptor set pointers written to this array.+ @return           If successful, returns SPV_REFLECT_RESULT_SUCCESS.+                   Otherwise, the error code indicates the cause of the+                   failure.++*/+SpvReflectResult spvReflectEnumerateDescriptorSets(+  const SpvReflectShaderModule* p_module,+  uint32_t*                     p_count,+  SpvReflectDescriptorSet**     pp_sets+);++/*! @fn spvReflectEnumerateEntryPointDescriptorSets+ @brief  Creates a listing of all descriptor sets and their bindings that are+         used in the static call tree of a given entry point.+ @param  p_module    Pointer to an instance of SpvReflectShaderModule.+ @param  entry_point The name of the entry point to get the descriptor bindings for.+ @param  p_count     If pp_sets is NULL, the module's descriptor set+                     count will be stored here.+                     If pp_sets is not NULL, *p_count must contain the+                     module's descriptor set count.+ @param  pp_sets     If NULL, the module's total descriptor set count+                     will be written to *p_count.+                     If non-NULL, pp_sets must point to an array with+                     *p_count entries, where pointers to the module's+                     descriptor sets will be written. The caller must not+                     free the descriptor set pointers written to this array.+ @return             If successful, returns SPV_REFLECT_RESULT_SUCCESS.+                     Otherwise, the error code indicates the cause of the+                     failure.++*/+SpvReflectResult spvReflectEnumerateEntryPointDescriptorSets(+  const SpvReflectShaderModule* p_module,+  const char*                   entry_point,+  uint32_t*                     p_count,+  SpvReflectDescriptorSet**     pp_sets+);+++/*! @fn spvReflectEnumerateInterfaceVariables+ @brief  If the module contains multiple entry points, this will only get+         the interface variables for the first one.+ @param  p_module      Pointer to an instance of SpvReflectShaderModule.+ @param  p_count       If pp_variables is NULL, the module's interface variable+                       count will be stored here.+                       If pp_variables is not NULL, *p_count must contain+                       the module's interface variable count.+ @param  pp_variables  If NULL, the module's interface variable count will be+                       written to *p_count.+                       If non-NULL, pp_variables must point to an array with+                       *p_count entries, where pointers to the module's+                       interface variables will be written. The caller must not+                       free the interface variables written to this array.+ @return               If successful, returns SPV_REFLECT_RESULT_SUCCESS.+                       Otherwise, the error code indicates the cause of the+                       failure.++*/+SpvReflectResult spvReflectEnumerateInterfaceVariables(+  const SpvReflectShaderModule* p_module,+  uint32_t*                     p_count,+  SpvReflectInterfaceVariable** pp_variables+);++/*! @fn spvReflectEnumerateEntryPointInterfaceVariables+ @brief  Enumerate the interface variables for a given entry point.+ @param  entry_point The name of the entry point to get the interface variables for.+ @param  p_module      Pointer to an instance of SpvReflectShaderModule.+ @param  p_count       If pp_variables is NULL, the entry point's interface variable+                       count will be stored here.+                       If pp_variables is not NULL, *p_count must contain+                       the entry point's interface variable count.+ @param  pp_variables  If NULL, the entry point's interface variable count will be+                       written to *p_count.+                       If non-NULL, pp_variables must point to an array with+                       *p_count entries, where pointers to the entry point's+                       interface variables will be written. The caller must not+                       free the interface variables written to this array.+ @return               If successful, returns SPV_REFLECT_RESULT_SUCCESS.+                       Otherwise, the error code indicates the cause of the+                       failure.++*/+SpvReflectResult spvReflectEnumerateEntryPointInterfaceVariables(+  const SpvReflectShaderModule* p_module,+  const char*                   entry_point,+  uint32_t*                     p_count,+  SpvReflectInterfaceVariable** pp_variables+);+++/*! @fn spvReflectEnumerateInputVariables+ @brief  If the module contains multiple entry points, this will only get+         the input variables for the first one.+ @param  p_module      Pointer to an instance of SpvReflectShaderModule.+ @param  p_count       If pp_variables is NULL, the module's input variable+                       count will be stored here.+                       If pp_variables is not NULL, *p_count must contain+                       the module's input variable count.+ @param  pp_variables  If NULL, the module's input variable count will be+                       written to *p_count.+                       If non-NULL, pp_variables must point to an array with+                       *p_count entries, where pointers to the module's+                       input variables will be written. The caller must not+                       free the interface variables written to this array.+ @return               If successful, returns SPV_REFLECT_RESULT_SUCCESS.+                       Otherwise, the error code indicates the cause of the+                       failure.++*/+SpvReflectResult spvReflectEnumerateInputVariables(+  const SpvReflectShaderModule* p_module,+  uint32_t*                     p_count,+  SpvReflectInterfaceVariable** pp_variables+);++/*! @fn spvReflectEnumerateEntryPointInputVariables+ @brief  Enumerate the input variables for a given entry point.+ @param  entry_point The name of the entry point to get the input variables for.+ @param  p_module      Pointer to an instance of SpvReflectShaderModule.+ @param  p_count       If pp_variables is NULL, the entry point's input variable+                       count will be stored here.+                       If pp_variables is not NULL, *p_count must contain+                       the entry point's input variable count.+ @param  pp_variables  If NULL, the entry point's input variable count will be+                       written to *p_count.+                       If non-NULL, pp_variables must point to an array with+                       *p_count entries, where pointers to the entry point's+                       input variables will be written. The caller must not+                       free the interface variables written to this array.+ @return               If successful, returns SPV_REFLECT_RESULT_SUCCESS.+                       Otherwise, the error code indicates the cause of the+                       failure.++*/+SpvReflectResult spvReflectEnumerateEntryPointInputVariables(+  const SpvReflectShaderModule* p_module,+  const char*                   entry_point,+  uint32_t*                     p_count,+  SpvReflectInterfaceVariable** pp_variables+);+++/*! @fn spvReflectEnumerateOutputVariables+ @brief  Note: If the module contains multiple entry points, this will only get+         the output variables for the first one.+ @param  p_module      Pointer to an instance of SpvReflectShaderModule.+ @param  p_count       If pp_variables is NULL, the module's output variable+                       count will be stored here.+                       If pp_variables is not NULL, *p_count must contain+                       the module's output variable count.+ @param  pp_variables  If NULL, the module's output variable count will be+                       written to *p_count.+                       If non-NULL, pp_variables must point to an array with+                       *p_count entries, where pointers to the module's+                       output variables will be written. The caller must not+                       free the interface variables written to this array.+ @return               If successful, returns SPV_REFLECT_RESULT_SUCCESS.+                       Otherwise, the error code indicates the cause of the+                       failure.++*/+SpvReflectResult spvReflectEnumerateOutputVariables(+  const SpvReflectShaderModule* p_module,+  uint32_t*                     p_count,+  SpvReflectInterfaceVariable** pp_variables+);++/*! @fn spvReflectEnumerateEntryPointOutputVariables+ @brief  Enumerate the output variables for a given entry point.+ @param  p_module      Pointer to an instance of SpvReflectShaderModule.+ @param  entry_point   The name of the entry point to get the output variables for.+ @param  p_count       If pp_variables is NULL, the entry point's output variable+                       count will be stored here.+                       If pp_variables is not NULL, *p_count must contain+                       the entry point's output variable count.+ @param  pp_variables  If NULL, the entry point's output variable count will be+                       written to *p_count.+                       If non-NULL, pp_variables must point to an array with+                       *p_count entries, where pointers to the entry point's+                       output variables will be written. The caller must not+                       free the interface variables written to this array.+ @return               If successful, returns SPV_REFLECT_RESULT_SUCCESS.+                       Otherwise, the error code indicates the cause of the+                       failure.++*/+SpvReflectResult spvReflectEnumerateEntryPointOutputVariables(+  const SpvReflectShaderModule* p_module,+  const char*                   entry_point,+  uint32_t*                     p_count,+  SpvReflectInterfaceVariable** pp_variables+);+++/*! @fn spvReflectEnumeratePushConstantBlocks+ @brief  Note: If the module contains multiple entry points, this will only get+         the push constant blocks for the first one.+ @param  p_module   Pointer to an instance of SpvReflectShaderModule.+ @param  p_count    If pp_blocks is NULL, the module's push constant+                    block count will be stored here.+                    If pp_blocks is not NULL, *p_count must+                    contain the module's push constant block count.+ @param  pp_blocks  If NULL, the module's push constant block count+                    will be written to *p_count.+                    If non-NULL, pp_blocks must point to an+                    array with *p_count entries, where pointers to+                    the module's push constant blocks will be written.+                    The caller must not free the block variables written+                    to this array.+ @return            If successful, returns SPV_REFLECT_RESULT_SUCCESS.+                    Otherwise, the error code indicates the cause of the+                    failure.++*/+SpvReflectResult spvReflectEnumeratePushConstantBlocks(+  const SpvReflectShaderModule* p_module,+  uint32_t*                     p_count,+  SpvReflectBlockVariable**     pp_blocks+);+SPV_REFLECT_DEPRECATED("renamed to spvReflectEnumeratePushConstantBlocks")+SpvReflectResult spvReflectEnumeratePushConstants(+  const SpvReflectShaderModule* p_module,+  uint32_t*                     p_count,+  SpvReflectBlockVariable**     pp_blocks+);++/*! @fn spvReflectEnumerateEntryPointPushConstantBlocks+ @brief  Enumerate the push constant blocks used in the static call tree of a+         given entry point.+ @param  p_module   Pointer to an instance of SpvReflectShaderModule.+ @param  p_count    If pp_blocks is NULL, the entry point's push constant+                    block count will be stored here.+                    If pp_blocks is not NULL, *p_count must+                    contain the entry point's push constant block count.+ @param  pp_blocks  If NULL, the entry point's push constant block count+                    will be written to *p_count.+                    If non-NULL, pp_blocks must point to an+                    array with *p_count entries, where pointers to+                    the entry point's push constant blocks will be written.+                    The caller must not free the block variables written+                    to this array.+ @return            If successful, returns SPV_REFLECT_RESULT_SUCCESS.+                    Otherwise, the error code indicates the cause of the+                    failure.++*/+SpvReflectResult spvReflectEnumerateEntryPointPushConstantBlocks(+  const SpvReflectShaderModule* p_module,+  const char*                   entry_point,+  uint32_t*                     p_count,+  SpvReflectBlockVariable**     pp_blocks+);+++/*! @fn spvReflectGetDescriptorBinding++ @param  p_module        Pointer to an instance of SpvReflectShaderModule.+ @param  binding_number  The "binding" value of the requested descriptor+                         binding.+ @param  set_number      The "set" value of the requested descriptor binding.+ @param  p_result        If successful, SPV_REFLECT_RESULT_SUCCESS will be+                         written to *p_result. Otherwise, a error code+                         indicating the cause of the failure will be stored+                         here.+ @return                 If the module contains a descriptor binding that+                         matches the provided [binding_number, set_number]+                         values, a pointer to that binding is returned. The+                         caller must not free this pointer.+                         If no match can be found, or if an unrelated error+                         occurs, the return value will be NULL. Detailed+                         error results are written to *pResult.+@note                    If the module contains multiple desriptor bindings+                         with the same set and binding numbers, there are+                         no guarantees about which binding will be returned.++*/+const SpvReflectDescriptorBinding* spvReflectGetDescriptorBinding(+  const SpvReflectShaderModule* p_module,+  uint32_t                      binding_number,+  uint32_t                      set_number,+  SpvReflectResult*             p_result+);++/*! @fn spvReflectGetEntryPointDescriptorBinding+ @brief  Get the descriptor binding with the given binding number and set+         number that is used in the static call tree of a certain entry+         point.+ @param  p_module        Pointer to an instance of SpvReflectShaderModule.+ @param  entry_point     The entry point to get the binding from.+ @param  binding_number  The "binding" value of the requested descriptor+                         binding.+ @param  set_number      The "set" value of the requested descriptor binding.+ @param  p_result        If successful, SPV_REFLECT_RESULT_SUCCESS will be+                         written to *p_result. Otherwise, a error code+                         indicating the cause of the failure will be stored+                         here.+ @return                 If the entry point contains a descriptor binding that+                         matches the provided [binding_number, set_number]+                         values, a pointer to that binding is returned. The+                         caller must not free this pointer.+                         If no match can be found, or if an unrelated error+                         occurs, the return value will be NULL. Detailed+                         error results are written to *pResult.+@note                    If the entry point contains multiple desriptor bindings+                         with the same set and binding numbers, there are+                         no guarantees about which binding will be returned.++*/+const SpvReflectDescriptorBinding* spvReflectGetEntryPointDescriptorBinding(+  const SpvReflectShaderModule* p_module,+  const char*                   entry_point,+  uint32_t                      binding_number,+  uint32_t                      set_number,+  SpvReflectResult*             p_result+);+++/*! @fn spvReflectGetDescriptorSet++ @param  p_module    Pointer to an instance of SpvReflectShaderModule.+ @param  set_number  The "set" value of the requested descriptor set.+ @param  p_result    If successful, SPV_REFLECT_RESULT_SUCCESS will be+                     written to *p_result. Otherwise, a error code+                     indicating the cause of the failure will be stored+                     here.+ @return             If the module contains a descriptor set with the+                     provided set_number, a pointer to that set is+                     returned. The caller must not free this pointer.+                     If no match can be found, or if an unrelated error+                     occurs, the return value will be NULL. Detailed+                     error results are written to *pResult.++*/+const SpvReflectDescriptorSet* spvReflectGetDescriptorSet(+  const SpvReflectShaderModule* p_module,+  uint32_t                      set_number,+  SpvReflectResult*             p_result+);++/*! @fn spvReflectGetEntryPointDescriptorSet++ @param  p_module    Pointer to an instance of SpvReflectShaderModule.+ @param  entry_point The entry point to get the descriptor set from.+ @param  set_number  The "set" value of the requested descriptor set.+ @param  p_result    If successful, SPV_REFLECT_RESULT_SUCCESS will be+                     written to *p_result. Otherwise, a error code+                     indicating the cause of the failure will be stored+                     here.+ @return             If the entry point contains a descriptor set with the+                     provided set_number, a pointer to that set is+                     returned. The caller must not free this pointer.+                     If no match can be found, or if an unrelated error+                     occurs, the return value will be NULL. Detailed+                     error results are written to *pResult.++*/+const SpvReflectDescriptorSet* spvReflectGetEntryPointDescriptorSet(+  const SpvReflectShaderModule* p_module,+  const char*                   entry_point,+  uint32_t                      set_number,+  SpvReflectResult*             p_result+);+++/* @fn spvReflectGetInputVariableByLocation++ @param  p_module  Pointer to an instance of SpvReflectShaderModule.+ @param  location  The "location" value of the requested input variable.+                   A location of 0xFFFFFFFF will always return NULL+                   with *p_result == ELEMENT_NOT_FOUND.+ @param  p_result  If successful, SPV_REFLECT_RESULT_SUCCESS will be+                   written to *p_result. Otherwise, a error code+                   indicating the cause of the failure will be stored+                   here.+ @return           If the module contains an input interface variable+                   with the provided location value, a pointer to that+                   variable is returned. The caller must not free this+                   pointer.+                   If no match can be found, or if an unrelated error+                   occurs, the return value will be NULL. Detailed+                   error results are written to *pResult.+@note++*/+const SpvReflectInterfaceVariable* spvReflectGetInputVariableByLocation(+  const SpvReflectShaderModule* p_module,+  uint32_t                      location,+  SpvReflectResult*             p_result+);+SPV_REFLECT_DEPRECATED("renamed to spvReflectGetInputVariableByLocation")+const SpvReflectInterfaceVariable* spvReflectGetInputVariable(+  const SpvReflectShaderModule* p_module,+  uint32_t                      location,+  SpvReflectResult*             p_result+);++/* @fn spvReflectGetEntryPointInputVariableByLocation++ @param  p_module    Pointer to an instance of SpvReflectShaderModule.+ @param  entry_point The entry point to get the input variable from.+ @param  location    The "location" value of the requested input variable.+                     A location of 0xFFFFFFFF will always return NULL+                     with *p_result == ELEMENT_NOT_FOUND.+ @param  p_result    If successful, SPV_REFLECT_RESULT_SUCCESS will be+                     written to *p_result. Otherwise, a error code+                     indicating the cause of the failure will be stored+                     here.+ @return             If the entry point contains an input interface variable+                     with the provided location value, a pointer to that+                     variable is returned. The caller must not free this+                     pointer.+                     If no match can be found, or if an unrelated error+                     occurs, the return value will be NULL. Detailed+                     error results are written to *pResult.+@note++*/+const SpvReflectInterfaceVariable* spvReflectGetEntryPointInputVariableByLocation(+  const SpvReflectShaderModule* p_module,+  const char*                   entry_point,+  uint32_t                      location,+  SpvReflectResult*             p_result+);++/* @fn spvReflectGetInputVariableBySemantic++ @param  p_module  Pointer to an instance of SpvReflectShaderModule.+ @param  semantic  The "semantic" value of the requested input variable.+                   A semantic of NULL will return NULL.+                   A semantic of "" will always return NULL with+                   *p_result == ELEMENT_NOT_FOUND.+ @param  p_result  If successful, SPV_REFLECT_RESULT_SUCCESS will be+                   written to *p_result. Otherwise, a error code+                   indicating the cause of the failure will be stored+                   here.+ @return           If the module contains an input interface variable+                   with the provided semantic, a pointer to that+                   variable is returned. The caller must not free this+                   pointer.+                   If no match can be found, or if an unrelated error+                   occurs, the return value will be NULL. Detailed+                   error results are written to *pResult.+@note++*/+const SpvReflectInterfaceVariable* spvReflectGetInputVariableBySemantic(+  const SpvReflectShaderModule* p_module,+  const char*                   semantic,+  SpvReflectResult*             p_result+);++/* @fn spvReflectGetEntryPointInputVariableBySemantic++ @param  p_module  Pointer to an instance of SpvReflectShaderModule.+ @param  entry_point The entry point to get the input variable from.+ @param  semantic  The "semantic" value of the requested input variable.+                   A semantic of NULL will return NULL.+                   A semantic of "" will always return NULL with+                   *p_result == ELEMENT_NOT_FOUND.+ @param  p_result  If successful, SPV_REFLECT_RESULT_SUCCESS will be+                   written to *p_result. Otherwise, a error code+                   indicating the cause of the failure will be stored+                   here.+ @return           If the entry point contains an input interface variable+                   with the provided semantic, a pointer to that+                   variable is returned. The caller must not free this+                   pointer.+                   If no match can be found, or if an unrelated error+                   occurs, the return value will be NULL. Detailed+                   error results are written to *pResult.+@note++*/+const SpvReflectInterfaceVariable* spvReflectGetEntryPointInputVariableBySemantic(+  const SpvReflectShaderModule* p_module,+  const char*                   entry_point,+  const char*                   semantic,+  SpvReflectResult*             p_result+);++/* @fn spvReflectGetOutputVariableByLocation++ @param  p_module  Pointer to an instance of SpvReflectShaderModule.+ @param  location  The "location" value of the requested output variable.+                   A location of 0xFFFFFFFF will always return NULL+                   with *p_result == ELEMENT_NOT_FOUND.+ @param  p_result  If successful, SPV_REFLECT_RESULT_SUCCESS will be+                   written to *p_result. Otherwise, a error code+                   indicating the cause of the failure will be stored+                   here.+ @return           If the module contains an output interface variable+                   with the provided location value, a pointer to that+                   variable is returned. The caller must not free this+                   pointer.+                   If no match can be found, or if an unrelated error+                   occurs, the return value will be NULL. Detailed+                   error results are written to *pResult.+@note++*/+const SpvReflectInterfaceVariable* spvReflectGetOutputVariableByLocation(+  const SpvReflectShaderModule*  p_module,+  uint32_t                       location,+  SpvReflectResult*              p_result+);+SPV_REFLECT_DEPRECATED("renamed to spvReflectGetOutputVariableByLocation")+const SpvReflectInterfaceVariable* spvReflectGetOutputVariable(+  const SpvReflectShaderModule*  p_module,+  uint32_t                       location,+  SpvReflectResult*              p_result+);++/* @fn spvReflectGetEntryPointOutputVariableByLocation++ @param  p_module     Pointer to an instance of SpvReflectShaderModule.+ @param  entry_point  The entry point to get the output variable from.+ @param  location     The "location" value of the requested output variable.+                      A location of 0xFFFFFFFF will always return NULL+                      with *p_result == ELEMENT_NOT_FOUND.+ @param  p_result     If successful, SPV_REFLECT_RESULT_SUCCESS will be+                      written to *p_result. Otherwise, a error code+                      indicating the cause of the failure will be stored+                      here.+ @return              If the entry point contains an output interface variable+                      with the provided location value, a pointer to that+                      variable is returned. The caller must not free this+                      pointer.+                      If no match can be found, or if an unrelated error+                      occurs, the return value will be NULL. Detailed+                      error results are written to *pResult.+@note++*/+const SpvReflectInterfaceVariable* spvReflectGetEntryPointOutputVariableByLocation(+  const SpvReflectShaderModule*  p_module,+  const char*                    entry_point,+  uint32_t                       location,+  SpvReflectResult*              p_result+);++/* @fn spvReflectGetOutputVariableBySemantic++ @param  p_module  Pointer to an instance of SpvReflectShaderModule.+ @param  semantic  The "semantic" value of the requested output variable.+                   A semantic of NULL will return NULL.+                   A semantic of "" will always return NULL with+                   *p_result == ELEMENT_NOT_FOUND.+ @param  p_result  If successful, SPV_REFLECT_RESULT_SUCCESS will be+                   written to *p_result. Otherwise, a error code+                   indicating the cause of the failure will be stored+                   here.+ @return           If the module contains an output interface variable+                   with the provided semantic, a pointer to that+                   variable is returned. The caller must not free this+                   pointer.+                   If no match can be found, or if an unrelated error+                   occurs, the return value will be NULL. Detailed+                   error results are written to *pResult.+@note++*/+const SpvReflectInterfaceVariable* spvReflectGetOutputVariableBySemantic(+  const SpvReflectShaderModule*  p_module,+  const char*                    semantic,+  SpvReflectResult*              p_result+);++/* @fn spvReflectGetEntryPointOutputVariableBySemantic++ @param  p_module  Pointer to an instance of SpvReflectShaderModule.+ @param  entry_point  The entry point to get the output variable from.+ @param  semantic  The "semantic" value of the requested output variable.+                   A semantic of NULL will return NULL.+                   A semantic of "" will always return NULL with+                   *p_result == ELEMENT_NOT_FOUND.+ @param  p_result  If successful, SPV_REFLECT_RESULT_SUCCESS will be+                   written to *p_result. Otherwise, a error code+                   indicating the cause of the failure will be stored+                   here.+ @return           If the entry point contains an output interface variable+                   with the provided semantic, a pointer to that+                   variable is returned. The caller must not free this+                   pointer.+                   If no match can be found, or if an unrelated error+                   occurs, the return value will be NULL. Detailed+                   error results are written to *pResult.+@note++*/+const SpvReflectInterfaceVariable* spvReflectGetEntryPointOutputVariableBySemantic(+  const SpvReflectShaderModule*  p_module,+  const char*                    entry_point,+  const char*                    semantic,+  SpvReflectResult*              p_result+);++/*! @fn spvReflectGetPushConstantBlock++ @param  p_module  Pointer to an instance of SpvReflectShaderModule.+ @param  index     The index of the desired block within the module's+                   array of push constant blocks.+ @param  p_result  If successful, SPV_REFLECT_RESULT_SUCCESS will be+                   written to *p_result. Otherwise, a error code+                   indicating the cause of the failure will be stored+                   here.+ @return           If the provided index is within range, a pointer to+                   the corresponding push constant block is returned.+                   The caller must not free this pointer.+                   If no match can be found, or if an unrelated error+                   occurs, the return value will be NULL. Detailed+                   error results are written to *pResult.++*/+const SpvReflectBlockVariable* spvReflectGetPushConstantBlock(+  const SpvReflectShaderModule*  p_module,+  uint32_t                       index,+  SpvReflectResult*              p_result+);+SPV_REFLECT_DEPRECATED("renamed to spvReflectGetPushConstantBlock")+const SpvReflectBlockVariable* spvReflectGetPushConstant(+  const SpvReflectShaderModule*  p_module,+  uint32_t                       index,+  SpvReflectResult*              p_result+);++/*! @fn spvReflectGetEntryPointPushConstantBlock+ @brief  Get the push constant block corresponding to the given entry point.+         As by the Vulkan specification there can be no more than one push+         constant block used by a given entry point, so if there is one it will+         be returned, otherwise NULL will be returned.+ @param  p_module     Pointer to an instance of SpvReflectShaderModule.+ @param  entry_point  The entry point to get the push constant block from.+ @param  p_result     If successful, SPV_REFLECT_RESULT_SUCCESS will be+                      written to *p_result. Otherwise, a error code+                      indicating the cause of the failure will be stored+                      here.+ @return              If the provided index is within range, a pointer to+                      the corresponding push constant block is returned.+                      The caller must not free this pointer.+                      If no match can be found, or if an unrelated error+                      occurs, the return value will be NULL. Detailed+                      error results are written to *pResult.++*/+const SpvReflectBlockVariable* spvReflectGetEntryPointPushConstantBlock(+  const SpvReflectShaderModule*  p_module,+  const char*                    entry_point,+  SpvReflectResult*              p_result+);+++/*! @fn spvReflectChangeDescriptorBindingNumbers+ @brief  Assign new set and/or binding numbers to a descriptor binding.+         In addition to updating the reflection data, this function modifies+         the underlying SPIR-V bytecode. The updated code can be retrieved+         with spvReflectGetCode().  If the binding is used in multiple+         entry points within the module, it will be changed in all of them.+ @param  p_module            Pointer to an instance of SpvReflectShaderModule.+ @param  p_binding           Pointer to the descriptor binding to modify.+ @param  new_binding_number  The new binding number to assign to the+                             provided descriptor binding.+                             To leave the binding number unchanged, pass+                             SPV_REFLECT_BINDING_NUMBER_DONT_CHANGE.+ @param  new_set_number      The new set number to assign to the+                             provided descriptor binding. Successfully changing+                             a descriptor binding's set number invalidates all+                             existing SpvReflectDescriptorBinding and+                             SpvReflectDescriptorSet pointers from this module.+                             To leave the set number unchanged, pass+                             SPV_REFLECT_SET_NUMBER_DONT_CHANGE.+ @return                     If successful, returns SPV_REFLECT_RESULT_SUCCESS.+                             Otherwise, the error code indicates the cause of+                             the failure.+*/+SpvReflectResult spvReflectChangeDescriptorBindingNumbers(+  SpvReflectShaderModule*            p_module,+  const SpvReflectDescriptorBinding* p_binding,+  uint32_t                           new_binding_number,+  uint32_t                           new_set_number+);+SPV_REFLECT_DEPRECATED("Renamed to spvReflectChangeDescriptorBindingNumbers")+SpvReflectResult spvReflectChangeDescriptorBindingNumber(+  SpvReflectShaderModule*            p_module,+  const SpvReflectDescriptorBinding* p_descriptor_binding,+  uint32_t                           new_binding_number,+  uint32_t                           optional_new_set_number+);++/*! @fn spvReflectChangeDescriptorSetNumber+ @brief  Assign a new set number to an entire descriptor set (including+         all descriptor bindings in that set).+         In addition to updating the reflection data, this function modifies+         the underlying SPIR-V bytecode. The updated code can be retrieved+         with spvReflectGetCode().  If the descriptor set is used in+         multiple entry points within the module, it will be modified in all+         of them.+ @param  p_module        Pointer to an instance of SpvReflectShaderModule.+ @param  p_set           Pointer to the descriptor binding to modify.+ @param  new_set_number  The new set number to assign to the+                         provided descriptor set, and all its descriptor+                         bindings. Successfully changing a descriptor+                         binding's set number invalidates all existing+                         SpvReflectDescriptorBinding and+                         SpvReflectDescriptorSet pointers from this module.+                         To leave the set number unchanged, pass+                         SPV_REFLECT_SET_NUMBER_DONT_CHANGE.+ @return                 If successful, returns SPV_REFLECT_RESULT_SUCCESS.+                         Otherwise, the error code indicates the cause of+                         the failure.+*/+SpvReflectResult spvReflectChangeDescriptorSetNumber(+  SpvReflectShaderModule*        p_module,+  const SpvReflectDescriptorSet* p_set,+  uint32_t                       new_set_number+);++/*! @fn spvReflectChangeInputVariableLocation+ @brief  Assign a new location to an input interface variable.+         In addition to updating the reflection data, this function modifies+         the underlying SPIR-V bytecode. The updated code can be retrieved+         with spvReflectGetCode().+         It is the caller's responsibility to avoid assigning the same+         location to multiple input variables.  If the input variable is used+         by multiple entry points in the module, it will be changed in all of+         them.+ @param  p_module          Pointer to an instance of SpvReflectShaderModule.+ @param  p_input_variable  Pointer to the input variable to update.+ @param  new_location      The new location to assign to p_input_variable.+ @return                   If successful, returns SPV_REFLECT_RESULT_SUCCESS.+                           Otherwise, the error code indicates the cause of+                           the failure.++*/+SpvReflectResult spvReflectChangeInputVariableLocation(+  SpvReflectShaderModule*            p_module,+  const SpvReflectInterfaceVariable* p_input_variable,+  uint32_t                           new_location+);+++/*! @fn spvReflectChangeOutputVariableLocation+ @brief  Assign a new location to an output interface variable.+         In addition to updating the reflection data, this function modifies+         the underlying SPIR-V bytecode. The updated code can be retrieved+         with spvReflectGetCode().+         It is the caller's responsibility to avoid assigning the same+         location to multiple output variables.  If the output variable is used+         by multiple entry points in the module, it will be changed in all of+         them.+ @param  p_module          Pointer to an instance of SpvReflectShaderModule.+ @param  p_output_variable Pointer to the output variable to update.+ @param  new_location      The new location to assign to p_output_variable.+ @return                   If successful, returns SPV_REFLECT_RESULT_SUCCESS.+                           Otherwise, the error code indicates the cause of+                           the failure.++*/+SpvReflectResult spvReflectChangeOutputVariableLocation(+  SpvReflectShaderModule*             p_module,+  const SpvReflectInterfaceVariable*  p_output_variable,+  uint32_t                            new_location+);+++/*! @fn spvReflectSourceLanguage++ @param  source_lang  The source language code.+ @return Returns string of source language specified in \a source_lang.+         The caller must not free the memory associated with this string.+*/+const char* spvReflectSourceLanguage(SpvSourceLanguage source_lang);++/*! @fn spvReflectBlockVariableTypeName++ @param  p_var Pointer to block variable.+ @return Returns string of block variable's type description type name+         or NULL if p_var is NULL.+*/+const char* spvReflectBlockVariableTypeName(+  const SpvReflectBlockVariable* p_var+);++#if defined(__cplusplus)+};+#endif++#if defined(__cplusplus)+#include <cstdlib>+#include <string>+#include <vector>++namespace spv_reflect {++/*! \class ShaderModule++*/+class ShaderModule {+public:+  ShaderModule();+  ShaderModule(size_t size, const void* p_code, SpvReflectModuleFlags flags = SPV_REFLECT_MODULE_FLAG_NONE);+  ShaderModule(const std::vector<uint8_t>& code, SpvReflectModuleFlags flags = SPV_REFLECT_MODULE_FLAG_NONE);+  ShaderModule(const std::vector<uint32_t>& code, SpvReflectModuleFlags flags = SPV_REFLECT_MODULE_FLAG_NONE);+  ~ShaderModule();++  ShaderModule(ShaderModule&& other);+  ShaderModule& operator=(ShaderModule&& other);++  SpvReflectResult GetResult() const;++  const SpvReflectShaderModule& GetShaderModule() const;++  uint32_t        GetCodeSize() const;+  const uint32_t* GetCode() const;++  const char*           GetEntryPointName() const;++  const char*           GetSourceFile() const;++  uint32_t                      GetEntryPointCount() const;+  const char*                   GetEntryPointName(uint32_t index) const;+  SpvReflectShaderStageFlagBits GetEntryPointShaderStage(uint32_t index) const;++  SpvReflectShaderStageFlagBits GetShaderStage() const;+  SPV_REFLECT_DEPRECATED("Renamed to GetShaderStage")+  SpvReflectShaderStageFlagBits GetVulkanShaderStage() const {+    return GetShaderStage();+  }++  SpvReflectResult  EnumerateDescriptorBindings(uint32_t* p_count, SpvReflectDescriptorBinding** pp_bindings) const;+  SpvReflectResult  EnumerateEntryPointDescriptorBindings(const char* entry_point, uint32_t* p_count, SpvReflectDescriptorBinding** pp_bindings) const;+  SpvReflectResult  EnumerateDescriptorSets( uint32_t* p_count, SpvReflectDescriptorSet** pp_sets) const ;+  SpvReflectResult  EnumerateEntryPointDescriptorSets(const char* entry_point, uint32_t* p_count, SpvReflectDescriptorSet** pp_sets) const ;+  SpvReflectResult  EnumerateInterfaceVariables(uint32_t* p_count, SpvReflectInterfaceVariable** pp_variables) const;+  SpvReflectResult  EnumerateEntryPointInterfaceVariables(const char* entry_point, uint32_t* p_count, SpvReflectInterfaceVariable** pp_variables) const;+  SpvReflectResult  EnumerateInputVariables(uint32_t* p_count,SpvReflectInterfaceVariable** pp_variables) const;+  SpvReflectResult  EnumerateEntryPointInputVariables(const char* entry_point, uint32_t* p_count, SpvReflectInterfaceVariable** pp_variables) const;+  SpvReflectResult  EnumerateOutputVariables(uint32_t* p_count,SpvReflectInterfaceVariable** pp_variables) const;+  SpvReflectResult  EnumerateEntryPointOutputVariables(const char* entry_point, uint32_t* p_count, SpvReflectInterfaceVariable** pp_variables) const;+  SpvReflectResult  EnumeratePushConstantBlocks(uint32_t* p_count, SpvReflectBlockVariable** pp_blocks) const;+  SpvReflectResult  EnumerateEntryPointPushConstantBlocks(const char* entry_point, uint32_t* p_count, SpvReflectBlockVariable** pp_blocks) const;+  SPV_REFLECT_DEPRECATED("Renamed to EnumeratePushConstantBlocks")+  SpvReflectResult  EnumeratePushConstants(uint32_t* p_count, SpvReflectBlockVariable** pp_blocks) const {+    return EnumeratePushConstantBlocks(p_count, pp_blocks);+  }++  const SpvReflectDescriptorBinding*  GetDescriptorBinding(uint32_t binding_number, uint32_t set_number, SpvReflectResult* p_result = nullptr) const;+  const SpvReflectDescriptorBinding*  GetEntryPointDescriptorBinding(const char* entry_point, uint32_t binding_number, uint32_t set_number, SpvReflectResult* p_result = nullptr) const;+  const SpvReflectDescriptorSet*      GetDescriptorSet(uint32_t set_number, SpvReflectResult* p_result = nullptr) const;+  const SpvReflectDescriptorSet*      GetEntryPointDescriptorSet(const char* entry_point, uint32_t set_number, SpvReflectResult* p_result = nullptr) const;+  const SpvReflectInterfaceVariable*  GetInputVariableByLocation(uint32_t location,  SpvReflectResult* p_result = nullptr) const;+  SPV_REFLECT_DEPRECATED("Renamed to GetInputVariableByLocation")+  const SpvReflectInterfaceVariable*  GetInputVariable(uint32_t location,  SpvReflectResult* p_result = nullptr) const {+    return GetInputVariableByLocation(location, p_result);+  }+  const SpvReflectInterfaceVariable*  GetEntryPointInputVariableByLocation(const char* entry_point, uint32_t location,  SpvReflectResult* p_result = nullptr) const;+  const SpvReflectInterfaceVariable*  GetInputVariableBySemantic(const char* semantic,  SpvReflectResult* p_result = nullptr) const;+  const SpvReflectInterfaceVariable*  GetEntryPointInputVariableBySemantic(const char* entry_point, const char* semantic,  SpvReflectResult* p_result = nullptr) const;+  const SpvReflectInterfaceVariable*  GetOutputVariableByLocation(uint32_t location, SpvReflectResult*  p_result = nullptr) const;+  SPV_REFLECT_DEPRECATED("Renamed to GetOutputVariableByLocation")+  const SpvReflectInterfaceVariable*  GetOutputVariable(uint32_t location, SpvReflectResult*  p_result = nullptr) const {+    return GetOutputVariableByLocation(location, p_result);+  }+  const SpvReflectInterfaceVariable*  GetEntryPointOutputVariableByLocation(const char* entry_point, uint32_t location, SpvReflectResult*  p_result = nullptr) const;+  const SpvReflectInterfaceVariable*  GetOutputVariableBySemantic(const char* semantic, SpvReflectResult*  p_result = nullptr) const;+  const SpvReflectInterfaceVariable*  GetEntryPointOutputVariableBySemantic(const char* entry_point, const char* semantic, SpvReflectResult*  p_result = nullptr) const;+  const SpvReflectBlockVariable*      GetPushConstantBlock(uint32_t index, SpvReflectResult*  p_result = nullptr) const;+  SPV_REFLECT_DEPRECATED("Renamed to GetPushConstantBlock")+  const SpvReflectBlockVariable*      GetPushConstant(uint32_t index, SpvReflectResult*  p_result = nullptr) const {+    return GetPushConstantBlock(index, p_result);+  }+  const SpvReflectBlockVariable*      GetEntryPointPushConstantBlock(const char* entry_point, SpvReflectResult*  p_result = nullptr) const;++  SpvReflectResult ChangeDescriptorBindingNumbers(const SpvReflectDescriptorBinding* p_binding,+      uint32_t new_binding_number = SPV_REFLECT_BINDING_NUMBER_DONT_CHANGE,+      uint32_t optional_new_set_number = SPV_REFLECT_SET_NUMBER_DONT_CHANGE);+  SPV_REFLECT_DEPRECATED("Renamed to ChangeDescriptorBindingNumbers")+  SpvReflectResult ChangeDescriptorBindingNumber(const SpvReflectDescriptorBinding* p_binding, uint32_t new_binding_number = SPV_REFLECT_BINDING_NUMBER_DONT_CHANGE,+      uint32_t new_set_number = SPV_REFLECT_SET_NUMBER_DONT_CHANGE) {+    return ChangeDescriptorBindingNumbers(p_binding, new_binding_number, new_set_number);+  }+  SpvReflectResult ChangeDescriptorSetNumber(const SpvReflectDescriptorSet* p_set, uint32_t new_set_number = SPV_REFLECT_SET_NUMBER_DONT_CHANGE);+  SpvReflectResult ChangeInputVariableLocation(const SpvReflectInterfaceVariable* p_input_variable, uint32_t new_location);+  SpvReflectResult ChangeOutputVariableLocation(const SpvReflectInterfaceVariable* p_output_variable, uint32_t new_location);++private:+  // Make noncopyable+  ShaderModule(const ShaderModule&);+  ShaderModule& operator=(const ShaderModule&);++private:+  mutable SpvReflectResult  m_result = SPV_REFLECT_RESULT_NOT_READY;+  SpvReflectShaderModule    m_module = {};+};+++// =================================================================================================+// ShaderModule+// =================================================================================================++/*! @fn ShaderModule++*/+inline ShaderModule::ShaderModule() {}+++/*! @fn ShaderModule++  @param  size+  @param  p_code++*/+inline ShaderModule::ShaderModule(size_t size, const void* p_code, SpvReflectModuleFlags flags) {+  m_result = spvReflectCreateShaderModule2(+    flags,+    size,+    p_code,+    &m_module);+}++/*! @fn ShaderModule++  @param  code+  +*/+inline ShaderModule::ShaderModule(const std::vector<uint8_t>& code, SpvReflectModuleFlags flags) {+  m_result = spvReflectCreateShaderModule2(+    flags,+    code.size(),+    code.data(),+    &m_module);+}++/*! @fn ShaderModule++  @param  code+  +*/+inline ShaderModule::ShaderModule(const std::vector<uint32_t>& code, SpvReflectModuleFlags flags) {+  m_result = spvReflectCreateShaderModule2(+    flags,+    code.size() * sizeof(uint32_t),+    code.data(),+    &m_module);+}++/*! @fn  ~ShaderModule++*/+inline ShaderModule::~ShaderModule() {+  spvReflectDestroyShaderModule(&m_module);+}+++inline ShaderModule::ShaderModule(ShaderModule&& other)+{+    *this = std::move(other);+}++inline ShaderModule& ShaderModule::operator=(ShaderModule&& other)+{+    m_result = std::move(other.m_result);+    m_module = std::move(other.m_module);++    other.m_module = {};+    return *this;+}++/*! @fn GetResult++  @return++*/+inline SpvReflectResult ShaderModule::GetResult() const {+  return m_result;+}+++/*! @fn GetShaderModule++  @return++*/+inline const SpvReflectShaderModule& ShaderModule::GetShaderModule() const {+  return m_module;+}+++/*! @fn GetCodeSize++  @return++  */+inline uint32_t ShaderModule::GetCodeSize() const {+  return spvReflectGetCodeSize(&m_module);+}+++/*! @fn GetCode++  @return++*/+inline const uint32_t* ShaderModule::GetCode() const {+  return spvReflectGetCode(&m_module);+}+++/*! @fn GetEntryPoint++  @return Returns entry point++*/+inline const char* ShaderModule::GetEntryPointName() const {+  return this->GetEntryPointName(0);+}++/*! @fn GetEntryPoint++  @return Returns entry point++*/+inline const char* ShaderModule::GetSourceFile() const {+  return m_module.source_file;+}++/*! @fn GetEntryPointCount++  @param+  @return+*/+inline uint32_t ShaderModule::GetEntryPointCount() const {+  return m_module.entry_point_count;+}++/*! @fn GetEntryPointName++  @param index+  @return+*/+inline const char* ShaderModule::GetEntryPointName(uint32_t index) const {+  return m_module.entry_points[index].name;+}++/*! @fn GetEntryPointShaderStage++  @param index+  @return Returns the shader stage for the entry point at \b index+*/+inline SpvReflectShaderStageFlagBits ShaderModule::GetEntryPointShaderStage(uint32_t index) const {+  return m_module.entry_points[index].shader_stage;+}++/*! @fn GetShaderStage++  @return Returns shader stage for the first entry point++*/+inline SpvReflectShaderStageFlagBits ShaderModule::GetShaderStage() const {+  return m_module.shader_stage;+}++/*! @fn EnumerateDescriptorBindings++  @param  count+  @param  p_binding_numbers+  @param  pp_bindings+  @return++*/+inline SpvReflectResult ShaderModule::EnumerateDescriptorBindings(+  uint32_t*                     p_count,+  SpvReflectDescriptorBinding** pp_bindings+) const+{+  m_result = spvReflectEnumerateDescriptorBindings(+    &m_module,+    p_count,+    pp_bindings);+  return m_result;+}++/*! @fn EnumerateEntryPointDescriptorBindings++  @param  entry_point+  @param  count+  @param  pp_bindings+  @return++*/+inline SpvReflectResult ShaderModule::EnumerateEntryPointDescriptorBindings(+  const char*                   entry_point,+  uint32_t*                     p_count,+  SpvReflectDescriptorBinding** pp_bindings+) const+{+  m_result = spvReflectEnumerateEntryPointDescriptorBindings(+      &m_module,+      entry_point,+      p_count,+      pp_bindings);+  return m_result;+}+++/*! @fn EnumerateDescriptorSets++  @param  count+  @param  pp_sets+  @return++*/+inline SpvReflectResult ShaderModule::EnumerateDescriptorSets(+  uint32_t*                 p_count,+  SpvReflectDescriptorSet** pp_sets+) const+{+  m_result = spvReflectEnumerateDescriptorSets(+    &m_module,+    p_count,+    pp_sets);+  return m_result;+}++/*! @fn EnumerateEntryPointDescriptorSets++  @param  entry_point+  @param  count+  @param  pp_sets+  @return++*/+inline SpvReflectResult ShaderModule::EnumerateEntryPointDescriptorSets(+  const char*               entry_point,+  uint32_t*                 p_count,+  SpvReflectDescriptorSet** pp_sets+) const+{+  m_result = spvReflectEnumerateEntryPointDescriptorSets(+      &m_module,+      entry_point,+      p_count,+      pp_sets);+  return m_result;+}+++/*! @fn EnumerateInterfaceVariables++  @param  count+  @param  pp_variables+  @return++*/+inline SpvReflectResult ShaderModule::EnumerateInterfaceVariables(+  uint32_t*                     p_count,+  SpvReflectInterfaceVariable** pp_variables+) const+{+  m_result = spvReflectEnumerateInterfaceVariables(+    &m_module,+    p_count,+    pp_variables);+  return m_result;+}++/*! @fn EnumerateEntryPointInterfaceVariables++  @param  entry_point+  @param  count+  @param  pp_variables+  @return++*/+inline SpvReflectResult ShaderModule::EnumerateEntryPointInterfaceVariables(+  const char*                   entry_point,+  uint32_t*                     p_count,+  SpvReflectInterfaceVariable** pp_variables+) const+{+  m_result = spvReflectEnumerateEntryPointInterfaceVariables(+      &m_module,+      entry_point,+      p_count,+      pp_variables);+  return m_result;+}+++/*! @fn EnumerateInputVariables++  @param  count+  @param  pp_variables+  @return++*/+inline SpvReflectResult ShaderModule::EnumerateInputVariables(+  uint32_t*                     p_count,+  SpvReflectInterfaceVariable** pp_variables+) const+{+  m_result = spvReflectEnumerateInputVariables(+    &m_module,+    p_count,+    pp_variables);+  return m_result;+}++/*! @fn EnumerateEntryPointInputVariables++  @param  entry_point+  @param  count+  @param  pp_variables+  @return++*/+inline SpvReflectResult ShaderModule::EnumerateEntryPointInputVariables(+  const char*                   entry_point,+  uint32_t*                     p_count,+  SpvReflectInterfaceVariable** pp_variables+) const+{+  m_result = spvReflectEnumerateEntryPointInputVariables(+      &m_module,+      entry_point,+      p_count,+      pp_variables);+  return m_result;+}+++/*! @fn EnumerateOutputVariables++  @param  count+  @param  pp_variables+  @return++*/+inline SpvReflectResult ShaderModule::EnumerateOutputVariables(+  uint32_t*                     p_count,+  SpvReflectInterfaceVariable** pp_variables+) const+{+  m_result = spvReflectEnumerateOutputVariables(+    &m_module,+    p_count,+    pp_variables);+  return m_result;+}++/*! @fn EnumerateEntryPointOutputVariables++  @param  entry_point+  @param  count+  @param  pp_variables+  @return++*/+inline SpvReflectResult ShaderModule::EnumerateEntryPointOutputVariables(+  const char*                   entry_point,+  uint32_t*                     p_count,+  SpvReflectInterfaceVariable** pp_variables+) const+{+  m_result = spvReflectEnumerateEntryPointOutputVariables(+      &m_module,+      entry_point,+      p_count,+      pp_variables);+  return m_result;+}+++/*! @fn EnumeratePushConstantBlocks++  @param  count+  @param  pp_blocks+  @return++*/+inline SpvReflectResult ShaderModule::EnumeratePushConstantBlocks(+  uint32_t*                 p_count,+  SpvReflectBlockVariable** pp_blocks+) const+{+  m_result = spvReflectEnumeratePushConstantBlocks(+    &m_module,+    p_count,+    pp_blocks);+  return m_result;+}++/*! @fn EnumerateEntryPointPushConstantBlocks++  @param  entry_point+  @param  count+  @param  pp_blocks+  @return++*/+inline SpvReflectResult ShaderModule::EnumerateEntryPointPushConstantBlocks(+  const char*               entry_point,+  uint32_t*                 p_count,+  SpvReflectBlockVariable** pp_blocks+) const+{+  m_result = spvReflectEnumerateEntryPointPushConstantBlocks(+      &m_module,+      entry_point,+      p_count,+      pp_blocks);+  return m_result;+}+++/*! @fn GetDescriptorBinding++  @param  binding_number+  @param  set_number+  @param  p_result+  @return++*/+inline const SpvReflectDescriptorBinding* ShaderModule::GetDescriptorBinding(+  uint32_t          binding_number,+  uint32_t          set_number,+  SpvReflectResult* p_result+) const+{+  return spvReflectGetDescriptorBinding(+    &m_module,+    binding_number,+    set_number,+    p_result);+}++/*! @fn GetEntryPointDescriptorBinding++  @param  entry_point+  @param  binding_number+  @param  set_number+  @param  p_result+  @return++*/+inline const SpvReflectDescriptorBinding* ShaderModule::GetEntryPointDescriptorBinding(+  const char*       entry_point,+  uint32_t          binding_number,+  uint32_t          set_number,+  SpvReflectResult* p_result+) const+{+  return spvReflectGetEntryPointDescriptorBinding(+    &m_module,+    entry_point,+    binding_number,+    set_number,+    p_result);+}+++/*! @fn GetDescriptorSet++  @param  set_number+  @param  p_result+  @return++*/+inline const SpvReflectDescriptorSet* ShaderModule::GetDescriptorSet(+  uint32_t          set_number,+  SpvReflectResult* p_result+) const+{+  return spvReflectGetDescriptorSet(+    &m_module,+    set_number,+    p_result);+}++/*! @fn GetEntryPointDescriptorSet++  @param  entry_point+  @param  set_number+  @param  p_result+  @return++*/+inline const SpvReflectDescriptorSet* ShaderModule::GetEntryPointDescriptorSet(+  const char*       entry_point,+  uint32_t          set_number,+  SpvReflectResult* p_result+) const+{+  return spvReflectGetEntryPointDescriptorSet(+    &m_module,+    entry_point,+    set_number,+    p_result);+}+++/*! @fn GetInputVariable++  @param  location+  @param  p_result+  @return++*/+inline const SpvReflectInterfaceVariable* ShaderModule::GetInputVariableByLocation(+  uint32_t          location,+  SpvReflectResult* p_result+) const+{+  return spvReflectGetInputVariableByLocation(+    &m_module,+    location,+    p_result);+}+inline const SpvReflectInterfaceVariable* ShaderModule::GetInputVariableBySemantic(+  const char*       semantic,+  SpvReflectResult* p_result+) const+{+  return spvReflectGetInputVariableBySemantic(+    &m_module,+    semantic,+    p_result);+}++/*! @fn GetEntryPointInputVariable++  @param  entry_point+  @param  location+  @param  p_result+  @return++*/+inline const SpvReflectInterfaceVariable* ShaderModule::GetEntryPointInputVariableByLocation(+  const char*       entry_point,+  uint32_t          location,+  SpvReflectResult* p_result+) const+{+  return spvReflectGetEntryPointInputVariableByLocation(+    &m_module,+    entry_point,+    location,+    p_result);+}+inline const SpvReflectInterfaceVariable* ShaderModule::GetEntryPointInputVariableBySemantic(+  const char*       entry_point,+  const char*       semantic,+  SpvReflectResult* p_result+) const+{+  return spvReflectGetEntryPointInputVariableBySemantic(+    &m_module,+    entry_point,+    semantic,+    p_result);+}+++/*! @fn GetOutputVariable++  @param  location+  @param  p_result+  @return++*/+inline const SpvReflectInterfaceVariable* ShaderModule::GetOutputVariableByLocation(+  uint32_t           location,+  SpvReflectResult*  p_result+) const+{+  return spvReflectGetOutputVariableByLocation(+    &m_module,+    location,+    p_result);+}+inline const SpvReflectInterfaceVariable* ShaderModule::GetOutputVariableBySemantic(+  const char*       semantic,+  SpvReflectResult* p_result+) const+{+  return spvReflectGetOutputVariableBySemantic(&m_module,+    semantic,+    p_result);+}++/*! @fn GetEntryPointOutputVariable++  @param  entry_point+  @param  location+  @param  p_result+  @return++*/+inline const SpvReflectInterfaceVariable* ShaderModule::GetEntryPointOutputVariableByLocation(+  const char*        entry_point,+  uint32_t           location,+  SpvReflectResult*  p_result+) const+{+  return spvReflectGetEntryPointOutputVariableByLocation(+    &m_module,+    entry_point,+    location,+    p_result);+}+inline const SpvReflectInterfaceVariable* ShaderModule::GetEntryPointOutputVariableBySemantic(+  const char*       entry_point,+  const char*       semantic,+  SpvReflectResult* p_result+) const+{+  return spvReflectGetEntryPointOutputVariableBySemantic(+    &m_module,+    entry_point,+    semantic,+    p_result);+}+++/*! @fn GetPushConstant++  @param  index+  @param  p_result+  @return++*/+inline const SpvReflectBlockVariable* ShaderModule::GetPushConstantBlock(+  uint32_t           index,+  SpvReflectResult*  p_result+) const+{+  return spvReflectGetPushConstantBlock(+    &m_module,+    index,+    p_result);+}++/*! @fn GetEntryPointPushConstant++  @param  entry_point+  @param  index+  @param  p_result+  @return++*/+inline const SpvReflectBlockVariable* ShaderModule::GetEntryPointPushConstantBlock(+  const char*        entry_point,+  SpvReflectResult*  p_result+) const+{+  return spvReflectGetEntryPointPushConstantBlock(+    &m_module,+    entry_point,+    p_result);+}+++/*! @fn ChangeDescriptorBindingNumbers++  @param  p_binding+  @param  new_binding_number+  @param  new_set_number+  @return++*/+inline SpvReflectResult ShaderModule::ChangeDescriptorBindingNumbers(+  const SpvReflectDescriptorBinding* p_binding,+  uint32_t                           new_binding_number,+  uint32_t                           new_set_number+)+{+  return spvReflectChangeDescriptorBindingNumbers(+    &m_module,+    p_binding,+    new_binding_number,+    new_set_number);+}+++/*! @fn ChangeDescriptorSetNumber++  @param  p_set+  @param  new_set_number+  @return++*/+inline SpvReflectResult ShaderModule::ChangeDescriptorSetNumber(+  const SpvReflectDescriptorSet* p_set,+  uint32_t                       new_set_number+)+{+  return spvReflectChangeDescriptorSetNumber(+    &m_module,+    p_set,+    new_set_number);+}+++/*! @fn ChangeInputVariableLocation++  @param  p_input_variable+  @param  new_location+  @return++*/+inline SpvReflectResult ShaderModule::ChangeInputVariableLocation(+  const SpvReflectInterfaceVariable* p_input_variable,+  uint32_t                           new_location)+{+  return spvReflectChangeInputVariableLocation(+    &m_module,+    p_input_variable,+    new_location);+}+++/*! @fn ChangeOutputVariableLocation++  @param  p_input_variable+  @param  new_location+  @return++*/+inline SpvReflectResult ShaderModule::ChangeOutputVariableLocation(+  const SpvReflectInterfaceVariable* p_output_variable,+  uint32_t                           new_location)+{+  return spvReflectChangeOutputVariableLocation(+    &m_module,+    p_output_variable,+    new_location);+}++} // namespace spv_reflect+#endif // defined(__cplusplus)+#endif // SPIRV_REFLECT_H
+ lib/Data/SpirV/Reflect/FFI.hs view
@@ -0,0 +1,34 @@+module Data.SpirV.Reflect.FFI+  ( Module+  , load+  , loadBytes+  ) where++import Control.Exception (finally)+import Control.Monad.IO.Class (MonadIO(..))+import Data.ByteString (ByteString)+import Data.ByteString qualified as ByteString+import Data.ByteString.Unsafe (unsafeUseAsCStringLen)+import Data.SpirV.Reflect.FFI.Internal qualified as C+import Foreign (allocaBytes, castPtr)++import Data.SpirV.Reflect.Module (Module)++load :: MonadIO io => FilePath -> io Module+load path = liftIO $+  ByteString.readFile path >>= loadBytes++loadBytes :: MonadIO io => ByteString -> io Module+loadBytes bytes = liftIO do+  unsafeUseAsCStringLen bytes \(code, size) -> do+    allocaBytes C.shaderModuleSize \smPtr -> do+      res <- C.createShaderModule2+        C.SpvReflectModuleFlagNoCopy+        (fromIntegral size)+        (castPtr code)+        smPtr+      case res of+        C.SpvReflectResultSuccess ->+          C.inflateModule smPtr `finally` C.destroyShaderModule smPtr+        err ->+          error $ "spvReflectCreateShaderModule2:" <> show err
+ lib/Data/SpirV/Reflect/FFI/Internal.chs view
@@ -0,0 +1,494 @@+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Data.SpirV.Reflect.FFI.Internal where++import Data.Coerce (Coercible, coerce)+import Data.Text (Text)+import Data.Text qualified as Text+import Data.Vector (Vector)+import Data.Vector qualified as Vector+import Data.Word (Word32)+import Foreign.C.String (CString)+import Foreign.C.Types (CULong)+import Foreign.Marshal.Utils (maybePeek)+import Foreign.Ptr (Ptr, castPtr, plusPtr, nullPtr)+import Foreign.Storable (peek)+import GHC.Ptr qualified as GHC++import Data.SpirV.Reflect.BlockVariable (BlockVariable)+import Data.SpirV.Reflect.BlockVariable qualified as BlockVariable+import Data.SpirV.Reflect.DescriptorBinding (DescriptorBinding)+import Data.SpirV.Reflect.DescriptorBinding qualified as DescriptorBinding+import Data.SpirV.Reflect.DescriptorSet (DescriptorSet)+import Data.SpirV.Reflect.DescriptorSet qualified as DescriptorSet+import Data.SpirV.Reflect.Enums qualified as Enums+import Data.SpirV.Reflect.InterfaceVariable (InterfaceVariable)+import Data.SpirV.Reflect.InterfaceVariable qualified as InterfaceVariable+import Data.SpirV.Reflect.Module (Module)+import Data.SpirV.Reflect.Module qualified as Module+import Data.SpirV.Reflect.Traits qualified as Traits+import Data.SpirV.Reflect.TypeDescription (TypeDescription)+import Data.SpirV.Reflect.TypeDescription qualified as TypeDescription++#include "spirv_reflect.h"++-- * Loader interface++{#pointer *SpvReflectShaderModule as ShaderModulePtr #}++{#enum+  SpvReflectResult as Result+  {underscoreToCase}+  deriving (Eq, Ord, Show)+#}++{#fun unsafe+  spvReflectCreateShaderModule as createShaderModule+  { id `CULong'+  , `Ptr ()'+  , `ShaderModulePtr'+  } -> `Result'+#}++{#enum+  SpvReflectModuleFlagBits as ModuleFlags+  {underscoreToCase}+  deriving (Eq, Ord, Show)+#}++{#fun unsafe+  spvReflectCreateShaderModule2 as createShaderModule2+  { `ModuleFlags'+  , id `CULong'+  , `Ptr ()'+  , `ShaderModulePtr'+  } -> `Result'+#}++{#fun unsafe+  spvReflectDestroyShaderModule as destroyShaderModule+  { `ShaderModulePtr'+  } -> `()'+#}++-- TODO: inflateEntryPoints :: ShaderModulePtr -> IO [EntryPoint]++-- * Module++shaderModuleSize :: Int+shaderModuleSize = {#sizeof SpvReflectShaderModule #}++inflateModule :: ShaderModulePtr -> IO Module+inflateModule smp = do+  let sm = castPtr smp++  generator <- inflateEnum $+    {#get SpvReflectShaderModule->generator #} sm++  entry_point_name <- inflateText $+    {#get SpvReflectShaderModule->entry_point_name #} sm++  entry_point_id <- inflateIntegral $+    {#get SpvReflectShaderModule->entry_point_id #} sm++  -- TODO: enums+  source_language <- inflateIntegral $+    {#get SpvReflectShaderModule->source_language #} sm++  source_language_version <- inflateIntegral $+    {#get SpvReflectShaderModule->source_language_version #} sm++  -- XXX: Uses value(s) from first entry point++  -- TODO: flags+  spirv_execution_model <- inflateIntegral $+    {#get SpvReflectShaderModule->spirv_execution_model #} sm++  -- TODO: flags+  shader_stage <- inflateIntegral $+    {#get SpvReflectShaderModule->shader_stage #} sm++  descriptor_bindings <-+    inflateVector+      ({#get SpvReflectShaderModule->descriptor_binding_count #} sm)+      ({#get SpvReflectShaderModule->descriptor_bindings #} sm)+      {#sizeof SpvReflectDescriptorBinding #}+      inflateDescriptorBinding++  descriptor_sets <-+    inflateVector+      ({#get SpvReflectShaderModule->descriptor_set_count #} sm)+      ({#get SpvReflectShaderModule->descriptor_sets #} sm)+      {#sizeof SpvReflectDescriptorSet #}+      inflateDescriptorSet++  inputPtr <- {#get SpvReflectShaderModule->input_variables #} sm+  input_variables <-+    if inputPtr == nullPtr then+      pure mempty+    else+      inflateVector+        ({#get SpvReflectShaderModule->input_variable_count #} sm)+        (peek inputPtr)+        {#sizeof SpvReflectInterfaceVariable #}+        inflateInterfaceVariable++  outputPtr <- {#get SpvReflectShaderModule->output_variables #} sm+  output_variables <-+    if outputPtr == nullPtr then+      pure mempty+    else+      inflateVector+        ({#get SpvReflectShaderModule->output_variable_count #} sm)+        (peek outputPtr)+        {#sizeof SpvReflectInterfaceVariable #}+        inflateInterfaceVariable++  push_constants <-+    inflateVector+      ({#get SpvReflectShaderModule->push_constant_block_count #} sm)+      ({#get SpvReflectShaderModule->push_constant_blocks #} sm)+      {#sizeof SpvReflectBlockVariable #}+      inflateBlockVariable++  pure Module.Module{..}++inflateVector :: Integral i => IO i -> IO (Ptr p) -> Int -> (Ptr p -> IO a) -> IO (Vector a)+inflateVector getCount getItems itemSize inflate = do+  count <- getCount+  itemsPtr <- getItems+  Vector.generateM (fromIntegral count) \pos -> do+    inflate $ itemsPtr `plusPtr` (itemSize * pos)++{#pointer *SpvReflectDescriptorBinding as DescriptorBindingPtr #}++inflateDescriptorBinding :: DescriptorBindingPtr -> IO DescriptorBinding+inflateDescriptorBinding db = do+  spirv_id <- fmap Just . inflateIntegral $+    {#get SpvReflectDescriptorBinding->spirv_id #} db++  name <- inflateText $+    {#get SpvReflectDescriptorBinding->name #} db++  binding <- inflateIntegral $+    {#get SpvReflectDescriptorBinding->binding #} db++  input_attachment_index <- inflateIntegral $+    {#get SpvReflectDescriptorBinding->input_attachment_index #} db++  set <- inflateIntegral $+    {#get SpvReflectDescriptorBinding->set #} db++  descriptor_type <- inflateEnum $+    {#get SpvReflectDescriptorBinding->descriptor_type #} db++  resource_type <- inflateFlags32 $+    {#get SpvReflectDescriptorBinding->resource_type #} db++  image <-+    inflateImageTraits+      db+      {#offsetof SpvReflectDescriptorBinding->image #}++  block <-+    {#get SpvReflectDescriptorBinding->block #} db >>=+      maybePeek inflateBlockVariable++  array <-+    inflateArrayTraits+      db+      {#offsetof SpvReflectDescriptorBinding->array #}++  count <- fmap Just . inflateIntegral $+    {#get SpvReflectDescriptorBinding->count #} db++  accessed <- inflateIntegral $+    {#get SpvReflectDescriptorBinding->accessed #} db++  uav_counter_id <- inflateIntegral $+    {#get SpvReflectDescriptorBinding->uav_counter_id #} db++  uav_counter_binding <-+    {#get SpvReflectDescriptorBinding->uav_counter_binding #} db >>=+      maybePeek inflateDescriptorBinding++  type_description <-+    {#get SpvReflectDescriptorBinding->type_description #} db >>=+      maybePeek inflateTypeDescription++  let word_offset = DescriptorBinding.WordOffset{..}++  decoration_flags <- inflateFlags32 $+    {#get SpvReflectDescriptorBinding->decoration_flags #} db++  pure DescriptorBinding.DescriptorBinding{..}++{#pointer *SpvReflectBlockVariable as BlockVariablePtr #}++inflateBlockVariable :: BlockVariablePtr -> IO BlockVariable+inflateBlockVariable bv = do+  spirv_id <- fmap Just . inflateIntegral $+    {#get SpvReflectBlockVariable->spirv_id #} bv++  name <- fmap Just . inflateText $+    {#get SpvReflectBlockVariable->name #} bv++  offset <- inflateIntegral $+    {#get SpvReflectBlockVariable->offset #} bv++  absolute_offset <- inflateIntegral $+    {#get SpvReflectBlockVariable->absolute_offset #} bv++  size <- inflateIntegral $+    {#get SpvReflectBlockVariable->size #} bv++  padded_size <- inflateIntegral $+    {#get SpvReflectBlockVariable->padded_size #} bv++  decorations <- inflateFlags32 $+    {#get SpvReflectBlockVariable->decoration_flags #} bv++  numeric <-+    inflateNumericTraits+      bv+      {#offsetof SpvReflectBlockVariable->numeric #}++  array <-+    inflateArrayTraits+      bv+      {#offsetof SpvReflectBlockVariable->array #}++  members <-+    inflateVector+      ({#get SpvReflectBlockVariable->member_count #} bv)+      ({#get SpvReflectBlockVariable->members #} bv)+      {#sizeof SpvReflectBlockVariable #}+      inflateBlockVariable++  type_description <-+    {#get SpvReflectBlockVariable->members #} bv >>=+      maybePeek inflateTypeDescription++  pure BlockVariable.BlockVariable{..}++{#pointer *SpvReflectTypeDescription as TypeDescriptionPtr #}++inflateTypeDescription :: TypeDescriptionPtr -> IO TypeDescription+inflateTypeDescription td = do+  id_ <- fmap Just . inflateIntegral $+    {#get SpvReflectTypeDescription->id #} td++  op <- fmap Just . inflateEnum $+    {#get SpvReflectTypeDescription->op #} td++  type_name <- fmap Just . inflateText $+    {#get SpvReflectTypeDescription->type_name #} td++  struct_member_name <- fmap Just . inflateText $+    {#get SpvReflectTypeDescription->struct_member_name #} td++  storage_class <- inflateEnum $+    {#get SpvReflectTypeDescription->storage_class #} td++  type_flags <- inflateFlags32 $+    {#get SpvReflectTypeDescription->type_flags #} td++  numeric <-+    inflateNumericTraits+      td+      {#offsetof SpvReflectTypeDescription->traits.numeric #}++  image <-+    inflateImageTraits+      td+      {#offsetof SpvReflectTypeDescription->traits.image #}++  array <-+    inflateArrayTraits+      td+      {#offsetof SpvReflectTypeDescription->traits.array #}++  let traits = Just TypeDescription.Traits{..}++  members <-+    inflateVector+      ({#get SpvReflectTypeDescription->member_count #} td)+      ({#get SpvReflectTypeDescription->members #} td)+      {#sizeof SpvReflectTypeDescription #}+      inflateTypeDescription++  pure TypeDescription.TypeDescription{id=id_, ..}++{#pointer *SpvReflectDescriptorSet as DescriptorSetPtr #}++inflateDescriptorSet :: DescriptorSetPtr -> IO DescriptorSet+inflateDescriptorSet ds = do+  set <- inflateIntegral $+    {#get SpvReflectDescriptorSet->set #} ds++  bindingsPtr <- {#get SpvReflectDescriptorSet->bindings #} ds+  bindings <-+    inflateVector+      ({#get SpvReflectDescriptorSet->binding_count #} ds)+      (peek bindingsPtr)+      {#sizeof SpvReflectDescriptorBinding #}+      inflateDescriptorBinding++  pure DescriptorSet.DescriptorSet{..}++{#pointer *SpvReflectInterfaceVariable as InterfaceVariablePtr #}++inflateInterfaceVariable :: InterfaceVariablePtr -> IO InterfaceVariable+inflateInterfaceVariable iv = do+  spirv_id <- fmap Just . inflateIntegral $+    {#get SpvReflectInterfaceVariable->spirv_id #} iv++  name <- fmap Just . inflateText $+    {#get SpvReflectInterfaceVariable->name #} iv++  location <- inflateIntegral $+    {#get SpvReflectInterfaceVariable->location #} iv++  storage_class <- inflateEnum $+    {#get SpvReflectInterfaceVariable->storage_class #} iv++  semantic <- fmap Just . inflateText $+    {#get SpvReflectInterfaceVariable->semantic #} iv++  decoration_flags <- inflateFlags32 $+    {#get SpvReflectInterfaceVariable->decoration_flags #} iv++  built_in <- inflateEnum $+    {#get SpvReflectInterfaceVariable->built_in #} iv++  numeric <-+    inflateNumericTraits+      iv+      {#offsetof SpvReflectInterfaceVariable->numeric #}++  array <-+    inflateArrayTraits+      iv+      {#offsetof SpvReflectInterfaceVariable->array #}++  members <-+    inflateVector+      ({#get SpvReflectInterfaceVariable->member_count #} iv)+      ({#get SpvReflectInterfaceVariable->members #} iv)+      {#sizeof SpvReflectInterfaceVariable #}+      inflateInterfaceVariable++  format <- inflateEnum $+    {#get SpvReflectInterfaceVariable->format #} iv++  type_description <-+    {#get SpvReflectInterfaceVariable->type_description #} iv >>=+      maybePeek inflateTypeDescription++  wo_location <- inflateIntegral $+    {#get SpvReflectInterfaceVariable->word_offset.location #} iv+  let word_offset = InterfaceVariable.WordOffset{location=wo_location}++  pure InterfaceVariable.InterfaceVariable{..}++-- * Traits++{#pointer *SpvReflectImageTraits as ImageTraitsPtr #}++inflateImageTraits :: Ptr struct -> Int -> IO Traits.Image+inflateImageTraits src offset = do+  let it = castPtr src `plusPtr` offset++  dim <- inflateEnum $+    {#get SpvReflectImageTraits->dim #} it++  depth <- inflateIntegral $+    {#get SpvReflectImageTraits->depth #} it++  arrayed <- inflateIntegral $+    {#get SpvReflectImageTraits->arrayed #} it++  ms <- inflateIntegral $+    {#get SpvReflectImageTraits->ms #} it++  sampled <- inflateIntegral $+    {#get SpvReflectImageTraits->sampled #} it++  image_format <- inflateEnum $+    {#get SpvReflectImageTraits->image_format #} it++  pure Traits.Image{..}++{#pointer *SpvReflectNumericTraits as NumericTraitsPtr #}++inflateNumericTraits :: Ptr struct -> Int -> IO Traits.Numeric+inflateNumericTraits src offset = do+  let nt = castPtr src `plusPtr` offset++  width <- inflateIntegral $+    {#get SpvReflectNumericTraits.scalar.width #} nt+  signedness <- inflateIntegral $+    {#get SpvReflectNumericTraits.scalar.signedness #} nt+  let scalar = Traits.Scalar{..}++  component_count <- inflateIntegral $+    {#get SpvReflectNumericTraits->vector.component_count #} nt+  let vector = Traits.Vector{..}++  column_count <- inflateIntegral $+    {#get SpvReflectNumericTraits->matrix.column_count #} nt+  row_count <- inflateIntegral $+    {#get SpvReflectNumericTraits->matrix.row_count #} nt+  stride <- inflateIntegral $+    {#get SpvReflectNumericTraits->matrix.stride #} nt+  let matrix = Traits.Matrix{..}++  pure Traits.Numeric{..}++{#pointer *SpvReflectArrayTraits as ArrayTraitsPtr #}++inflateArrayTraits :: Ptr struct -> Int -> IO Traits.Array+inflateArrayTraits src offset = do+  let at = castPtr src `plusPtr` offset++  dims_count <- inflateIntegral $+    {#get SpvReflectArrayTraits->dims_count #} at++  dims <- fmap Vector.convert $ inflateVector+    ({#get SpvReflectArrayTraits->dims_count #} at)+    ({#get SpvReflectArrayTraits->dims #} at)+    {#sizeof uint32_t #}+    (fmap fromIntegral . peek)++  stride <- fmap Just . inflateIntegral $+    {#get SpvReflectArrayTraits->stride #} at++  pure Traits.Array{..}++-- * Atomic types++inflateIntegral :: (Integral a, Num b) => IO a -> IO b+inflateIntegral getIntegral =+  getIntegral >>=+      pure . fromIntegral++inflateEnum :: (Integral a, Enum b) => IO a -> IO b+inflateEnum getEnum =+  getEnum >>=+      pure . toEnum . fromIntegral++inflateFlags32 :: forall a b . (Integral a, Coercible Word32 b) => IO a -> IO b+inflateFlags32 gitBits =+  gitBits >>=+      pure . coerce @Word32 @b . fromIntegral++inflateText :: IO CString -> IO Text+inflateText getPtr =+  getPtr >>= \ptr ->+    if nullPtr == ptr then+      pure mempty+    else+      case ptr of+        GHC.Ptr addr ->+          pure $! Text.unpackCString# addr
+ spirv-reflect-ffi.cabal view
@@ -0,0 +1,99 @@+cabal-version: 1.12++-- This file has been generated from package.yaml by hpack version 0.34.4.+--+-- see: https://github.com/sol/hpack++name:           spirv-reflect-ffi+version:        0.1+synopsis:       C-library loader for spirv-reflect tool.+category:       Graphics+author:         IC Rainbow+maintainer:     ic.rbow@gmail.com+copyright:      2022 IC Rainbow+license:        BSD3+license-file:   LICENSE+build-type:     Simple+extra-source-files:+    cbits/include/spirv/unified1/spirv.h+    cbits/spirv_reflect.c+    cbits/spirv_reflect.h+    ChangeLog.md++source-repository head+  type: git+  location: https://gitlab.com/dpwiz/spirv-reflect++flag tests+  manual: True+  default: False++library+  exposed-modules:+      Data.SpirV.Reflect.FFI+      Data.SpirV.Reflect.FFI.Internal+  other-modules:+      Paths_spirv_reflect_ffi+  hs-source-dirs:+      lib+  default-extensions:+      ApplicativeDo+      BlockArguments+      DeriveGeneric+      DerivingStrategies+      DuplicateRecordFields+      FlexibleContexts+      GeneralizedNewtypeDeriving+      ImportQualifiedPost+      LambdaCase+      OverloadedStrings+      PatternSynonyms+      RecordWildCards+      StrictData+      TypeApplications+  include-dirs:+      cbits+  c-sources:+      cbits/spirv_reflect.c+  build-tools:+      c2hs+  build-depends:+      base >=4.7 && <5+    , bytestring+    , spirv-reflect-types >=0.2+    , text+    , vector+  default-language: Haskell2010++test-suite spirv-reflect-yaml-test+  type: exitcode-stdio-1.0+  main-is: Main.hs+  other-modules:+      Paths_spirv_reflect_ffi+  hs-source-dirs:+      test+  default-extensions:+      ApplicativeDo+      BlockArguments+      DeriveGeneric+      DerivingStrategies+      DuplicateRecordFields+      FlexibleContexts+      GeneralizedNewtypeDeriving+      ImportQualifiedPost+      LambdaCase+      OverloadedStrings+      PatternSynonyms+      RecordWildCards+      StrictData+      TypeApplications+  build-depends:+      base >=4.7 && <5+    , directory+    , filepath+    , spirv-reflect-ffi+    , tasty+    , tasty-hunit+  if !flag(tests)+    buildable: False+  default-language: Haskell2010
+ test/Main.hs view
@@ -0,0 +1,56 @@+{-# LANGUAGE BangPatterns #-}++module Main where++import Control.Monad (guard)+import System.Directory (doesDirectoryExist, listDirectory)+import System.FilePath (splitExtensions, takeFileName, (</>))+import Test.Tasty (TestTree, defaultMain, testGroup)+import Test.Tasty.HUnit (testCase)++import Data.SpirV.Reflect.FFI qualified as FFI++main :: IO ()+main = discover >>= defaultMain++discover :: IO TestTree+discover = do+  groupDirs <- listDirectory UPSTREAM_PATH >>= traverse \path -> do+    let groupPath = UPSTREAM_PATH </> path+    isDir <- doesDirectoryExist groupPath+    if not isDir then+      pure mempty+    else do+      groupContents <- listDirectory groupPath+      let+        files = do+          filePath <- groupContents+          case splitExtensions filePath of+            (name, ".spv") ->+              pure+                ( takeFileName name+                , groupPath </> filePath+                )+            _skip ->+              mempty+      pure (path, files)++  let+    groups = do+      (name, yamls) <- groupDirs+      guard $ not (null yamls)+      pure $ testGroup name (map mkTest yamls)++  pure $ testGroup "upstream" groups++mkTest :: (String, FilePath) -> TestTree+mkTest (name, file) =+  testCase name do+    -- putStrLn $ file <> " >>>>"+    !_loaded <- FFI.load file+    pure ()+    -- print loaded+    -- putStrLn $ file <> " <<<<"++pattern UPSTREAM_PATH :: FilePath+pattern UPSTREAM_PATH = "../SPIRV-Reflect/tests/"