diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,12 +1,20 @@
 # Changelog for spirv-reflect-ffi
 
+## [0.3] - 2024-09-30
+
+* Update cbits to `vulkan-sdk-1.3.290`.
+* Updates for `spirv-reflect-types-0.3`.
+
+[0.3]: https://gitlab.com/dpwiz/spirv-reflect/-/tree/v0.3-ffi
+
 ## [0.2] - 2022-09-04
 
 * Fixed a mess in input/output interface variables.
 
+[0.2]: https://gitlab.com/dpwiz/spirv-reflect/-/tree/v0.2-ffi
+
 ## [0.1] - 2022-09-04
 
 * Initial release.
 
 [0.1]: https://gitlab.com/dpwiz/spirv-reflect/-/tree/v0.1-ffi
-[0.2]: https://gitlab.com/dpwiz/spirv-reflect/-/tree/v0.2-ffi
diff --git a/cbits/include/spirv/unified1/spirv.h b/cbits/include/spirv/unified1/spirv.h
--- a/cbits/include/spirv/unified1/spirv.h
+++ b/cbits/include/spirv/unified1/spirv.h
@@ -1,2541 +1,4889 @@
 /*
 ** 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;
-    }
+**
+** 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, Beef
+**
+** - 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
+** - Beef will use enum classes in the Specification class located in the "Spv"
+*namespace,
+**     e.g.: Spv.Specification.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,
+  SpvSourceLanguageHERO_C = 8,
+  SpvSourceLanguageNZSL = 9,
+  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,
+  SpvExecutionModelTaskEXT = 5364,
+  SpvExecutionModelMeshEXT = 5365,
+  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,
+  SpvExecutionModeNonCoherentColorAttachmentReadEXT = 4169,
+  SpvExecutionModeNonCoherentDepthAttachmentReadEXT = 4170,
+  SpvExecutionModeNonCoherentStencilAttachmentReadEXT = 4171,
+  SpvExecutionModeSubgroupUniformControlFlowKHR = 4421,
+  SpvExecutionModePostDepthCoverage = 4446,
+  SpvExecutionModeDenormPreserve = 4459,
+  SpvExecutionModeDenormFlushToZero = 4460,
+  SpvExecutionModeSignedZeroInfNanPreserve = 4461,
+  SpvExecutionModeRoundingModeRTE = 4462,
+  SpvExecutionModeRoundingModeRTZ = 4463,
+  SpvExecutionModeEarlyAndLateFragmentTestsAMD = 5017,
+  SpvExecutionModeStencilRefReplacingEXT = 5027,
+  SpvExecutionModeStencilRefUnchangedFrontAMD = 5079,
+  SpvExecutionModeStencilRefGreaterFrontAMD = 5080,
+  SpvExecutionModeStencilRefLessFrontAMD = 5081,
+  SpvExecutionModeStencilRefUnchangedBackAMD = 5082,
+  SpvExecutionModeStencilRefGreaterBackAMD = 5083,
+  SpvExecutionModeStencilRefLessBackAMD = 5084,
+  SpvExecutionModeOutputLinesEXT = 5269,
+  SpvExecutionModeOutputLinesNV = 5269,
+  SpvExecutionModeOutputPrimitivesEXT = 5270,
+  SpvExecutionModeOutputPrimitivesNV = 5270,
+  SpvExecutionModeDerivativeGroupQuadsNV = 5289,
+  SpvExecutionModeDerivativeGroupLinearNV = 5290,
+  SpvExecutionModeOutputTrianglesEXT = 5298,
+  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,
+  SpvExecutionModeStreamingInterfaceINTEL = 6154,
+  SpvExecutionModeRegisterMapInterfaceINTEL = 6160,
+  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,
+  SpvStorageClassTileImageEXT = 4172,
+  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,
+  SpvStorageClassHitObjectAttributeNV = 5385,
+  SpvStorageClassTaskPayloadWorkgroupEXT = 5402,
+  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,
+  SpvDimTileImageDataEXT = 4173,
+  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,
+  SpvImageChannelDataTypeUnsignedIntRaw10EXT = 19,
+  SpvImageChannelDataTypeUnsignedIntRaw12EXT = 20,
+  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,
+  SpvFunctionParameterAttributeRuntimeAlignedINTEL = 5940,
+  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,
+  SpvDecorationWeightTextureQCOM = 4487,
+  SpvDecorationBlockMatchTextureQCOM = 4488,
+  SpvDecorationExplicitInterpAMD = 4999,
+  SpvDecorationOverrideCoverageNV = 5248,
+  SpvDecorationPassthroughNV = 5250,
+  SpvDecorationViewportRelativeNV = 5252,
+  SpvDecorationSecondaryViewportRelativeNV = 5256,
+  SpvDecorationPerPrimitiveEXT = 5271,
+  SpvDecorationPerPrimitiveNV = 5271,
+  SpvDecorationPerViewNV = 5272,
+  SpvDecorationPerTaskNV = 5273,
+  SpvDecorationPerVertexKHR = 5285,
+  SpvDecorationPerVertexNV = 5285,
+  SpvDecorationNonUniform = 5300,
+  SpvDecorationNonUniformEXT = 5300,
+  SpvDecorationRestrictPointer = 5355,
+  SpvDecorationRestrictPointerEXT = 5355,
+  SpvDecorationAliasedPointer = 5356,
+  SpvDecorationAliasedPointerEXT = 5356,
+  SpvDecorationHitObjectShaderRecordBufferNV = 5386,
+  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,
+  SpvDecorationMathOpDSPModeINTEL = 5909,
+  SpvDecorationAliasScopeINTEL = 5914,
+  SpvDecorationNoAliasINTEL = 5915,
+  SpvDecorationInitiationIntervalINTEL = 5917,
+  SpvDecorationMaxConcurrencyINTEL = 5918,
+  SpvDecorationPipelineEnableINTEL = 5919,
+  SpvDecorationBufferLocationINTEL = 5921,
+  SpvDecorationIOPipeStorageINTEL = 5944,
+  SpvDecorationFunctionFloatingPointModeINTEL = 6080,
+  SpvDecorationSingleElementVectorINTEL = 6085,
+  SpvDecorationVectorComputeCallableFunctionINTEL = 6087,
+  SpvDecorationMediaBlockIOINTEL = 6140,
+  SpvDecorationLatencyControlLabelINTEL = 6172,
+  SpvDecorationLatencyControlConstraintINTEL = 6173,
+  SpvDecorationConduitKernelArgumentINTEL = 6175,
+  SpvDecorationRegisterMapKernelArgumentINTEL = 6176,
+  SpvDecorationMMHostInterfaceAddressWidthINTEL = 6177,
+  SpvDecorationMMHostInterfaceDataWidthINTEL = 6178,
+  SpvDecorationMMHostInterfaceLatencyINTEL = 6179,
+  SpvDecorationMMHostInterfaceReadWriteModeINTEL = 6180,
+  SpvDecorationMMHostInterfaceMaxBurstINTEL = 6181,
+  SpvDecorationMMHostInterfaceWaitRequestINTEL = 6182,
+  SpvDecorationStableKernelArgumentINTEL = 6183,
+  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,
+  SpvBuiltInCoreIDARM = 4160,
+  SpvBuiltInCoreCountARM = 4161,
+  SpvBuiltInCoreMaxIDARM = 4162,
+  SpvBuiltInWarpIDARM = 4163,
+  SpvBuiltInWarpMaxIDARM = 4164,
+  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,
+  SpvBuiltInPrimitivePointIndicesEXT = 5294,
+  SpvBuiltInPrimitiveLineIndicesEXT = 5295,
+  SpvBuiltInPrimitiveTriangleIndicesEXT = 5296,
+  SpvBuiltInCullPrimitiveEXT = 5299,
+  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,
+  SpvBuiltInHitTriangleVertexPositionsKHR = 5335,
+  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,
+  SpvLoopControlLoopCountINTELShift = 24,
+  SpvLoopControlMaxReinvocationDelayINTELShift = 25,
+  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,
+  SpvLoopControlLoopCountINTELMask = 0x01000000,
+  SpvLoopControlMaxReinvocationDelayINTELMask = 0x02000000,
+} 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,
+  SpvCapabilityCoreBuiltinsARM = 4165,
+  SpvCapabilityTileImageColorReadAccessEXT = 4166,
+  SpvCapabilityTileImageDepthReadAccessEXT = 4167,
+  SpvCapabilityTileImageStencilReadAccessEXT = 4168,
+  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,
+  SpvCapabilityTextureSampleWeightedQCOM = 4484,
+  SpvCapabilityTextureBoxFilterQCOM = 4485,
+  SpvCapabilityTextureBlockMatchQCOM = 4486,
+  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,
+  SpvCapabilityMeshShadingEXT = 5283,
+  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,
+  SpvCapabilityRayTracingPositionFetchKHR = 5336,
+  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,
+  SpvCapabilityRayTracingOpacityMicromapEXT = 5381,
+  SpvCapabilityShaderInvocationReorderNV = 5383,
+  SpvCapabilityBindlessTextureNV = 5390,
+  SpvCapabilityRayQueryPositionFetchKHR = 5391,
+  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,
+  SpvCapabilityFPGADSPControlINTEL = 5908,
+  SpvCapabilityMemoryAccessAliasingINTEL = 5910,
+  SpvCapabilityFPGAInvocationPipeliningAttributesINTEL = 5916,
+  SpvCapabilityFPGABufferLocationINTEL = 5920,
+  SpvCapabilityArbitraryPrecisionFixedPointINTEL = 5922,
+  SpvCapabilityUSMStorageClassesINTEL = 5935,
+  SpvCapabilityRuntimeAlignedAttributeINTEL = 5939,
+  SpvCapabilityIOPipesINTEL = 5943,
+  SpvCapabilityBlockingPipesINTEL = 5945,
+  SpvCapabilityFPGARegINTEL = 5948,
+  SpvCapabilityDotProductInputAll = 6016,
+  SpvCapabilityDotProductInputAllKHR = 6016,
+  SpvCapabilityDotProductInput4x8Bit = 6017,
+  SpvCapabilityDotProductInput4x8BitKHR = 6017,
+  SpvCapabilityDotProductInput4x8BitPacked = 6018,
+  SpvCapabilityDotProductInput4x8BitPackedKHR = 6018,
+  SpvCapabilityDotProduct = 6019,
+  SpvCapabilityDotProductKHR = 6019,
+  SpvCapabilityRayCullMaskKHR = 6020,
+  SpvCapabilityCooperativeMatrixKHR = 6022,
+  SpvCapabilityBitInstructions = 6025,
+  SpvCapabilityGroupNonUniformRotateKHR = 6026,
+  SpvCapabilityAtomicFloat32AddEXT = 6033,
+  SpvCapabilityAtomicFloat64AddEXT = 6034,
+  SpvCapabilityLongConstantCompositeINTEL = 6089,
+  SpvCapabilityOptNoneINTEL = 6094,
+  SpvCapabilityAtomicFloat16AddEXT = 6095,
+  SpvCapabilityDebugInfoModuleINTEL = 6114,
+  SpvCapabilityBFloat16ConversionINTEL = 6115,
+  SpvCapabilitySplitBarrierINTEL = 6141,
+  SpvCapabilityFPGAKernelAttributesv2INTEL = 6161,
+  SpvCapabilityFPGALatencyControlINTEL = 6171,
+  SpvCapabilityFPGAArgumentInterfacesINTEL = 6174,
+  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,
+  SpvRayFlagsForceOpacityMicromap2StateEXTShift = 10,
+  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,
+  SpvRayFlagsForceOpacityMicromap2StateEXTMask = 0x00000400,
+} 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 SpvCooperativeMatrixOperandsShift_ {
+  SpvCooperativeMatrixOperandsMatrixASignedComponentsShift = 0,
+  SpvCooperativeMatrixOperandsMatrixBSignedComponentsShift = 1,
+  SpvCooperativeMatrixOperandsMatrixCSignedComponentsShift = 2,
+  SpvCooperativeMatrixOperandsMatrixResultSignedComponentsShift = 3,
+  SpvCooperativeMatrixOperandsSaturatingAccumulationShift = 4,
+  SpvCooperativeMatrixOperandsMax = 0x7fffffff,
+} SpvCooperativeMatrixOperandsShift;
+
+typedef enum SpvCooperativeMatrixOperandsMask_ {
+  SpvCooperativeMatrixOperandsMaskNone = 0,
+  SpvCooperativeMatrixOperandsMatrixASignedComponentsMask = 0x00000001,
+  SpvCooperativeMatrixOperandsMatrixBSignedComponentsMask = 0x00000002,
+  SpvCooperativeMatrixOperandsMatrixCSignedComponentsMask = 0x00000004,
+  SpvCooperativeMatrixOperandsMatrixResultSignedComponentsMask = 0x00000008,
+  SpvCooperativeMatrixOperandsSaturatingAccumulationMask = 0x00000010,
+} SpvCooperativeMatrixOperandsMask;
+
+typedef enum SpvCooperativeMatrixLayout_ {
+  SpvCooperativeMatrixLayoutRowMajorKHR = 0,
+  SpvCooperativeMatrixLayoutColumnMajorKHR = 1,
+  SpvCooperativeMatrixLayoutMax = 0x7fffffff,
+} SpvCooperativeMatrixLayout;
+
+typedef enum SpvCooperativeMatrixUse_ {
+  SpvCooperativeMatrixUseMatrixAKHR = 0,
+  SpvCooperativeMatrixUseMatrixBKHR = 1,
+  SpvCooperativeMatrixUseMatrixAccumulatorKHR = 2,
+  SpvCooperativeMatrixUseMax = 0x7fffffff,
+} SpvCooperativeMatrixUse;
+
+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,
+  SpvOpColorAttachmentReadEXT = 4160,
+  SpvOpDepthAttachmentReadEXT = 4161,
+  SpvOpStencilAttachmentReadEXT = 4162,
+  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,
+  SpvOpTypeCooperativeMatrixKHR = 4456,
+  SpvOpCooperativeMatrixLoadKHR = 4457,
+  SpvOpCooperativeMatrixStoreKHR = 4458,
+  SpvOpCooperativeMatrixMulAddKHR = 4459,
+  SpvOpCooperativeMatrixLengthKHR = 4460,
+  SpvOpTypeRayQueryKHR = 4472,
+  SpvOpRayQueryInitializeKHR = 4473,
+  SpvOpRayQueryTerminateKHR = 4474,
+  SpvOpRayQueryGenerateIntersectionKHR = 4475,
+  SpvOpRayQueryConfirmIntersectionKHR = 4476,
+  SpvOpRayQueryProceedKHR = 4477,
+  SpvOpRayQueryGetIntersectionTypeKHR = 4479,
+  SpvOpImageSampleWeightedQCOM = 4480,
+  SpvOpImageBoxFilterQCOM = 4481,
+  SpvOpImageBlockMatchSSDQCOM = 4482,
+  SpvOpImageBlockMatchSADQCOM = 4483,
+  SpvOpGroupIAddNonUniformAMD = 5000,
+  SpvOpGroupFAddNonUniformAMD = 5001,
+  SpvOpGroupFMinNonUniformAMD = 5002,
+  SpvOpGroupUMinNonUniformAMD = 5003,
+  SpvOpGroupSMinNonUniformAMD = 5004,
+  SpvOpGroupFMaxNonUniformAMD = 5005,
+  SpvOpGroupUMaxNonUniformAMD = 5006,
+  SpvOpGroupSMaxNonUniformAMD = 5007,
+  SpvOpFragmentMaskFetchAMD = 5011,
+  SpvOpFragmentFetchAMD = 5012,
+  SpvOpReadClockKHR = 5056,
+  SpvOpHitObjectRecordHitMotionNV = 5249,
+  SpvOpHitObjectRecordHitWithIndexMotionNV = 5250,
+  SpvOpHitObjectRecordMissMotionNV = 5251,
+  SpvOpHitObjectGetWorldToObjectNV = 5252,
+  SpvOpHitObjectGetObjectToWorldNV = 5253,
+  SpvOpHitObjectGetObjectRayDirectionNV = 5254,
+  SpvOpHitObjectGetObjectRayOriginNV = 5255,
+  SpvOpHitObjectTraceRayMotionNV = 5256,
+  SpvOpHitObjectGetShaderRecordBufferHandleNV = 5257,
+  SpvOpHitObjectGetShaderBindingTableRecordIndexNV = 5258,
+  SpvOpHitObjectRecordEmptyNV = 5259,
+  SpvOpHitObjectTraceRayNV = 5260,
+  SpvOpHitObjectRecordHitNV = 5261,
+  SpvOpHitObjectRecordHitWithIndexNV = 5262,
+  SpvOpHitObjectRecordMissNV = 5263,
+  SpvOpHitObjectExecuteShaderNV = 5264,
+  SpvOpHitObjectGetCurrentTimeNV = 5265,
+  SpvOpHitObjectGetAttributesNV = 5266,
+  SpvOpHitObjectGetHitKindNV = 5267,
+  SpvOpHitObjectGetPrimitiveIndexNV = 5268,
+  SpvOpHitObjectGetGeometryIndexNV = 5269,
+  SpvOpHitObjectGetInstanceIdNV = 5270,
+  SpvOpHitObjectGetInstanceCustomIndexNV = 5271,
+  SpvOpHitObjectGetWorldRayDirectionNV = 5272,
+  SpvOpHitObjectGetWorldRayOriginNV = 5273,
+  SpvOpHitObjectGetRayTMaxNV = 5274,
+  SpvOpHitObjectGetRayTMinNV = 5275,
+  SpvOpHitObjectIsEmptyNV = 5276,
+  SpvOpHitObjectIsHitNV = 5277,
+  SpvOpHitObjectIsMissNV = 5278,
+  SpvOpReorderThreadWithHitObjectNV = 5279,
+  SpvOpReorderThreadWithHintNV = 5280,
+  SpvOpTypeHitObjectNV = 5281,
+  SpvOpImageSampleFootprintNV = 5283,
+  SpvOpEmitMeshTasksEXT = 5294,
+  SpvOpSetMeshOutputsEXT = 5295,
+  SpvOpGroupNonUniformPartitionNV = 5296,
+  SpvOpWritePackedPrimitiveIndices4x8NV = 5299,
+  SpvOpReportIntersectionKHR = 5334,
+  SpvOpReportIntersectionNV = 5334,
+  SpvOpIgnoreIntersectionNV = 5335,
+  SpvOpTerminateRayNV = 5336,
+  SpvOpTraceNV = 5337,
+  SpvOpTraceMotionNV = 5338,
+  SpvOpTraceRayMotionNV = 5339,
+  SpvOpRayQueryGetIntersectionTriangleVertexPositionsKHR = 5340,
+  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,
+  SpvOpConvertFToBF16INTEL = 6116,
+  SpvOpConvertBF16ToFINTEL = 6117,
+  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 SpvOpColorAttachmentReadEXT:
+      *hasResult = true;
+      *hasResultType = true;
+      break;
+    case SpvOpDepthAttachmentReadEXT:
+      *hasResult = true;
+      *hasResultType = true;
+      break;
+    case SpvOpStencilAttachmentReadEXT:
+      *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 SpvOpTypeCooperativeMatrixKHR:
+      *hasResult = true;
+      *hasResultType = false;
+      break;
+    case SpvOpCooperativeMatrixLoadKHR:
+      *hasResult = true;
+      *hasResultType = true;
+      break;
+    case SpvOpCooperativeMatrixStoreKHR:
+      *hasResult = false;
+      *hasResultType = false;
+      break;
+    case SpvOpCooperativeMatrixMulAddKHR:
+      *hasResult = true;
+      *hasResultType = true;
+      break;
+    case SpvOpCooperativeMatrixLengthKHR:
+      *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 SpvOpImageSampleWeightedQCOM:
+      *hasResult = true;
+      *hasResultType = true;
+      break;
+    case SpvOpImageBoxFilterQCOM:
+      *hasResult = true;
+      *hasResultType = true;
+      break;
+    case SpvOpImageBlockMatchSSDQCOM:
+      *hasResult = true;
+      *hasResultType = true;
+      break;
+    case SpvOpImageBlockMatchSADQCOM:
+      *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 SpvOpHitObjectRecordHitMotionNV:
+      *hasResult = false;
+      *hasResultType = false;
+      break;
+    case SpvOpHitObjectRecordHitWithIndexMotionNV:
+      *hasResult = false;
+      *hasResultType = false;
+      break;
+    case SpvOpHitObjectRecordMissMotionNV:
+      *hasResult = false;
+      *hasResultType = false;
+      break;
+    case SpvOpHitObjectGetWorldToObjectNV:
+      *hasResult = true;
+      *hasResultType = true;
+      break;
+    case SpvOpHitObjectGetObjectToWorldNV:
+      *hasResult = true;
+      *hasResultType = true;
+      break;
+    case SpvOpHitObjectGetObjectRayDirectionNV:
+      *hasResult = true;
+      *hasResultType = true;
+      break;
+    case SpvOpHitObjectGetObjectRayOriginNV:
+      *hasResult = true;
+      *hasResultType = true;
+      break;
+    case SpvOpHitObjectTraceRayMotionNV:
+      *hasResult = false;
+      *hasResultType = false;
+      break;
+    case SpvOpHitObjectGetShaderRecordBufferHandleNV:
+      *hasResult = true;
+      *hasResultType = true;
+      break;
+    case SpvOpHitObjectGetShaderBindingTableRecordIndexNV:
+      *hasResult = true;
+      *hasResultType = true;
+      break;
+    case SpvOpHitObjectRecordEmptyNV:
+      *hasResult = false;
+      *hasResultType = false;
+      break;
+    case SpvOpHitObjectTraceRayNV:
+      *hasResult = false;
+      *hasResultType = false;
+      break;
+    case SpvOpHitObjectRecordHitNV:
+      *hasResult = false;
+      *hasResultType = false;
+      break;
+    case SpvOpHitObjectRecordHitWithIndexNV:
+      *hasResult = false;
+      *hasResultType = false;
+      break;
+    case SpvOpHitObjectRecordMissNV:
+      *hasResult = false;
+      *hasResultType = false;
+      break;
+    case SpvOpHitObjectExecuteShaderNV:
+      *hasResult = false;
+      *hasResultType = false;
+      break;
+    case SpvOpHitObjectGetCurrentTimeNV:
+      *hasResult = true;
+      *hasResultType = true;
+      break;
+    case SpvOpHitObjectGetAttributesNV:
+      *hasResult = false;
+      *hasResultType = false;
+      break;
+    case SpvOpHitObjectGetHitKindNV:
+      *hasResult = true;
+      *hasResultType = true;
+      break;
+    case SpvOpHitObjectGetPrimitiveIndexNV:
+      *hasResult = true;
+      *hasResultType = true;
+      break;
+    case SpvOpHitObjectGetGeometryIndexNV:
+      *hasResult = true;
+      *hasResultType = true;
+      break;
+    case SpvOpHitObjectGetInstanceIdNV:
+      *hasResult = true;
+      *hasResultType = true;
+      break;
+    case SpvOpHitObjectGetInstanceCustomIndexNV:
+      *hasResult = true;
+      *hasResultType = true;
+      break;
+    case SpvOpHitObjectGetWorldRayDirectionNV:
+      *hasResult = true;
+      *hasResultType = true;
+      break;
+    case SpvOpHitObjectGetWorldRayOriginNV:
+      *hasResult = true;
+      *hasResultType = true;
+      break;
+    case SpvOpHitObjectGetRayTMaxNV:
+      *hasResult = true;
+      *hasResultType = true;
+      break;
+    case SpvOpHitObjectGetRayTMinNV:
+      *hasResult = true;
+      *hasResultType = true;
+      break;
+    case SpvOpHitObjectIsEmptyNV:
+      *hasResult = true;
+      *hasResultType = true;
+      break;
+    case SpvOpHitObjectIsHitNV:
+      *hasResult = true;
+      *hasResultType = true;
+      break;
+    case SpvOpHitObjectIsMissNV:
+      *hasResult = true;
+      *hasResultType = true;
+      break;
+    case SpvOpReorderThreadWithHitObjectNV:
+      *hasResult = false;
+      *hasResultType = false;
+      break;
+    case SpvOpReorderThreadWithHintNV:
+      *hasResult = false;
+      *hasResultType = false;
+      break;
+    case SpvOpTypeHitObjectNV:
+      *hasResult = true;
+      *hasResultType = false;
+      break;
+    case SpvOpImageSampleFootprintNV:
+      *hasResult = true;
+      *hasResultType = true;
+      break;
+    case SpvOpEmitMeshTasksEXT:
+      *hasResult = false;
+      *hasResultType = false;
+      break;
+    case SpvOpSetMeshOutputsEXT:
+      *hasResult = false;
+      *hasResultType = false;
+      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 SpvOpRayQueryGetIntersectionTriangleVertexPositionsKHR:
+      *hasResult = true;
+      *hasResultType = true;
+      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 SpvOpConvertFToBF16INTEL:
+      *hasResult = true;
+      *hasResultType = true;
+      break;
+    case SpvOpConvertBF16ToFINTEL:
+      *hasResult = true;
+      *hasResultType = true;
+      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 */
 
diff --git a/cbits/spirv_reflect.c b/cbits/spirv_reflect.c
--- a/cbits/spirv_reflect.c
+++ b/cbits/spirv_reflect.c
@@ -15,5083 +15,5468 @@
 */
 
 #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;
+
+#include <assert.h>
+#include <stdbool.h>
+#include <string.h>
+
+#if defined(WIN32)
+#define _CRTDBG_MAP_ALLOC
+#include <crtdbg.h>
+#include <stdlib.h>
+#else
+#include <stdlib.h>
+#endif
+
+#if defined(__clang__) || (defined(__GNUC__) && __GNUC__ >= 7) || defined(__APPLE_CC__)
+#define FALLTHROUGH __attribute__((fallthrough))
+#else
+#define FALLTHROUGH
+#endif
+
+#if defined(SPIRV_REFLECT_ENABLE_ASSERTS)
+#define SPV_REFLECT_ASSERT(COND) assert(COND);
+#else
+#define SPV_REFLECT_ASSERT(COND)
+#endif
+
+// 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,
+};
+
+enum {
+  INVALID_VALUE  = 0xFFFFFFFF,
+};
+
+enum {
+  MAX_NODE_NAME_LENGTH        = 1024,
+  // Number of unique PhysicalStorageBuffer structs tracked to detect recursion
+  MAX_RECURSIVE_PHYSICAL_POINTER_CHECK = 128,
+};
+
+enum {
+  IMAGE_SAMPLED = 1,
+  IMAGE_STORAGE = 2,
+};
+
+typedef struct SpvReflectPrvArrayTraits {
+  uint32_t                        element_type_id;
+  uint32_t                        length_id;
+} SpvReflectPrvArrayTraits;
+
+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;
+
+typedef struct SpvReflectPrvNumberDecoration {
+  uint32_t                        word_offset;
+  uint32_t                        value;
+} SpvReflectPrvNumberDecoration;
+
+typedef struct SpvReflectPrvStringDecoration {
+  uint32_t                        word_offset;
+  const char*                     value;
+} SpvReflectPrvStringDecoration;
+
+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;
+  bool                            is_patch;
+  bool                            is_per_vertex;
+  bool                            is_per_task;
+  bool                            is_weight_texture;
+  bool                            is_block_match_texture;
+  SpvReflectUserType              user_type;
+  SpvReflectPrvNumberDecoration   set;
+  SpvReflectPrvNumberDecoration   binding;
+  SpvReflectPrvNumberDecoration   input_attachment_index;
+  SpvReflectPrvNumberDecoration   location;
+  SpvReflectPrvNumberDecoration   component;
+  SpvReflectPrvNumberDecoration   offset;
+  SpvReflectPrvNumberDecoration   uav_counter_buffer;
+  SpvReflectPrvStringDecoration   semantic;
+  uint32_t                        array_stride;
+  uint32_t                        matrix_stride;
+  uint32_t                        spec_id;
+  SpvBuiltIn                      built_in;
+} SpvReflectPrvDecorations;
+
+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;
+
+typedef struct SpvReflectPrvString {
+  uint32_t                        result_id;
+  const char*                     string;
+} SpvReflectPrvString;
+
+// There are a limit set of instructions that can touch an OpVariable,
+// these are represented here with how it was accessed
+// Examples:
+//    OpImageRead  -> OpLoad -> OpVariable
+//    OpImageWrite -> OpLoad -> OpVariable
+//    OpStore      -> OpAccessChain -> OpAccessChain -> OpVariable
+//    OpAtomicIAdd -> OpAccessChain -> OpVariable
+//    OpAtomicLoad -> OpImageTexelPointer -> OpVariable
+typedef struct SpvReflectPrvAccessedVariable {
+  SpvReflectPrvNode*     p_node;
+  uint32_t               result_id;
+  uint32_t               variable_ptr;
+  uint32_t               function_id;
+  uint32_t               function_parameter_index;
+} SpvReflectPrvAccessedVariable;
+
+typedef struct SpvReflectPrvFunction {
+  uint32_t                        id;
+  uint32_t                        parameter_count;
+  uint32_t*                       parameters;
+  uint32_t                        callee_count;
+  uint32_t*                       callees;
+  struct SpvReflectPrvFunction**  callee_ptrs;
+  uint32_t                        accessed_variable_count;
+  SpvReflectPrvAccessedVariable*  accessed_variables;
+} SpvReflectPrvFunction;
+
+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;
+  //
+  // Block variable ac is pointing to (for block references)
+  SpvReflectBlockVariable*        block_var;
+} SpvReflectPrvAccessChain;
+
+// To prevent infinite recursion, we never walk down a
+// PhysicalStorageBuffer struct twice, but incase a 2nd variable
+// needs to use that struct, save a copy
+typedef struct SpvReflectPrvPhysicalPointerStruct {
+    uint32_t struct_id;
+    // first variable to see the PhysicalStorageBuffer struct
+    SpvReflectBlockVariable* p_var;
+} SpvReflectPrvPhysicalPointerStruct;
+
+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;
+
+  SpvReflectTypeDescription*      physical_pointer_check[MAX_RECURSIVE_PHYSICAL_POINTER_CHECK];
+  uint32_t                        physical_pointer_count;
+
+  SpvReflectPrvPhysicalPointerStruct* physical_pointer_structs;
+  uint32_t                            physical_pointer_struct_count;
+} SpvReflectPrvParser;
+// clang-format on
+
+static uint32_t Max(uint32_t a, uint32_t b) { return a > b ? a : b; }
+static uint32_t Min(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;
+}
+
+static int SortCompareAccessedVariable(const void* a, const void* b) {
+  const SpvReflectPrvAccessedVariable* p_a = (const SpvReflectPrvAccessedVariable*)a;
+  const SpvReflectPrvAccessedVariable* p_b = (const SpvReflectPrvAccessedVariable*)b;
+
+  return (int)p_a->variable_ptr - (int)p_b->variable_ptr;
+}
+
+//
+// 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 IntersectSortedAccessedVariable(const SpvReflectPrvAccessedVariable* 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 SpvReflectPrvAccessedVariable* p_arr0_end = p_arr0 + arr0_size;
+  const uint32_t* p_arr1_end = p_arr1 + arr1_size;
+
+  const SpvReflectPrvAccessedVariable* p_idx0 = p_arr0;
+  const uint32_t* p_idx1 = p_arr1;
+  while (p_idx0 != p_arr0_end && p_idx1 != p_arr1_end) {
+    if (p_idx0->variable_ptr < *p_idx1) {
+      ++p_idx0;
+    } else if (p_idx0->variable_ptr > *p_idx1) {
+      ++p_idx1;
+    } else {
+      ++*res_size;
+      ++p_idx0;
+      ++p_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* p_idxr = *pp_res;
+    p_idx0 = p_arr0;
+    p_idx1 = p_arr1;
+    while (p_idx0 != p_arr0_end && p_idx1 != p_arr1_end) {
+      if (p_idx0->variable_ptr < *p_idx1) {
+        ++p_idx0;
+      } else if (p_idx0->variable_ptr > *p_idx1) {
+        ++p_idx1;
+      } else {
+        *(p_idxr++) = p_idx0->variable_ptr;
+        ++p_idx0;
+        ++p_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 UNCHECKED_READU32(parser, word_offset, value) \
+  { (void)ReadU32(parser, word_offset, (uint32_t*)&(value)); }
+
+#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;
+  }
+  if (p_decoration_fields->is_patch) {
+    decorations |= SPV_REFLECT_DECORATION_PATCH;
+  }
+  if (p_decoration_fields->is_per_vertex) {
+    decorations |= SPV_REFLECT_DECORATION_PER_VERTEX;
+  }
+  if (p_decoration_fields->is_per_task) {
+    decorations |= SPV_REFLECT_DECORATION_PER_TASK;
+  }
+  if (p_decoration_fields->is_weight_texture) {
+    decorations |= SPV_REFLECT_DECORATION_WEIGHT_TEXTURE;
+  }
+  if (p_decoration_fields->is_block_match_texture) {
+    decorations |= SPV_REFLECT_DECORATION_BLOCK_MATCH_TEXTURE;
+  }
+  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 bool IsSpecConstant(const SpvReflectPrvNode* p_node) {
+  return (p_node->op == SpvOpSpecConstant || p_node->op == SpvOpSpecConstantOp || p_node->op == SpvOpSpecConstantTrue ||
+          p_node->op == SpvOpSpecConstantFalse);
+}
+
+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 SpvReflectPrvAccessChain* FindAccessChain(SpvReflectPrvParser* p_parser, uint32_t id) {
+  const uint32_t ac_count = p_parser->access_chain_count;
+  for (uint32_t i = 0; i < ac_count; i++) {
+    if (p_parser->access_chains[i].result_id == id) {
+      return &p_parser->access_chains[i];
+    }
+  }
+  return 0;
+}
+
+// Access Chains mostly have their Base ID pointed directly to a OpVariable, but sometimes
+// it will be through a load and this funciton handles the edge cases how to find that
+static uint32_t FindAccessChainBaseVariable(SpvReflectPrvParser* p_parser, SpvReflectPrvAccessChain* p_access_chain) {
+  uint32_t base_id = p_access_chain->base_id;
+  SpvReflectPrvNode* base_node = FindNode(p_parser, base_id);
+  // TODO - This is just a band-aid to fix crashes.
+  // Need to understand why here and hopefully remove
+  // https://github.com/KhronosGroup/SPIRV-Reflect/pull/206
+  if (IsNull(base_node)) {
+    return 0;
+  }
+  while (base_node->op != SpvOpVariable) {
+    switch (base_node->op) {
+      case SpvOpLoad: {
+        UNCHECKED_READU32(p_parser, base_node->word_offset + 3, base_id);
+      } break;
+      case SpvOpFunctionParameter: {
+        UNCHECKED_READU32(p_parser, base_node->word_offset + 2, base_id);
+      } break;
+      case SpvOpBitcast:
+        // This can be caused by something like GL_EXT_buffer_reference_uvec2 trying to load a pointer.
+        // We currently call from a push constant, so no way to have a reference loop back into the PC block
+        return 0;
+      default: {
+        assert(false);
+      } break;
+    }
+
+    SpvReflectPrvAccessChain* base_ac = FindAccessChain(p_parser, base_id);
+    if (base_ac == 0) {
+      return 0;
+    }
+    base_id = base_ac->base_id;
+    base_node = FindNode(p_parser, base_id);
+    if (IsNull(base_node)) {
+      return 0;
+    }
+  }
+  return base_id;
+}
+
+static SpvReflectBlockVariable* GetRefBlkVar(SpvReflectPrvParser* p_parser, SpvReflectPrvAccessChain* p_access_chain) {
+  uint32_t base_id = p_access_chain->base_id;
+  SpvReflectPrvNode* base_node = FindNode(p_parser, base_id);
+  assert(base_node->op == SpvOpLoad);
+  UNCHECKED_READU32(p_parser, base_node->word_offset + 3, base_id);
+  SpvReflectPrvAccessChain* base_ac = FindAccessChain(p_parser, base_id);
+  assert(base_ac != 0);
+  SpvReflectBlockVariable* base_var = base_ac->block_var;
+  assert(base_var != 0);
+  return base_var;
+}
+
+bool IsPointerToPointer(SpvReflectPrvParser* p_parser, uint32_t type_id) {
+  SpvReflectPrvNode* ptr_node = FindNode(p_parser, type_id);
+  if (IsNull(ptr_node) || (ptr_node->op != SpvOpTypePointer)) {
+    return false;
+  }
+  uint32_t pte_id = 0;
+  UNCHECKED_READU32(p_parser, ptr_node->word_offset + 3, pte_id);
+  SpvReflectPrvNode* pte_node = FindNode(p_parser, pte_id);
+  if (IsNull(pte_node)) {
+    return false;
+  }
+  return pte_node->op == SpvOpTypePointer;
+}
+
+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].parameters);
+      SafeFree(p_parser->functions[i].callees);
+      SafeFree(p_parser->functions[i].callee_ptrs);
+      SafeFree(p_parser->functions[i].accessed_variables);
+    }
+
+    // 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);
+
+    if (IsNotNull(p_parser->physical_pointer_structs)) {
+      SafeFree(p_parser->physical_pointer_structs);
+    }
+    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.component.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.spec_id = (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
+
+          SafeFree(p_parser->source_embedded);
+          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, embedded_source_len + 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;
+        FALLTHROUGH;
+      }  // Fall through
+
+      // This is all the rest of OpType* that need to be tracked
+      // Possible new extensions might expose new type, will need to be added
+      // here
+      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:
+      case SpvOpTypeHitObjectNV:
+      case SpvOpTypeCooperativeMatrixNV:
+      case SpvOpTypeCooperativeMatrixKHR: {
+        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: {
+        uint32_t result_id;
+        CHECKED_READU32(p_parser, p_node->word_offset + 1, result_id);
+        // Look for forward pointer. Clear result id if found
+        SpvReflectPrvNode* p_fwd_node = FindNode(p_parser, result_id);
+        if (p_fwd_node) {
+          p_fwd_node->result_id = 0;
+        }
+        // Register pointer type
+        p_node->result_id = 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 || p_index_value_node->op == SpvOpSpecConstant)) {
+              // 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);
+        }
+        FALLTHROUGH;
+      }  // Fall through
+
+      case SpvOpFunctionEnd: {
+        function_node = (uint32_t)INVALID_VALUE;
+      } break;
+      case SpvOpFunctionParameter: {
+        CHECKED_READU32(p_parser, p_node->word_offset + 2, p_node->result_id);
+      } break;
+      case SpvOpBitcast:
+      case SpvOpShiftRightLogical:
+      case SpvOpIAdd:
+      case SpvOpISub:
+      case SpvOpIMul:
+      case SpvOpUDiv:
+      case SpvOpSDiv: {
+        CHECKED_READU32(p_parser, p_node->word_offset + 2, p_node->result_id);
+      } 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->parameter_count = 0;
+  p_func->callee_count = 0;
+  p_func->accessed_variable_count = 0;
+
+  // First get count to know how much to allocate
+  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 SpvOpFunctionParameter: {
+        ++(p_func->parameter_count);
+      } break;
+      case SpvOpFunctionCall: {
+        p_func->accessed_variable_count += p_node->word_count - 4;
+        ++(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_variable_count);
+      } break;
+      case SpvOpCopyMemory:
+      case SpvOpCopyMemorySized: {
+        p_func->accessed_variable_count += 2;
+      } break;
+      default:
+        break;
+    }
+  }
+
+  if (p_func->parameter_count > 0) {
+    p_func->parameters = (uint32_t*)calloc(p_func->parameter_count, sizeof(*(p_func->parameters)));
+    if (IsNull(p_func->parameters)) {
+      return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;
+    }
+  }
+
+  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_variable_count > 0) {
+    p_func->accessed_variables =
+        (SpvReflectPrvAccessedVariable*)calloc(p_func->accessed_variable_count, sizeof(*(p_func->accessed_variables)));
+    if (IsNull(p_func->accessed_variables)) {
+      return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;
+    }
+  }
+
+  p_func->parameter_count = 0;
+  p_func->callee_count = 0;
+  p_func->accessed_variable_count = 0;
+  // Now have allocation, fill in values
+  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 SpvOpFunctionParameter: {
+        CHECKED_READU32(p_parser, p_node->word_offset + 2, p_func->parameters[p_func->parameter_count]);
+        (++p_func->parameter_count);
+      } break;
+      case SpvOpFunctionCall: {
+        CHECKED_READU32(p_parser, p_node->word_offset + 3, p_func->callees[p_func->callee_count]);
+        const uint32_t result_index = p_node->word_offset + 2;
+        for (uint32_t j = 0, parameter_count = p_node->word_count - 4; j < parameter_count; j++) {
+          const uint32_t ptr_index = p_node->word_offset + 4 + j;
+          SpvReflectPrvAccessedVariable* access_ptr = &p_func->accessed_variables[p_func->accessed_variable_count];
+
+          access_ptr->p_node = p_node;
+          // Need to track Result ID as not sure there has been any memory access through here yet
+          CHECKED_READU32(p_parser, result_index, access_ptr->result_id);
+          CHECKED_READU32(p_parser, ptr_index, access_ptr->variable_ptr);
+          access_ptr->function_id = p_func->callees[p_func->callee_count];
+          access_ptr->function_parameter_index = j;
+          (++p_func->accessed_variable_count);
+        }
+        (++p_func->callee_count);
+      } break;
+      case SpvOpLoad:
+      case SpvOpAccessChain:
+      case SpvOpInBoundsAccessChain:
+      case SpvOpPtrAccessChain:
+      case SpvOpArrayLength:
+      case SpvOpGenericPtrMemSemantics:
+      case SpvOpInBoundsPtrAccessChain:
+      case SpvOpImageTexelPointer: {
+        const uint32_t result_index = p_node->word_offset + 2;
+        const uint32_t ptr_index = p_node->word_offset + 3;
+        SpvReflectPrvAccessedVariable* access_ptr = &p_func->accessed_variables[p_func->accessed_variable_count];
+
+        access_ptr->p_node = p_node;
+        // Need to track Result ID as not sure there has been any memory access through here yet
+        CHECKED_READU32(p_parser, result_index, access_ptr->result_id);
+        CHECKED_READU32(p_parser, ptr_index, access_ptr->variable_ptr);
+        (++p_func->accessed_variable_count);
+      } break;
+      case SpvOpStore: {
+        const uint32_t result_index = p_node->word_offset + 2;
+        CHECKED_READU32(p_parser, result_index, p_func->accessed_variables[p_func->accessed_variable_count].variable_ptr);
+        p_func->accessed_variables[p_func->accessed_variable_count].p_node = p_node;
+        (++p_func->accessed_variable_count);
+      } break;
+      case SpvOpCopyMemory:
+      case SpvOpCopyMemorySized: {
+        // There is no result_id or node, being zero is same as being invalid
+        CHECKED_READU32(p_parser, p_node->word_offset + 1,
+                        p_func->accessed_variables[p_func->accessed_variable_count].variable_ptr);
+        (++p_func->accessed_variable_count);
+        CHECKED_READU32(p_parser, p_node->word_offset + 2,
+                        p_func->accessed_variables[p_func->accessed_variable_count].variable_ptr);
+        (++p_func->accessed_variable_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_variable_count > 0) {
+    qsort(p_func->accessed_variables, p_func->accessed_variable_count, sizeof(*(p_func->accessed_variables)),
+          SortCompareAccessedVariable);
+  }
+
+  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;
+      for (size_t j = i; j < p_parser->node_count; ++j) {
+        if (p_parser->nodes[j].op == SpvOpLabel) {
+          func_definition = true;
+          break;
+        }
+        if (p_parser->nodes[j].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;
+}
+
+// Returns true if user_type matches pattern or if user_type begins with pattern and the next character is ':'
+// For example, UserTypeMatches("rwbuffer", "rwbuffer") will be true, UserTypeMatches("rwbuffer", "rwbuffer:<S>") will be true, and
+// UserTypeMatches("rwbuffer", "rwbufferfoo") will be false.
+static bool UserTypeMatches(const char* user_type, const char* pattern) {
+  const size_t pattern_length = strlen(pattern);
+  if (strncmp(user_type, pattern, pattern_length) == 0) {
+    if (user_type[pattern_length] == ':' || user_type[pattern_length] == '\0') {
+      return true;
+    }
+  }
+  return false;
+}
+
+static SpvReflectResult ParseDecorations(SpvReflectPrvParser* p_parser, SpvReflectShaderModule* p_module) {
+  uint32_t spec_constant_count = 0;
+  for (uint32_t i = 0; i < p_parser->node_count; ++i) {
+    SpvReflectPrvNode* p_node = &(p_parser->nodes[i]);
+
+    if ((p_node->op != SpvOpDecorate) && (p_node->op != SpvOpMemberDecorate) && (p_node->op != SpvOpDecorateId) &&
+        (p_node->op != SpvOpDecorateString) && (p_node->op != SpvOpMemberDecorateString)) {
+      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 SpvDecorationPatch:
+      case SpvDecorationPerVertexKHR:
+      case SpvDecorationPerTaskNV:
+      case SpvDecorationLocation:
+      case SpvDecorationComponent:
+      case SpvDecorationBinding:
+      case SpvDecorationDescriptorSet:
+      case SpvDecorationOffset:
+      case SpvDecorationInputAttachmentIndex:
+      case SpvDecorationSpecId:
+      case SpvDecorationWeightTextureQCOM:
+      case SpvDecorationBlockMatchTextureQCOM:
+      case SpvDecorationUserTypeGOOGLE:
+      case SpvDecorationHlslCounterBufferGOOGLE:
+      case SpvDecorationHlslSemanticGOOGLE: {
+        skip = false;
+      } break;
+    }
+    if (skip) {
+      continue;
+    }
+
+    // Find 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 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 SpvDecorationPatch: {
+        p_target_decorations->is_patch = true;
+      } break;
+
+      case SpvDecorationPerVertexKHR: {
+        p_target_decorations->is_per_vertex = true;
+      } break;
+
+      case SpvDecorationPerTaskNV: {
+        p_target_decorations->is_per_task = 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 SpvDecorationComponent: {
+        uint32_t word_offset = p_node->word_offset + member_offset + 3;
+        CHECKED_READU32(p_parser, word_offset, p_target_decorations->component.value);
+        p_target_decorations->component.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 SpvDecorationSpecId: {
+        spec_constant_count++;
+      } break;
+
+      case SpvDecorationHlslCounterBufferGOOGLE: {
+        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 SpvDecorationHlslSemanticGOOGLE: {
+        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;
+
+      case SpvDecorationWeightTextureQCOM: {
+        p_target_decorations->is_weight_texture = true;
+      } break;
+
+      case SpvDecorationBlockMatchTextureQCOM: {
+        p_target_decorations->is_block_match_texture = true;
+      } break;
+    }
+
+    if (p_node->op == SpvOpDecorateString && decoration == SpvDecorationUserTypeGOOGLE) {
+      uint32_t terminator = 0;
+      SpvReflectResult result = ReadStr(p_parser, p_node->word_offset + 3, 0, p_node->word_count, &terminator, NULL);
+      if (result != SPV_REFLECT_RESULT_SUCCESS) {
+        return result;
+      }
+      const char* name = (const char*)(p_parser->spirv_code + p_node->word_offset + 3);
+      if (UserTypeMatches(name, "cbuffer")) {
+        p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_CBUFFER;
+      } else if (UserTypeMatches(name, "tbuffer")) {
+        p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_TBUFFER;
+      } else if (UserTypeMatches(name, "appendstructuredbuffer")) {
+        p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_APPEND_STRUCTURED_BUFFER;
+      } else if (UserTypeMatches(name, "buffer")) {
+        p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_BUFFER;
+      } else if (UserTypeMatches(name, "byteaddressbuffer")) {
+        p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_BYTE_ADDRESS_BUFFER;
+      } else if (UserTypeMatches(name, "constantbuffer")) {
+        p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_CONSTANT_BUFFER;
+      } else if (UserTypeMatches(name, "consumestructuredbuffer")) {
+        p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_CONSUME_STRUCTURED_BUFFER;
+      } else if (UserTypeMatches(name, "inputpatch")) {
+        p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_INPUT_PATCH;
+      } else if (UserTypeMatches(name, "outputpatch")) {
+        p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_OUTPUT_PATCH;
+      } else if (UserTypeMatches(name, "rasterizerorderedbuffer")) {
+        p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_RASTERIZER_ORDERED_BUFFER;
+      } else if (UserTypeMatches(name, "rasterizerorderedbyteaddressbuffer")) {
+        p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_RASTERIZER_ORDERED_BYTE_ADDRESS_BUFFER;
+      } else if (UserTypeMatches(name, "rasterizerorderedstructuredbuffer")) {
+        p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_RASTERIZER_ORDERED_STRUCTURED_BUFFER;
+      } else if (UserTypeMatches(name, "rasterizerorderedtexture1d")) {
+        p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_RASTERIZER_ORDERED_TEXTURE_1D;
+      } else if (UserTypeMatches(name, "rasterizerorderedtexture1darray")) {
+        p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_RASTERIZER_ORDERED_TEXTURE_1D_ARRAY;
+      } else if (UserTypeMatches(name, "rasterizerorderedtexture2d")) {
+        p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_RASTERIZER_ORDERED_TEXTURE_2D;
+      } else if (UserTypeMatches(name, "rasterizerorderedtexture2darray")) {
+        p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_RASTERIZER_ORDERED_TEXTURE_2D_ARRAY;
+      } else if (UserTypeMatches(name, "rasterizerorderedtexture3d")) {
+        p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_RASTERIZER_ORDERED_TEXTURE_3D;
+      } else if (UserTypeMatches(name, "raytracingaccelerationstructure")) {
+        p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_RAYTRACING_ACCELERATION_STRUCTURE;
+      } else if (UserTypeMatches(name, "rwbuffer")) {
+        p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_RW_BUFFER;
+      } else if (UserTypeMatches(name, "rwbyteaddressbuffer")) {
+        p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_RW_BYTE_ADDRESS_BUFFER;
+      } else if (UserTypeMatches(name, "rwstructuredbuffer")) {
+        p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_RW_STRUCTURED_BUFFER;
+      } else if (UserTypeMatches(name, "rwtexture1d")) {
+        p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_RW_TEXTURE_1D;
+      } else if (UserTypeMatches(name, "rwtexture1darray")) {
+        p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_RW_TEXTURE_1D_ARRAY;
+      } else if (UserTypeMatches(name, "rwtexture2d")) {
+        p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_RW_TEXTURE_2D;
+      } else if (UserTypeMatches(name, "rwtexture2darray")) {
+        p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_RW_TEXTURE_2D_ARRAY;
+      } else if (UserTypeMatches(name, "rwtexture3d")) {
+        p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_RW_TEXTURE_3D;
+      } else if (UserTypeMatches(name, "structuredbuffer")) {
+        p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_STRUCTURED_BUFFER;
+      } else if (UserTypeMatches(name, "subpassinput")) {
+        p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_SUBPASS_INPUT;
+      } else if (UserTypeMatches(name, "subpassinputms")) {
+        p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_SUBPASS_INPUT_MS;
+      } else if (UserTypeMatches(name, "texture1d")) {
+        p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_TEXTURE_1D;
+      } else if (UserTypeMatches(name, "texture1darray")) {
+        p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_TEXTURE_1D_ARRAY;
+      } else if (UserTypeMatches(name, "texture2d")) {
+        p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_TEXTURE_2D;
+      } else if (UserTypeMatches(name, "texture2darray")) {
+        p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_TEXTURE_2D_ARRAY;
+      } else if (UserTypeMatches(name, "texture2dms")) {
+        p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_TEXTURE_2DMS;
+      } else if (UserTypeMatches(name, "texture2dmsarray")) {
+        p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_TEXTURE_2DMS_ARRAY;
+      } else if (UserTypeMatches(name, "texture3d")) {
+        p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_TEXTURE_3D;
+      } else if (UserTypeMatches(name, "texturebuffer")) {
+        p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_TEXTURE_BUFFER;
+      } else if (UserTypeMatches(name, "texturecube")) {
+        p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_TEXTURE_CUBE;
+      } else if (UserTypeMatches(name, "texturecubearray")) {
+        p_target_decorations->user_type = SPV_REFLECT_USER_TYPE_TEXTURE_CUBE_ARRAY;
+      }
+    }
+  }
+
+  if (spec_constant_count > 0) {
+    p_module->spec_constants = (SpvReflectSpecializationConstant*)calloc(spec_constant_count, sizeof(*p_module->spec_constants));
+    if (IsNull(p_module->spec_constants)) {
+      return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;
+    }
+  }
+  for (uint32_t i = 0; i < p_parser->node_count; ++i) {
+    SpvReflectPrvNode* p_node = &(p_parser->nodes[i]);
+    if (p_node->op == SpvOpDecorate) {
+      uint32_t decoration = (uint32_t)INVALID_VALUE;
+      CHECKED_READU32(p_parser, p_node->word_offset + 2, decoration);
+      if (decoration == SpvDecorationSpecId) {
+        const uint32_t count = p_module->spec_constant_count;
+        CHECKED_READU32(p_parser, p_node->word_offset + 1, p_module->spec_constants[count].spirv_id);
+        CHECKED_READU32(p_parser, p_node->word_offset + 3, p_module->spec_constants[count].constant_id);
+        // If being used for a OpSpecConstantComposite (ex. LocalSizeId), there won't be a name
+        SpvReflectPrvNode* target_node = FindNode(p_parser, p_module->spec_constants[count].spirv_id);
+        if (IsNotNull(target_node)) {
+          p_module->spec_constants[count].name = target_node->name;
+        }
+        p_module->spec_constant_count++;
+      }
+    }
+  }
+
+  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->struct_type_description = FindType(p_module, p_node->result_id);
+    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;
+            uint32_t length = 0;
+            IF_READU32(result, p_parser, p_length_node->word_offset + 3, length);
+            if (result == SPV_REFLECT_RESULT_SUCCESS) {
+              p_type->traits.array.dims[dim_index] = length;
+              p_type->traits.array.dims_count += 1;
+              p_type->traits.array.spec_constant_op_ids[dim_index] =
+                  IsSpecConstant(p_length_node) ? p_length_node->decorations.spec_id : (uint32_t)INVALID_VALUE;
+            } 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] = (uint32_t)SPV_REFLECT_ARRAY_DIM_RUNTIME;
+        p_type->traits.array.spec_constant_op_ids[dim_index] = (uint32_t)INVALID_VALUE;
+        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: {
+        p_type->type_flags |= SPV_REFLECT_TYPE_FLAG_REF;
+        IF_READU32_CAST(result, p_parser, p_node->word_offset + 2, SpvStorageClass, p_type->storage_class);
+
+        bool found_recursion = false;
+        if (p_type->storage_class == SpvStorageClassPhysicalStorageBuffer) {
+          // Need to make sure we haven't started an infinite recursive loop
+          for (uint32_t i = 0; i < p_parser->physical_pointer_count; i++) {
+            if (p_type->id == p_parser->physical_pointer_check[i]->id) {
+              found_recursion = true;
+              memcpy(p_type, p_parser->physical_pointer_check[i], sizeof(SpvReflectTypeDescription));
+              p_type->copied = 1;
+              return SPV_REFLECT_RESULT_SUCCESS;
+            }
+          }
+          if (!found_recursion) {
+            p_parser->physical_pointer_struct_count++;
+            p_parser->physical_pointer_check[p_parser->physical_pointer_count] = p_type;
+            p_parser->physical_pointer_count++;
+            if (p_parser->physical_pointer_count >= MAX_RECURSIVE_PHYSICAL_POINTER_CHECK) {
+              return SPV_REFLECT_RESULT_ERROR_SPIRV_MAX_RECURSIVE_EXCEEDED;
+            }
+          }
+        }
+
+        // Parse type
+        SpvReflectPrvNode* p_next_node = FindNode(p_parser, p_node->type_id);
+        if (IsNull(p_next_node)) {
+          result = SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;
+          SPV_REFLECT_ASSERT(false);
+        } else if (!found_recursion) {
+          if (p_next_node->op == SpvOpTypeStruct) {
+            p_type->struct_type_description = FindType(p_module, p_next_node->result_id);
+          }
+
+          result = ParseType(p_parser, p_next_node, NULL, p_module, p_type);
+        }
+      } 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]);
+    p_parser->physical_pointer_count = 0;
+    SpvReflectResult result = ParseType(p_parser, p_node, NULL, p_module, p_type);
+    if (result != SPV_REFLECT_RESULT_SUCCESS) {
+      return result;
+    }
+    ++type_index;
+  }
+
+  // allocate now and fill in when parsing struct variable later
+  if (p_parser->physical_pointer_struct_count > 0) {
+    p_parser->physical_pointer_structs = (SpvReflectPrvPhysicalPointerStruct*)calloc(p_parser->physical_pointer_struct_count,
+                                                                                     sizeof(*(p_parser->physical_pointer_structs)));
+    if (IsNull(p_parser->physical_pointer_structs)) {
+      return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;
+    }
+  }
+  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);
+    p_descriptor->user_type = p_node->decorations.user_type;
+
+    // Flags like non-writable and non-readable are found as member decorations only.
+    // If all members have one of those decorations set, promote the decoration up
+    // to the whole descriptor.
+    const SpvReflectPrvNode* p_type_node = FindNode(p_parser, p_type->id);
+    if (IsNotNull(p_type_node) && p_type_node->member_count) {
+      SpvReflectPrvDecorations common_flags = p_type_node->member_decorations[0];
+
+      for (uint32_t m = 1; m < p_type_node->member_count; ++m) {
+        common_flags.is_relaxed_precision &= p_type_node->member_decorations[m].is_relaxed_precision;
+        common_flags.is_block &= p_type_node->member_decorations[m].is_block;
+        common_flags.is_buffer_block &= p_type_node->member_decorations[m].is_buffer_block;
+        common_flags.is_row_major &= p_type_node->member_decorations[m].is_row_major;
+        common_flags.is_column_major &= p_type_node->member_decorations[m].is_column_major;
+        common_flags.is_built_in &= p_type_node->member_decorations[m].is_built_in;
+        common_flags.is_noperspective &= p_type_node->member_decorations[m].is_noperspective;
+        common_flags.is_flat &= p_type_node->member_decorations[m].is_flat;
+        common_flags.is_non_writable &= p_type_node->member_decorations[m].is_non_writable;
+        common_flags.is_non_readable &= p_type_node->member_decorations[m].is_non_readable;
+        common_flags.is_patch &= p_type_node->member_decorations[m].is_patch;
+        common_flags.is_per_vertex &= p_type_node->member_decorations[m].is_per_vertex;
+        common_flags.is_per_task &= p_type_node->member_decorations[m].is_per_task;
+        common_flags.is_weight_texture &= p_type_node->member_decorations[m].is_weight_texture;
+        common_flags.is_block_match_texture &= p_type_node->member_decorations[m].is_block_match_texture;
+      }
+
+      p_descriptor->decoration_flags |= ApplyDecorations(&common_flags);
+    }
+
+    // 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];
+      // If pointer type, treat like reference and resolve to pointee type
+      SpvReflectTypeDescription* p_member_ptr_type = 0;
+      bool found_recursion = false;
+
+      if ((p_member_type->storage_class == SpvStorageClassPhysicalStorageBuffer) &&
+          (p_member_type->type_flags & SPV_REFLECT_TYPE_FLAG_REF)) {
+        // Remember the original type
+        p_member_ptr_type = p_member_type;
+
+        // strip array
+        if (p_member_type->op == SpvOpTypeArray || p_member_type->op == SpvOpTypeRuntimeArray) {
+          SpvReflectPrvNode* p_node = FindNode(p_parser, p_member_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;
+          p_member_type = FindType(p_module, element_type_id);
+          if (p_member_type == NULL) {
+            return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;
+          }
+        }
+
+        // Need to make sure we haven't started an infinite recursive loop
+        for (uint32_t i = 0; i < p_parser->physical_pointer_count; i++) {
+          if (p_member_type->id == p_parser->physical_pointer_check[i]->id) {
+            found_recursion = true;
+            break;  // still need to fill in p_member_type values
+          }
+        }
+        if (!found_recursion) {
+          uint32_t struct_id = FindType(p_module, p_member_type->id)->struct_type_description->id;
+          p_parser->physical_pointer_structs[p_parser->physical_pointer_struct_count].struct_id = struct_id;
+          p_parser->physical_pointer_structs[p_parser->physical_pointer_struct_count].p_var = p_member_var;
+          p_parser->physical_pointer_struct_count++;
+
+          p_parser->physical_pointer_check[p_parser->physical_pointer_count] = p_member_type;
+          p_parser->physical_pointer_count++;
+          if (p_parser->physical_pointer_count >= MAX_RECURSIVE_PHYSICAL_POINTER_CHECK) {
+            return SPV_REFLECT_RESULT_ERROR_SPIRV_MAX_RECURSIVE_EXCEEDED;
+          }
+        }
+
+        SpvReflectPrvNode* p_member_type_node = FindNode(p_parser, p_member_type->id);
+        if (IsNull(p_member_type_node)) {
+          return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;
+        }
+        // Should be the pointee type
+        p_member_type = FindType(p_module, p_member_type_node->type_id);
+        if (IsNull(p_member_type)) {
+          return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;
+        }
+      }
+      bool is_struct = (p_member_type->type_flags & SPV_REFLECT_TYPE_FLAG_STRUCT) == SPV_REFLECT_TYPE_FLAG_STRUCT;
+      if (is_struct) {
+        if (!found_recursion) {
+          SpvReflectResult result = ParseDescriptorBlockVariable(p_parser, p_module, p_member_type, p_member_var);
+          if (result != SPV_REFLECT_RESULT_SUCCESS) {
+            return result;
+          }
+        } else {
+          // if 2 member of structs are same PhysicalPointer type, copy the
+          // members values that aren't found skipping the recursion call
+          for (uint32_t i = 0; i < p_parser->physical_pointer_struct_count; i++) {
+            if (p_parser->physical_pointer_structs[i].struct_id == p_member_type->id) {
+              p_member_var->members = p_parser->physical_pointer_structs[i].p_var->members;
+              p_member_var->member_count = p_parser->physical_pointer_structs[i].p_var->member_count;
+              // Set here as it is the first time we need to walk down structs
+              p_member_var->flags |= SPV_REFLECT_VARIABLE_FLAGS_PHYSICAL_POINTER_COPY;
+            }
+          }
+        }
+      }
+
+      if (p_type_node->storage_class == SpvStorageClassPhysicalStorageBuffer && !p_type_node->member_names) {
+        // TODO 212 - If a buffer ref has an array of itself, all members are null
+        continue;
+      }
+
+      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->word_offset.offset = p_type_node->member_decorations[member_index].offset.word_offset;
+      p_member_var->type_description = p_member_ptr_type ? p_member_ptr_type : 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 uint32_t GetPhysicalPointerStructSize(SpvReflectPrvParser* p_parser, uint32_t id) {
+  for (uint32_t i = 0; i < p_parser->physical_pointer_struct_count; i++) {
+    if (p_parser->physical_pointer_structs[i].struct_id == id) {
+      return p_parser->physical_pointer_structs[i].p_var->size;
+    }
+  }
+  return 0;
+}
+
+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;
+  }
+
+  bool is_parent_ref = p_var->type_description->op == SpvOpTypePointer;
+
+  // 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 : (is_parent_ref ? p_member_var->offset : 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;
+
+    if (!p_member_type) {
+      // TODO 212 - If a buffer ref has an array of itself, all members are null
+      continue;
+    }
+    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) {
+          if (p_member_var->flags & SPV_REFLECT_VARIABLE_FLAGS_PHYSICAL_POINTER_COPY) {
+            p_member_var->size = GetPhysicalPointerStructSize(p_parser, p_member_type->id);
+          } else {
+            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 SpvOpTypePointer: {
+        // Reference. Get to underlying struct type.
+        SpvReflectPrvNode* p_member_type_node = FindNode(p_parser, p_member_type->id);
+        if (IsNull(p_member_type_node)) {
+          return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;
+        }
+        // Get the pointee type
+        p_member_type = FindType(p_module, p_member_type_node->type_id);
+        if (IsNull(p_member_type)) {
+          return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;
+        }
+        assert(p_member_type->op == SpvOpTypeStruct);
+        FALLTHROUGH;
+      }
+
+      case SpvOpTypeStruct: {
+        if (p_member_var->flags & SPV_REFLECT_VARIABLE_FLAGS_PHYSICAL_POINTER_COPY) {
+          p_member_var->size = GetPhysicalPointerStructSize(p_parser, p_member_type->id);
+        } else {
+          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;
+    }
+  }
+
+  // Structs can offset order don't need to match the index order, so first order by offset
+  // example:
+  //     OpMemberDecorate %struct 0 Offset 4
+  //     OpMemberDecorate %struct 1 Offset 0
+  SpvReflectBlockVariable** pp_member_offset_order =
+      (SpvReflectBlockVariable**)calloc(p_var->member_count, sizeof(SpvReflectBlockVariable*));
+  if (IsNull(pp_member_offset_order)) {
+    return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;
+  }
+
+  uint32_t bottom_bound = 0;
+  for (uint32_t i = 0; i < p_var->member_count; ++i) {
+    uint32_t lowest_offset = UINT32_MAX;
+    uint32_t member_index = 0;
+    for (uint32_t j = 0; j < p_var->member_count; ++j) {
+      const uint32_t offset = p_var->members[j].offset;
+      if (offset < lowest_offset && offset >= bottom_bound) {
+        member_index = j;
+        lowest_offset = offset;
+      }
+    }
+    pp_member_offset_order[i] = &p_var->members[member_index];
+    bottom_bound = lowest_offset + 1;  // 2 index can't share the same offset
+  }
+
+  // Parse padded size using offset difference for all member except for the last entry...
+  for (uint32_t i = 0; i < (p_var->member_count - 1); ++i) {
+    SpvReflectBlockVariable* p_member_var = pp_member_offset_order[i];
+    SpvReflectBlockVariable* p_next_member_var = pp_member_offset_order[i + 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.
+  // last entry == entry with largest offset value
+  SpvReflectBlockVariable* p_last_member_var = pp_member_offset_order[p_var->member_count - 1];
+  p_last_member_var->padded_size =
+      RoundUp(p_last_member_var->offset + p_last_member_var->size, SPIRV_DATA_ALIGNMENT) - p_last_member_var->offset;
+  if (p_last_member_var->size > p_last_member_var->padded_size) {
+    p_last_member_var->size = p_last_member_var->padded_size;
+  }
+  if (is_parent_rta) {
+    p_last_member_var->padded_size = p_last_member_var->size;
+  }
+
+  SafeFree(pp_member_offset_order);
+
+  // If buffer ref, sizes are same as uint64_t
+  if (is_parent_ref) {
+    p_var->size = p_var->padded_size = 8;
+    return SPV_REFLECT_RESULT_SUCCESS;
+  }
+
+  // @TODO validate this with assertion
+  p_var->size = p_last_member_var->offset + p_last_member_var->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 UNUSED 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) {
+  // 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.
+  SpvReflectTypeDescription* p_type = p_var->type_description;
+  SpvOp op_type = p_type->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
+      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 reached 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 SpvOpTypePointer: {
+      // Reference. Get to underlying struct type.
+      SpvReflectPrvNode* p_type_node = FindNode(p_parser, p_type->id);
+      if (IsNull(p_type_node)) {
+        return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;
+      }
+      // Get the pointee type
+      p_type = FindType(p_module, p_type_node->type_id);
+      if (IsNull(p_type)) {
+        return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;
+      }
+      if (p_type->op != SpvOpTypeStruct) {
+        break;
+      }
+      FALLTHROUGH;
+    }
+
+    case SpvOpTypeStruct: {
+      assert(p_var->member_count > 0);
+      if (p_var->member_count == 0) {
+        return SPV_REFLECT_RESULT_ERROR_SPIRV_UNEXPECTED_BLOCK_DATA;
+      }
+
+      // The access chain can have zero indexes, if used for a runtime array
+      if (p_access_chain->index_count == 0) {
+        return SPV_REFLECT_RESULT_SUCCESS;
+      }
+
+      // 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];
+
+      bool is_pointer_to_pointer = IsPointerToPointer(p_parser, p_access_chain->result_type_id);
+      if (is_pointer_to_pointer) {
+        // Remember block var for this access chain for downstream dereference
+        p_access_chain->block_var = p_member_var;
+      }
+
+      // 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 if (!is_pointer_to_pointer) {
+        // Clear UNUSED flag for remaining variables
+        MarkSelfAndAllMemberVarsAsUsed(p_member_var);
+      }
+    } 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;
+  }
+
+  p_parser->physical_pointer_struct_count = 0;
+
+  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;
+    p_parser->physical_pointer_count = 0;
+    // 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 16: {
+          switch (component_count) {
+            case 2:
+              *p_format = SPV_REFLECT_FORMAT_R16G16_SFLOAT;
+              break;
+            case 3:
+              *p_format = SPV_REFLECT_FORMAT_R16G16B16_SFLOAT;
+              break;
+            case 4:
+              *p_format = SPV_REFLECT_FORMAT_R16G16B16A16_SFLOAT;
+              break;
+          }
+        } break;
+
+        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 16: {
+          switch (component_count) {
+            case 2:
+              *p_format = signedness ? SPV_REFLECT_FORMAT_R16G16_SINT : SPV_REFLECT_FORMAT_R16G16_UINT;
+              break;
+            case 3:
+              *p_format = signedness ? SPV_REFLECT_FORMAT_R16G16B16_SINT : SPV_REFLECT_FORMAT_R16G16B16_UINT;
+              break;
+            case 4:
+              *p_format = signedness ? SPV_REFLECT_FORMAT_R16G16B16A16_SINT : SPV_REFLECT_FORMAT_R16G16B16A16_UINT;
+              break;
+          }
+        } break;
+
+        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 16:
+        *p_format = SPV_REFLECT_FORMAT_R16_SFLOAT;
+        break;
+      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 16:
+        *p_format = signedness ? SPV_REFLECT_FORMAT_R16_SINT : SPV_REFLECT_FORMAT_R16_UINT;
+        break;
+        break;
+      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];
+
+      // Storage class is the same throughout the whole struct
+      p_member_var->storage_class = p_var->storage_class;
+
+      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);
+  } else {
+    // Apply member decoration values to struct members
+    p_var->location = p_type_node_decorations->location.value;
+    p_var->component = p_type_node_decorations->component.value;
+  }
+
+  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) || IsNull(p_type)) {
+      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->component = p_node->decorations.component.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 uint32_t GetUint32Constant(SpvReflectPrvParser* p_parser, uint32_t id) {
+  uint32_t result = (uint32_t)INVALID_VALUE;
+  SpvReflectPrvNode* p_node = FindNode(p_parser, id);
+  if (p_node && p_node->op == SpvOpConstant) {
+    UNCHECKED_READU32(p_parser, p_node->word_offset + 3, result);
+  }
+  return result;
+}
+
+static bool HasByteAddressBufferOffset(SpvReflectPrvNode* p_node, SpvReflectDescriptorBinding* p_binding) {
+  return IsNotNull(p_node) && IsNotNull(p_binding) && p_node->op == SpvOpAccessChain && p_node->word_count == 6 &&
+         (p_binding->user_type == SPV_REFLECT_USER_TYPE_BYTE_ADDRESS_BUFFER ||
+          p_binding->user_type == SPV_REFLECT_USER_TYPE_RW_BYTE_ADDRESS_BUFFER);
+}
+
+static SpvReflectResult ParseByteAddressBuffer(SpvReflectPrvParser* p_parser, SpvReflectPrvNode* p_node,
+                                               SpvReflectDescriptorBinding* p_binding) {
+  const SpvReflectResult not_found = SPV_REFLECT_RESULT_SUCCESS;
+  if (!HasByteAddressBufferOffset(p_node, p_binding)) {
+    return not_found;
+  }
+
+  uint32_t offset = 0;  // starting offset
+
+  uint32_t base_id = 0;
+  // expect first index of 2D access is zero
+  UNCHECKED_READU32(p_parser, p_node->word_offset + 4, base_id);
+  if (GetUint32Constant(p_parser, base_id) != 0) {
+    return not_found;
+  }
+  UNCHECKED_READU32(p_parser, p_node->word_offset + 5, base_id);
+  SpvReflectPrvNode* p_next_node = FindNode(p_parser, base_id);
+  if (IsNull(p_next_node)) {
+    return not_found;
+  } else if (p_next_node->op == SpvOpConstant) {
+    // The access chain might just be a constant right to the offset
+    offset = GetUint32Constant(p_parser, base_id);
+    p_binding->byte_address_buffer_offsets[p_binding->byte_address_buffer_offset_count] = offset;
+    p_binding->byte_address_buffer_offset_count++;
+    return SPV_REFLECT_RESULT_SUCCESS;
+  }
+
+  // there is usually 2 (sometimes 3) instrucitons that make up the arithmetic logic to calculate the offset
+  SpvReflectPrvNode* arithmetic_node_stack[8];
+  uint32_t arithmetic_count = 0;
+
+  while (IsNotNull(p_next_node)) {
+    if (p_next_node->op == SpvOpLoad || p_next_node->op == SpvOpBitcast || p_next_node->op == SpvOpConstant) {
+      break;  // arithmetic starts here
+    }
+    arithmetic_node_stack[arithmetic_count++] = p_next_node;
+    if (arithmetic_count >= 8) {
+      return not_found;
+    }
+
+    UNCHECKED_READU32(p_parser, p_next_node->word_offset + 3, base_id);
+    p_next_node = FindNode(p_parser, base_id);
+  }
+
+  const uint32_t count = arithmetic_count;
+  for (uint32_t i = 0; i < count; i++) {
+    p_next_node = arithmetic_node_stack[--arithmetic_count];
+    // All arithmetic ops takes 2 operands, assumption is the 2nd operand has the constant
+    UNCHECKED_READU32(p_parser, p_next_node->word_offset + 4, base_id);
+    uint32_t value = GetUint32Constant(p_parser, base_id);
+    if (value == INVALID_VALUE) {
+      return not_found;
+    }
+
+    switch (p_next_node->op) {
+      case SpvOpShiftRightLogical:
+        offset >>= value;
+        break;
+      case SpvOpIAdd:
+        offset += value;
+        break;
+      case SpvOpISub:
+        offset -= value;
+        break;
+      case SpvOpIMul:
+        offset *= value;
+        break;
+      case SpvOpUDiv:
+        offset /= value;
+        break;
+      case SpvOpSDiv:
+        // OpConstant might be signed, but value should never be negative
+        assert((int32_t)value > 0);
+        offset /= value;
+        break;
+      default:
+        return not_found;
+    }
+  }
+
+  p_binding->byte_address_buffer_offsets[p_binding->byte_address_buffer_offset_count] = offset;
+  p_binding->byte_address_buffer_offset_count++;
+  return SPV_REFLECT_RESULT_SUCCESS;
+}
+
+static SpvReflectResult ParseFunctionParameterAccess(SpvReflectPrvParser* p_parser, uint32_t callee_function_id,
+                                                     uint32_t function_parameter_index, uint32_t* p_accessed) {
+  SpvReflectPrvFunction* p_func = NULL;
+  for (size_t i = 0; i < p_parser->function_count; ++i) {
+    if (p_parser->functions[i].id == callee_function_id) {
+      p_func = &(p_parser->functions[i]);
+      break;
+    }
+  }
+  if (p_func == NULL) {
+    return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE;
+  }
+
+  assert(function_parameter_index < p_func->parameter_count);
+
+  for (size_t i = 0; i < p_func->accessed_variable_count; ++i) {
+    if (p_func->parameters[function_parameter_index] == p_func->accessed_variables[i].variable_ptr) {
+      SpvReflectPrvAccessedVariable* p_var = &p_func->accessed_variables[i];
+      if (p_var->function_id > 0) {
+        SpvReflectResult result =
+            ParseFunctionParameterAccess(p_parser, p_var->function_id, p_var->function_parameter_index, p_accessed);
+        if (result != SPV_REFLECT_RESULT_SUCCESS) {
+          return result;
+        }
+      } else {
+        *p_accessed = 1;
+      }
+      // Early out as soon as p_accessed is true
+      if (*p_accessed) {
+        return SPV_REFLECT_RESULT_SUCCESS;
+      }
+    }
+  }
+
+  *p_accessed = 0;
+  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) {
+    SafeFree(p_called_functions);
+    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_acessed_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_acessed_count += p_parser->functions[j].accessed_variable_count;
+  }
+  SpvReflectPrvAccessedVariable* p_used_accesses = NULL;
+  if (used_acessed_count > 0) {
+    p_used_accesses = (SpvReflectPrvAccessedVariable*)calloc(used_acessed_count, sizeof(SpvReflectPrvAccessedVariable));
+    if (IsNull(p_used_accesses)) {
+      SafeFree(p_called_functions);
+      return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;
+    }
+  }
+  used_acessed_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(&p_used_accesses[used_acessed_count], p_parser->functions[j].accessed_variables,
+           p_parser->functions[j].accessed_variable_count * sizeof(SpvReflectPrvAccessedVariable));
+    used_acessed_count += p_parser->functions[j].accessed_variable_count;
+  }
+  SafeFree(p_called_functions);
+
+  if (used_acessed_count > 0) {
+    qsort(p_used_accesses, used_acessed_count, sizeof(*p_used_accesses), SortCompareAccessedVariable);
+  }
+
+  // Do set intersection to find the used uniform and push constants
+  size_t used_uniform_count = 0;
+  result = IntersectSortedAccessedVariable(p_used_accesses, used_acessed_count, uniforms, uniform_count, &p_entry->used_uniforms,
+                                           &used_uniform_count);
+  if (result != SPV_REFLECT_RESULT_SUCCESS) {
+    SafeFree(p_used_accesses);
+    return result;
+  }
+
+  size_t used_push_constant_count = 0;
+  result = IntersectSortedAccessedVariable(p_used_accesses, used_acessed_count, push_constants, push_constant_count,
+                                           &p_entry->used_push_constants, &used_push_constant_count);
+  if (result != SPV_REFLECT_RESULT_SUCCESS) {
+    SafeFree(p_used_accesses);
+    return result;
+  }
+
+  for (uint32_t i = 0; i < p_module->descriptor_binding_count; ++i) {
+    SpvReflectDescriptorBinding* p_binding = &p_module->descriptor_bindings[i];
+    uint32_t byte_address_buffer_offset_count = 0;
+
+    for (uint32_t j = 0; j < used_acessed_count; j++) {
+      SpvReflectPrvAccessedVariable* p_var = &p_used_accesses[j];
+      if (p_var->variable_ptr == p_binding->spirv_id) {
+        if (p_var->function_id > 0) {
+          result =
+              ParseFunctionParameterAccess(p_parser, p_var->function_id, p_var->function_parameter_index, &p_binding->accessed);
+          if (result != SPV_REFLECT_RESULT_SUCCESS) {
+            SafeFree(p_used_accesses);
+            return result;
+          }
+        } else {
+          p_binding->accessed = 1;
+        }
+
+        if (HasByteAddressBufferOffset(p_used_accesses[j].p_node, p_binding)) {
+          byte_address_buffer_offset_count++;
+        }
+      }
+    }
+
+    // only if SPIR-V has ByteAddressBuffer user type
+    if (byte_address_buffer_offset_count > 0) {
+      bool multi_entrypoint = p_binding->byte_address_buffer_offset_count > 0;
+      if (multi_entrypoint) {
+        // If there is a 2nd entrypoint, we can have multiple entry points, in this case we want to just combine the accessed
+        // offsets and then de-duplicate it
+        uint32_t* prev_byte_address_buffer_offsets = p_binding->byte_address_buffer_offsets;
+        p_binding->byte_address_buffer_offsets =
+            (uint32_t*)calloc(byte_address_buffer_offset_count + p_binding->byte_address_buffer_offset_count, sizeof(uint32_t));
+        memcpy(p_binding->byte_address_buffer_offsets, prev_byte_address_buffer_offsets,
+               sizeof(uint32_t) * p_binding->byte_address_buffer_offset_count);
+        SafeFree(prev_byte_address_buffer_offsets);
+      } else {
+        // possible not all allocated offset slots are used, but this will be a max per binding
+        p_binding->byte_address_buffer_offsets = (uint32_t*)calloc(byte_address_buffer_offset_count, sizeof(uint32_t));
+      }
+
+      if (IsNull(p_binding->byte_address_buffer_offsets)) {
+        SafeFree(p_used_accesses);
+        return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;
+      }
+
+      for (uint32_t j = 0; j < used_acessed_count; j++) {
+        if (p_used_accesses[j].variable_ptr == p_binding->spirv_id) {
+          result = ParseByteAddressBuffer(p_parser, p_used_accesses[j].p_node, p_binding);
+          if (result != SPV_REFLECT_RESULT_SUCCESS) {
+            SafeFree(p_used_accesses);
+            return result;
+          }
+        }
+      }
+
+      if (multi_entrypoint) {
+        qsort(p_binding->byte_address_buffer_offsets, p_binding->byte_address_buffer_offset_count,
+              sizeof(*(p_binding->byte_address_buffer_offsets)), SortCompareUint32);
+        p_binding->byte_address_buffer_offset_count =
+            (uint32_t)DedupSortedUint32(p_binding->byte_address_buffer_offsets, p_binding->byte_address_buffer_offset_count);
+      }
+    }
+  }
+
+  SafeFree(p_used_accesses);
+
+  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 SpvExecutionModelTaskEXT:
+        p_entry_point->shader_stage = SPV_REFLECT_SHADER_STAGE_TASK_BIT_EXT;
+        break;
+      case SpvExecutionModelMeshNV:
+        p_entry_point->shader_stage = SPV_REFLECT_SHADER_STAGE_MESH_BIT_NV;
+        break;
+      case SpvExecutionModelMeshEXT:
+        p_entry_point->shader_stage = SPV_REFLECT_SHADER_STAGE_MESH_BIT_EXT;
+        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 && p_node->op != SpvOpExecutionModeId) {
+        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) {
+        case SpvExecutionModeInvocations: {
+          CHECKED_READU32(p_parser, p_node->word_offset + 3, p_entry_point->invocations);
+        } 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 SpvExecutionModeLocalSizeId: {
+          uint32_t local_size_x_id = 0;
+          uint32_t local_size_y_id = 0;
+          uint32_t local_size_z_id = 0;
+          CHECKED_READU32(p_parser, p_node->word_offset + 3, local_size_x_id);
+          CHECKED_READU32(p_parser, p_node->word_offset + 4, local_size_y_id);
+          CHECKED_READU32(p_parser, p_node->word_offset + 5, local_size_z_id);
+
+          SpvReflectPrvNode* x_node = FindNode(p_parser, local_size_x_id);
+          SpvReflectPrvNode* y_node = FindNode(p_parser, local_size_y_id);
+          SpvReflectPrvNode* z_node = FindNode(p_parser, local_size_z_id);
+          if (IsNotNull(x_node) && IsNotNull(y_node) && IsNotNull(z_node)) {
+            if (IsSpecConstant(x_node)) {
+              p_entry_point->local_size.x = (uint32_t)SPV_REFLECT_EXECUTION_MODE_SPEC_CONSTANT;
+            } else {
+              CHECKED_READU32(p_parser, x_node->word_offset + 3, p_entry_point->local_size.x);
+            }
+
+            if (IsSpecConstant(y_node)) {
+              p_entry_point->local_size.y = (uint32_t)SPV_REFLECT_EXECUTION_MODE_SPEC_CONSTANT;
+            } else {
+              CHECKED_READU32(p_parser, y_node->word_offset + 3, p_entry_point->local_size.y);
+            }
+
+            if (IsSpecConstant(z_node)) {
+              p_entry_point->local_size.z = (uint32_t)SPV_REFLECT_EXECUTION_MODE_SPEC_CONSTANT;
+            } else {
+              CHECKED_READU32(p_parser, z_node->word_offset + 3, p_entry_point->local_size.z);
+            }
+          }
+        } break;
+
+        case SpvExecutionModeOutputVertices: {
+          CHECKED_READU32(p_parser, p_node->word_offset + 3, p_entry_point->output_vertices);
+        } break;
+
+        default:
+          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];
+      if (p_entry_point->execution_mode_count > 0) {
+        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;
+  }
+
+  p_parser->physical_pointer_struct_count = 0;
+  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) || IsNull(p_type)) {
+      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;
+    p_parser->physical_pointer_count = 0;
+    SpvReflectResult result = ParseDescriptorBlockVariable(p_parser, p_module, p_type, p_push_constant);
+    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 push constant block
+      if (p_push_constant->spirv_id != FindAccessChainBaseVariable(p_parser, p_access_chain)) {
+        continue;
+      }
+      SpvReflectBlockVariable* p_var =
+          (p_access_chain->base_id == p_push_constant->spirv_id) ? p_push_constant : GetRefBlkVar(p_parser, p_access_chain);
+      result = ParseDescriptorBlockVariableUsage(p_parser, p_module, p_access_chain, 0, (SpvOp)INVALID_VALUE, p_var);
+      if (result != SPV_REFLECT_RESULT_SUCCESS) {
+        return result;
+      }
+    }
+
+    p_push_constant->name = p_node->name;
+    result = ParseDescriptorBlockVariableSizes(p_parser, p_module, true, false, false, p_push_constant);
+    if (result != SPV_REFLECT_RESULT_SUCCESS) {
+      return result;
+    }
+
+    // Get minimum offset for whole Push Constant block
+    // It is not valid SPIR-V to have an empty Push Constant Block
+    p_push_constant->offset = UINT32_MAX;
+    for (uint32_t k = 0; k < p_push_constant->member_count; ++k) {
+      const uint32_t member_offset = p_push_constant->members[k].offset;
+      p_push_constant->offset = Min(p_push_constant->offset, member_offset);
+    }
+
+    ++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);
+  }
+
+  // Initialize everything to zero
+  SpvReflectPrvParser parser;
+  memset(&parser, 0, sizeof(SpvReflectPrvParser));
+
+  // Create parser
+  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, p_module);
+    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) || p_type->copied) {
+    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;
+  }
+
+  // We share pointers to Physical Pointer structs and don't want to double free
+  if (p_block->flags & SPV_REFLECT_VARIABLE_FLAGS_PHYSICAL_POINTER_COPY) {
+    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];
+    if (IsNotNull(p_descriptor->byte_address_buffer_offsets)) {
+      SafeFree(p_descriptor->byte_address_buffer_offsets);
+    }
+    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);
+  SafeFree(p_module->spec_constants);
+
+  // 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;
+}
+
+SpvReflectResult spvReflectEnumerateSpecializationConstants(const SpvReflectShaderModule* p_module, uint32_t* p_count,
+                                                            SpvReflectSpecializationConstant** pp_constants) {
+  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_constants)) {
+    if (*p_count != p_module->spec_constant_count) {
+      return SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH;
+    }
+
+    for (uint32_t index = 0; index < *p_count; ++index) {
+      SpvReflectSpecializationConstant* p_constant = (SpvReflectSpecializationConstant*)&p_module->spec_constants[index];
+      pp_constants[index] = p_constant;
+    }
+  } else {
+    *p_count = p_module->spec_constant_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 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 SpvSourceLanguageHERO_C:
+      return "Hero C";
+    case SpvSourceLanguageNZSL:
+      return "NZSL";
+    default:
+      break;
+  }
+  // The source language is SpvSourceLanguageUnknown, SpvSourceLanguageMax, or
+  // some other value that does not correspond to a knonwn language.
+  return "Unknown";
+}
+
+const char* spvReflectBlockVariableTypeName(const SpvReflectBlockVariable* p_var) {
+  if (p_var == NULL) {
+    return NULL;
+  }
+  return p_var->type_description->type_name;
 }
diff --git a/cbits/spirv_reflect.h b/cbits/spirv_reflect.h
--- a/cbits/spirv_reflect.h
+++ b/cbits/spirv_reflect.h
@@ -22,6 +22,7 @@
 
 */
 
+// clang-format off
 /*!
 
  @file spirv_reflect.h
@@ -79,15 +80,16 @@
   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,
+  SPV_REFLECT_RESULT_ERROR_SPIRV_MAX_RECURSIVE_EXCEEDED,
 } 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 
+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 
+  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.
@@ -119,6 +121,7 @@
   SPV_REFLECT_TYPE_FLAG_EXTERNAL_MASK                   = 0x00FF0000,
   SPV_REFLECT_TYPE_FLAG_STRUCT                          = 0x10000000,
   SPV_REFLECT_TYPE_FLAG_ARRAY                           = 0x20000000,
+  SPV_REFLECT_TYPE_FLAG_REF                             = 0x40000000,
 } SpvReflectTypeFlagBits;
 
 typedef uint32_t SpvReflectTypeFlags;
@@ -132,6 +135,9 @@
       SPIRV-Reflect reads the data as is and does not make any
       attempt to correct it to match what's in the source.
 
+      The Patch, PerVertex, and PerTask are used for Interface
+      variables that can have array
+
 */
 typedef enum SpvReflectDecorationFlagBits {
   SPV_REFLECT_DECORATION_NONE                   = 0x00000000,
@@ -145,10 +151,59 @@
   SPV_REFLECT_DECORATION_NON_WRITABLE           = 0x00000080,
   SPV_REFLECT_DECORATION_RELAXED_PRECISION      = 0x00000100,
   SPV_REFLECT_DECORATION_NON_READABLE           = 0x00000200,
+  SPV_REFLECT_DECORATION_PATCH                  = 0x00000400,
+  SPV_REFLECT_DECORATION_PER_VERTEX             = 0x00000800,
+  SPV_REFLECT_DECORATION_PER_TASK               = 0x00001000,
+  SPV_REFLECT_DECORATION_WEIGHT_TEXTURE         = 0x00002000,
+  SPV_REFLECT_DECORATION_BLOCK_MATCH_TEXTURE    = 0x00004000,
 } SpvReflectDecorationFlagBits;
 
 typedef uint32_t SpvReflectDecorationFlags;
 
+// Based of SPV_GOOGLE_user_type
+typedef enum SpvReflectUserType {
+  SPV_REFLECT_USER_TYPE_INVALID = 0,
+  SPV_REFLECT_USER_TYPE_CBUFFER,
+  SPV_REFLECT_USER_TYPE_TBUFFER,
+  SPV_REFLECT_USER_TYPE_APPEND_STRUCTURED_BUFFER,
+  SPV_REFLECT_USER_TYPE_BUFFER,
+  SPV_REFLECT_USER_TYPE_BYTE_ADDRESS_BUFFER,
+  SPV_REFLECT_USER_TYPE_CONSTANT_BUFFER,
+  SPV_REFLECT_USER_TYPE_CONSUME_STRUCTURED_BUFFER,
+  SPV_REFLECT_USER_TYPE_INPUT_PATCH,
+  SPV_REFLECT_USER_TYPE_OUTPUT_PATCH,
+  SPV_REFLECT_USER_TYPE_RASTERIZER_ORDERED_BUFFER,
+  SPV_REFLECT_USER_TYPE_RASTERIZER_ORDERED_BYTE_ADDRESS_BUFFER,
+  SPV_REFLECT_USER_TYPE_RASTERIZER_ORDERED_STRUCTURED_BUFFER,
+  SPV_REFLECT_USER_TYPE_RASTERIZER_ORDERED_TEXTURE_1D,
+  SPV_REFLECT_USER_TYPE_RASTERIZER_ORDERED_TEXTURE_1D_ARRAY,
+  SPV_REFLECT_USER_TYPE_RASTERIZER_ORDERED_TEXTURE_2D,
+  SPV_REFLECT_USER_TYPE_RASTERIZER_ORDERED_TEXTURE_2D_ARRAY,
+  SPV_REFLECT_USER_TYPE_RASTERIZER_ORDERED_TEXTURE_3D,
+  SPV_REFLECT_USER_TYPE_RAYTRACING_ACCELERATION_STRUCTURE,
+  SPV_REFLECT_USER_TYPE_RW_BUFFER,
+  SPV_REFLECT_USER_TYPE_RW_BYTE_ADDRESS_BUFFER,
+  SPV_REFLECT_USER_TYPE_RW_STRUCTURED_BUFFER,
+  SPV_REFLECT_USER_TYPE_RW_TEXTURE_1D,
+  SPV_REFLECT_USER_TYPE_RW_TEXTURE_1D_ARRAY,
+  SPV_REFLECT_USER_TYPE_RW_TEXTURE_2D,
+  SPV_REFLECT_USER_TYPE_RW_TEXTURE_2D_ARRAY,
+  SPV_REFLECT_USER_TYPE_RW_TEXTURE_3D,
+  SPV_REFLECT_USER_TYPE_STRUCTURED_BUFFER,
+  SPV_REFLECT_USER_TYPE_SUBPASS_INPUT,
+  SPV_REFLECT_USER_TYPE_SUBPASS_INPUT_MS,
+  SPV_REFLECT_USER_TYPE_TEXTURE_1D,
+  SPV_REFLECT_USER_TYPE_TEXTURE_1D_ARRAY,
+  SPV_REFLECT_USER_TYPE_TEXTURE_2D,
+  SPV_REFLECT_USER_TYPE_TEXTURE_2D_ARRAY,
+  SPV_REFLECT_USER_TYPE_TEXTURE_2DMS,
+  SPV_REFLECT_USER_TYPE_TEXTURE_2DMS_ARRAY,
+  SPV_REFLECT_USER_TYPE_TEXTURE_3D,
+  SPV_REFLECT_USER_TYPE_TEXTURE_BUFFER,
+  SPV_REFLECT_USER_TYPE_TEXTURE_CUBE,
+  SPV_REFLECT_USER_TYPE_TEXTURE_CUBE_ARRAY,
+} SpvReflectUserType;
+
 /*! @enum SpvReflectResourceType
 
 */
@@ -165,6 +220,18 @@
 */
 typedef enum SpvReflectFormat {
   SPV_REFLECT_FORMAT_UNDEFINED           =   0, // = VK_FORMAT_UNDEFINED
+  SPV_REFLECT_FORMAT_R16_UINT            =  74, // = VK_FORMAT_R16_UINT
+  SPV_REFLECT_FORMAT_R16_SINT            =  75, // = VK_FORMAT_R16_SINT
+  SPV_REFLECT_FORMAT_R16_SFLOAT          =  76, // = VK_FORMAT_R16_SFLOAT
+  SPV_REFLECT_FORMAT_R16G16_UINT         =  81, // = VK_FORMAT_R16G16_UINT
+  SPV_REFLECT_FORMAT_R16G16_SINT         =  82, // = VK_FORMAT_R16G16_SINT
+  SPV_REFLECT_FORMAT_R16G16_SFLOAT       =  83, // = VK_FORMAT_R16G16_SFLOAT
+  SPV_REFLECT_FORMAT_R16G16B16_UINT      =  88, // = VK_FORMAT_R16G16B16_UINT
+  SPV_REFLECT_FORMAT_R16G16B16_SINT      =  89, // = VK_FORMAT_R16G16B16_SINT
+  SPV_REFLECT_FORMAT_R16G16B16_SFLOAT    =  90, // = VK_FORMAT_R16G16B16_SFLOAT
+  SPV_REFLECT_FORMAT_R16G16B16A16_UINT   =  95, // = VK_FORMAT_R16G16B16A16_UINT
+  SPV_REFLECT_FORMAT_R16G16B16A16_SINT   =  96, // = VK_FORMAT_R16G16B16A16_SINT
+  SPV_REFLECT_FORMAT_R16G16B16A16_SFLOAT =  97, // = VK_FORMAT_R16G16B16A16_SFLOAT
   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
@@ -197,6 +264,8 @@
 enum SpvReflectVariableFlagBits{
   SPV_REFLECT_VARIABLE_FLAGS_NONE   = 0x00000000,
   SPV_REFLECT_VARIABLE_FLAGS_UNUSED = 0x00000001,
+  // If variable points to a copy of the PhysicalStorageBuffer struct
+  SPV_REFLECT_VARIABLE_FLAGS_PHYSICAL_POINTER_COPY = 0x00000002,
 };
 
 typedef uint32_t SpvReflectVariableFlags;
@@ -230,7 +299,9 @@
   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_TASK_BIT_EXT                = SPV_REFLECT_SHADER_STAGE_TASK_BIT_NV, // = VK_SHADER_STAGE_CALLABLE_BIT_EXT
   SPV_REFLECT_SHADER_STAGE_MESH_BIT_NV                 = 0x00000080, // = VK_SHADER_STAGE_MESH_BIT_NV
+  SPV_REFLECT_SHADER_STAGE_MESH_BIT_EXT                = SPV_REFLECT_SHADER_STAGE_MESH_BIT_NV, // = VK_SHADER_STAGE_CALLABLE_BIT_EXT
   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
@@ -292,10 +363,16 @@
   SpvImageFormat                    image_format;
 } SpvReflectImageTraits;
 
+typedef enum SpvReflectArrayDimType {
+  SPV_REFLECT_ARRAY_DIM_RUNTIME       = 0,         // OpTypeRuntimeArray
+} SpvReflectArrayDimType;
+
 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.
+  // Each entry is either:
+  // - specialization constant dimension
+  // - OpTypeRuntimeArray
+  // - 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];
@@ -308,12 +385,13 @@
 } SpvReflectBindingArrayTraits;
 
 /*! @struct SpvReflectTypeDescription
-
+    @brief Information about an OpType* instruction
 */
 typedef struct SpvReflectTypeDescription {
   uint32_t                          id;
   SpvOp                             op;
   const char*                       type_name;
+  // Non-NULL if type is member of a struct
   const char*                       struct_member_name;
   SpvStorageClass                   storage_class;
   SpvReflectTypeFlags               type_flags;
@@ -325,18 +403,29 @@
     SpvReflectArrayTraits           array;
   } traits;
 
+  // If underlying type is a struct (ex. array of structs)
+  // this gives access to the OpTypeStruct
+  struct SpvReflectTypeDescription* struct_type_description;
+
+  // Some pointers to SpvReflectTypeDescription are really
+  // just copies of another reference to the same OpType
+  uint32_t                          copied;
+
+  // @deprecated use struct_type_description instead
   uint32_t                          member_count;
+  // @deprecated use struct_type_description instead
   struct SpvReflectTypeDescription* members;
 } SpvReflectTypeDescription;
 
 
 /*! @struct SpvReflectInterfaceVariable
-
+    @brief The OpVariable that is either an Input or Output to the module
 */
 typedef struct SpvReflectInterfaceVariable {
   uint32_t                            spirv_id;
   const char*                         name;
   uint32_t                            location;
+  uint32_t                            component;
   SpvStorageClass                     storage_class;
   const char*                         semantic;
   SpvReflectDecorationFlags           decoration_flags;
@@ -366,6 +455,7 @@
 typedef struct SpvReflectBlockVariable {
   uint32_t                          spirv_id;
   const char*                       name;
+  // For Push Constants, this is the lowest offset of all memebers
   uint32_t                          offset;           // Measured in bytes
   uint32_t                          absolute_offset;  // Measured in bytes
   uint32_t                          size;             // Measured in bytes
@@ -379,6 +469,11 @@
   struct SpvReflectBlockVariable*   members;
 
   SpvReflectTypeDescription*        type_description;
+
+  struct {
+    uint32_t                          offset;
+  } word_offset;
+
 } SpvReflectBlockVariable;
 
 /*! @struct SpvReflectDescriptorBinding
@@ -399,6 +494,8 @@
   uint32_t                            accessed;
   uint32_t                            uav_counter_id;
   struct SpvReflectDescriptorBinding* uav_counter_binding;
+  uint32_t                            byte_address_buffer_offset_count;
+  uint32_t*                           byte_address_buffer_offsets;
 
   SpvReflectTypeDescription*          type_description;
 
@@ -408,6 +505,8 @@
   } word_offset;
 
   SpvReflectDecorationFlags           decoration_flags;
+  // Requires SPV_GOOGLE_user_type
+  SpvReflectUserType                  user_type;
 } SpvReflectDescriptorBinding;
 
 /*! @struct SpvReflectDescriptorSet
@@ -419,6 +518,10 @@
   SpvReflectDescriptorBinding**     bindings;
 } SpvReflectDescriptorSet;
 
+typedef enum SpvReflectExecutionModeValue {
+  SPV_REFLECT_EXECUTION_MODE_SPEC_CONSTANT = 0xFFFFFFFF // specialization constant
+} SpvReflectExecutionModeValue;
+
 /*! @struct SpvReflectEntryPoint
 
  */
@@ -429,10 +532,10 @@
   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                          input_variable_count;
+  SpvReflectInterfaceVariable**     input_variables;
+  uint32_t                          output_variable_count;
+  SpvReflectInterfaceVariable**     output_variables;
   uint32_t                          interface_variable_count;
   SpvReflectInterfaceVariable*      interface_variables;
 
@@ -464,6 +567,16 @@
   uint32_t                          word_offset;
 } SpvReflectCapability;
 
+
+/*! @struct SpvReflectSpecId
+
+*/
+typedef struct SpvReflectSpecializationConstant {
+  uint32_t spirv_id;
+  uint32_t constant_id;
+  const char* name;
+} SpvReflectSpecializationConstant;
+
 /*! @struct SpvReflectShaderModule
 
 */
@@ -493,6 +606,8 @@
   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
+  uint32_t                          spec_constant_count;                              // Uses value(s) from first entry point
+  SpvReflectSpecializationConstant* spec_constants;                                   // Uses value(s) from first entry point
 
   struct Internal {
     SpvReflectModuleFlags           module_flags;
@@ -904,6 +1019,25 @@
 );
 
 
+/*! @fn spvReflectEnumerateSpecializationConstants
+ @param  p_module      Pointer to an instance of SpvReflectShaderModule.
+ @param  p_count       If pp_blocks is NULL, the module's specialization constant
+                       count will be stored here. If pp_blocks is not NULL, *p_count
+                       must contain the module's specialization constant count.
+ @param  pp_constants  If NULL, the module's specialization constant 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 specialization constant blocks will be written.
+                       The caller must not free the  variables written to this array.
+ @return               If successful, returns SPV_REFLECT_RESULT_SUCCESS.
+                       Otherwise, the error code indicates the cause of the failure.
+*/
+SpvReflectResult spvReflectEnumerateSpecializationConstants(
+  const SpvReflectShaderModule*      p_module,
+  uint32_t*                          p_count,
+  SpvReflectSpecializationConstant** pp_constants
+);
+
 /*! @fn spvReflectGetDescriptorBinding
 
  @param  p_module        Pointer to an instance of SpvReflectShaderModule.
@@ -1436,7 +1570,7 @@
 };
 #endif
 
-#if defined(__cplusplus)
+#if defined(__cplusplus) && !defined(SPIRV_REFLECT_DISABLE_CPP_BINDINGS)
 #include <cstdlib>
 #include <string>
 #include <vector>
@@ -1494,6 +1628,7 @@
   SpvReflectResult  EnumeratePushConstants(uint32_t* p_count, SpvReflectBlockVariable** pp_blocks) const {
     return EnumeratePushConstantBlocks(p_count, pp_blocks);
   }
+  SpvReflectResult  EnumerateSpecializationConstants(uint32_t* p_count, SpvReflectSpecializationConstant** pp_constants) const;
 
   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;
@@ -1572,7 +1707,7 @@
 /*! @fn ShaderModule
 
   @param  code
-  
+
 */
 inline ShaderModule::ShaderModule(const std::vector<uint8_t>& code, SpvReflectModuleFlags flags) {
   m_result = spvReflectCreateShaderModule2(
@@ -1585,7 +1720,7 @@
 /*! @fn ShaderModule
 
   @param  code
-  
+
 */
 inline ShaderModule::ShaderModule(const std::vector<uint32_t>& code, SpvReflectModuleFlags flags) {
   m_result = spvReflectCreateShaderModule2(
@@ -1666,9 +1801,9 @@
   return this->GetEntryPointName(0);
 }
 
-/*! @fn GetEntryPoint
+/*! @fn GetSourceFile
 
-  @return Returns entry point
+  @return Returns source file
 
 */
 inline const char* ShaderModule::GetSourceFile() const {
@@ -1941,6 +2076,24 @@
   return m_result;
 }
 
+/*! @fn EnumerateSpecializationConstants
+  @param  p_count
+  @param  pp_constants
+  @return
+*/
+inline SpvReflectResult ShaderModule::EnumerateSpecializationConstants(
+    uint32_t*                          p_count,
+    SpvReflectSpecializationConstant** pp_constants
+) const
+{
+  m_result = spvReflectEnumerateSpecializationConstants(
+    &m_module,
+    p_count,
+    pp_constants
+  );
+  return m_result;
+}
+
 /*! @fn EnumerateEntryPointPushConstantBlocks
 
   @param  entry_point
@@ -2288,5 +2441,7 @@
 }
 
 } // namespace spv_reflect
-#endif // defined(__cplusplus)
+#endif // defined(__cplusplus) && !defined(SPIRV_REFLECT_DISABLE_CPP_WRAPPER)
 #endif // SPIRV_REFLECT_H
+
+// clang-format on
diff --git a/lib/Data/SpirV/Reflect/FFI.hs b/lib/Data/SpirV/Reflect/FFI.hs
--- a/lib/Data/SpirV/Reflect/FFI.hs
+++ b/lib/Data/SpirV/Reflect/FFI.hs
@@ -1,16 +1,19 @@
+{-# LANGUAGE Strict #-}
+
 module Data.SpirV.Reflect.FFI
   ( Module
   , load
   , loadBytes
   ) where
 
-import Control.Exception (finally)
+import Control.Exception (onException)
 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 Foreign (callocBytes, castPtr, free)
+import System.Mem.Weak (addFinalizer)
 
 import Data.SpirV.Reflect.Module (Module)
 
@@ -21,14 +24,17 @@
 loadBytes :: MonadIO io => ByteString -> io Module
 loadBytes bytes = liftIO do
   unsafeUseAsCStringLen bytes \(code, size) -> do
-    allocaBytes C.shaderModuleSize \smPtr -> do
+    smPtr <- callocBytes C.shaderModuleSize
+    flip onException (free smPtr) do
       res <- C.createShaderModule2
         C.SpvReflectModuleFlagNoCopy
         (fromIntegral size)
         (castPtr code)
         smPtr
       case res of
-        C.SpvReflectResultSuccess ->
-          C.inflateModule smPtr `finally` C.destroyShaderModule smPtr
+        C.SpvReflectResultSuccess -> do
+          m <- C.inflateModule smPtr `onException` C.destroyShaderModule smPtr
+          addFinalizer m $ C.destroyShaderModule smPtr
+          pure m
         err ->
           error $ "spvReflectCreateShaderModule2:" <> show err
diff --git a/lib/Data/SpirV/Reflect/FFI/Internal.chs b/lib/Data/SpirV/Reflect/FFI/Internal.chs
--- a/lib/Data/SpirV/Reflect/FFI/Internal.chs
+++ b/lib/Data/SpirV/Reflect/FFI/Internal.chs
@@ -1,15 +1,19 @@
 {-# LANGUAGE MagicHash #-}
 {-# LANGUAGE NamedFieldPuns #-}
 {-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE Strict #-}
 
 module Data.SpirV.Reflect.FFI.Internal where
 
 import Data.Coerce (Coercible, coerce)
-import Data.List (sortOn)
+import Data.Ord (comparing)
+import Data.SpirV.Enum qualified as SpirV
+import Data.SpirV.Enum.StorageClass qualified as StorageClass
 import Data.Text (Text)
 import Data.Text qualified as Text
 import Data.Vector (Vector)
 import Data.Vector qualified as Vector
+import Data.Vector.Algorithms.Heap qualified as Heap
 import Data.Word (Word32)
 import Foreign.C.String (CString)
 import Foreign.C.Types (CULong)
@@ -24,7 +28,7 @@
 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.Enums qualified as Reflect
 import Data.SpirV.Reflect.InterfaceVariable (InterfaceVariable)
 import Data.SpirV.Reflect.InterfaceVariable qualified as InterfaceVariable
 import Data.SpirV.Reflect.Module (Module)
@@ -32,6 +36,8 @@
 import Data.SpirV.Reflect.Traits qualified as Traits
 import Data.SpirV.Reflect.TypeDescription (TypeDescription)
 import Data.SpirV.Reflect.TypeDescription qualified as TypeDescription
+import Data.SpirV.Reflect.SpecializationConstant (SpecializationConstant)
+import Data.SpirV.Reflect.SpecializationConstant qualified as SpecializationConstant
 
 #include "spirv_reflect.h"
 
@@ -137,16 +143,15 @@
       location
 
     pickIvs query =
-      Vector.fromList . sortOn ivLocation . filter query $
-        Vector.toList interface_variables
+      Vector.modify (Heap.sortBy $ comparing ivLocation) $ Vector.filter query interface_variables
 
     input_variables =
       pickIvs $
-        (== Enums.StorageClassInput) . InterfaceVariable.storage_class
+        (== StorageClass.Input) . InterfaceVariable.storage_class
 
     output_variables =
       pickIvs $
-        (== Enums.StorageClassOutput) . InterfaceVariable.storage_class
+        (== StorageClass.Output) . InterfaceVariable.storage_class
 
   push_constants <-
     inflateVector
@@ -155,20 +160,20 @@
       {#sizeof SpvReflectBlockVariable #}
       inflateBlockVariable
 
-  pure Module.Module{..}
+  spec_constants <-
+    inflateVector
+      ({#get SpvReflectShaderModule->spec_constant_count #} sm)
+      ({#get SpvReflectShaderModule->spec_constants #} sm)
+      {#sizeof SpvReflectSpecializationConstant #}
+      inflateSpecConstant
 
-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)
+  pure Module.Module{..}
 
 {#pointer *SpvReflectDescriptorBinding as DescriptorBindingPtr #}
 
 inflateDescriptorBinding :: DescriptorBindingPtr -> IO DescriptorBinding
 inflateDescriptorBinding db = do
-  spirv_id <- fmap Just . inflateIntegral $
+  spirv_id <- fmap just . inflateIntegral $
     {#get SpvReflectDescriptorBinding->spirv_id #} db
 
   name <- inflateText $
@@ -203,7 +208,7 @@
       db
       {#offsetof SpvReflectDescriptorBinding->array #}
 
-  count <- fmap Just . inflateIntegral $
+  count <- fmap just . inflateIntegral $
     {#get SpvReflectDescriptorBinding->count #} db
 
   accessed <- inflateIntegral $
@@ -225,16 +230,39 @@
   decoration_flags <- inflateFlags32 $
     {#get SpvReflectDescriptorBinding->decoration_flags #} db
 
+  byte_address_buffer_offsets <-
+    inflateVector
+      ({#get SpvReflectDescriptorBinding->byte_address_buffer_offset_count #} db)
+      ({#get SpvReflectDescriptorBinding->byte_address_buffer_offsets #} db)
+      {#sizeof uint32_t #}
+      (fmap fromIntegral . peek)
+
+  user_type <- inflateMaybe (Reflect.UserType 0) inflateEnum $
+    {#get SpvReflectDescriptorBinding->user_type #} db
+
   pure DescriptorBinding.DescriptorBinding{..}
 
+inflateSpecConstant :: Ptr () -> IO SpecializationConstant
+inflateSpecConstant sc = do
+  spirv_id <- fmap just . inflateIntegral $
+    {#get SpvReflectSpecializationConstant->spirv_id #} sc
+
+  constant_id <- inflateIntegral $
+    {#get SpvReflectSpecializationConstant->constant_id #} sc
+
+  name <- inflateMaybe "" inflateText $
+    {#get SpvReflectSpecializationConstant->name #} sc
+
+  pure SpecializationConstant.SpecializationConstant {..}
+
 {#pointer *SpvReflectBlockVariable as BlockVariablePtr #}
 
 inflateBlockVariable :: BlockVariablePtr -> IO BlockVariable
 inflateBlockVariable bv = do
-  spirv_id <- fmap Just . inflateIntegral $
+  spirv_id <- fmap just . inflateIntegral $
     {#get SpvReflectBlockVariable->spirv_id #} bv
 
-  name <- fmap Just . inflateText $
+  name <- inflateMaybe "" inflateText $
     {#get SpvReflectBlockVariable->name #} bv
 
   offset <- inflateIntegral $
@@ -270,28 +298,32 @@
       inflateBlockVariable
 
   type_description <-
-    {#get SpvReflectBlockVariable->members #} bv >>=
+    {#get SpvReflectBlockVariable->type_description #} bv >>=
       maybePeek inflateTypeDescription
 
+  word_offset <-
+    fmap (Just . BlockVariable.WordOffset) . inflateIntegral $
+      {#get SpvReflectBlockVariable->word_offset.offset #} bv
+
   pure BlockVariable.BlockVariable{..}
 
 {#pointer *SpvReflectTypeDescription as TypeDescriptionPtr #}
 
 inflateTypeDescription :: TypeDescriptionPtr -> IO TypeDescription
 inflateTypeDescription td = do
-  id_ <- fmap Just . inflateIntegral $
+  id_ <- fmap just . inflateIntegral $
     {#get SpvReflectTypeDescription->id #} td
 
-  op <- fmap Just . inflateEnum $
+  op <- fmap (just . SpirV.Op) . inflateIntegral $
     {#get SpvReflectTypeDescription->op #} td
 
-  type_name <- fmap Just . inflateText $
+  type_name <- inflateMaybe "" inflateText $
     {#get SpvReflectTypeDescription->type_name #} td
 
-  struct_member_name <- fmap Just . inflateText $
+  struct_member_name <- inflateMaybe "" inflateText $
     {#get SpvReflectTypeDescription->struct_member_name #} td
 
-  storage_class <- inflateEnum $
+  storage_class <- fmap SpirV.StorageClass . inflateIntegral $
     {#get SpvReflectTypeDescription->storage_class #} td
 
   type_flags <- inflateFlags32 $
@@ -312,8 +344,20 @@
       td
       {#offsetof SpvReflectTypeDescription->traits.array #}
 
-  let traits = Just TypeDescription.Traits{..}
+  let
+    traits' = Just TypeDescription.Traits{..}
+    traits = if traits' == Just TypeDescription.emptyTraits then Nothing else traits'
 
+  struct_type_description <-
+    {#get SpvReflectTypeDescription->struct_type_description #} td >>=
+      maybePeek inflateTypeDescription
+
+  copied <-
+    fmap (\n -> if n > 0 then Just n else Nothing) . inflateIntegral $
+      {#get SpvReflectTypeDescription->copied #} td
+
+  -- XXX: deprecated, but struct_type_description isn't always available for structs
+  -- BUG: trips up on recusive types
   members <-
     inflateVector
       ({#get SpvReflectTypeDescription->member_count #} td)
@@ -344,25 +388,28 @@
 
 inflateInterfaceVariable :: InterfaceVariablePtr -> IO InterfaceVariable
 inflateInterfaceVariable iv = do
-  spirv_id <- fmap Just . inflateIntegral $
+  spirv_id <- fmap just . inflateIntegral $
     {#get SpvReflectInterfaceVariable->spirv_id #} iv
 
-  name <- fmap Just . inflateText $
+  name <- inflateMaybe "" inflateText $
     {#get SpvReflectInterfaceVariable->name #} iv
 
   location <- inflateIntegral $
     {#get SpvReflectInterfaceVariable->location #} iv
 
-  storage_class <- inflateEnum $
+  component <- inflateMaybe 4294967295 inflateIntegral $
+    {#get SpvReflectInterfaceVariable->component #} iv
+
+  storage_class <- fmap SpirV.StorageClass . inflateIntegral $
     {#get SpvReflectInterfaceVariable->storage_class #} iv
 
-  semantic <- fmap Just . inflateText $
+  semantic <- inflateMaybe "" inflateText $
     {#get SpvReflectInterfaceVariable->semantic #} iv
 
   decoration_flags <- inflateFlags32 $
     {#get SpvReflectInterfaceVariable->decoration_flags #} iv
 
-  built_in <- inflateEnum $
+  built_in <- inflateMaybe (SpirV.BuiltIn maxBound) (fmap SpirV.BuiltIn . inflateIntegral) $
     {#get SpvReflectInterfaceVariable->built_in #} iv
 
   numeric <-
@@ -403,7 +450,7 @@
 inflateImageTraits src offset = do
   let it = castPtr src `plusPtr` offset
 
-  dim <- inflateEnum $
+  dim <- fmap SpirV.Dim . inflateIntegral $
     {#get SpvReflectImageTraits->dim #} it
 
   depth <- inflateIntegral $
@@ -418,7 +465,7 @@
   sampled <- inflateIntegral $
     {#get SpvReflectImageTraits->sampled #} it
 
-  image_format <- inflateEnum $
+  image_format <- fmap SpirV.ImageFormat . inflateEnum $
     {#get SpvReflectImageTraits->image_format #} it
 
   pure Traits.Image{..}
@@ -433,6 +480,7 @@
     {#get SpvReflectNumericTraits.scalar.width #} nt
   signedness <- inflateIntegral $
     {#get SpvReflectNumericTraits.scalar.signedness #} nt
+  let signed = signedness /= (0 :: C2HSImp.CUInt)
   let scalar = Traits.Scalar{..}
 
   component_count <- inflateIntegral $
@@ -464,27 +512,35 @@
     {#sizeof uint32_t #}
     (fmap fromIntegral . peek)
 
-  stride <- fmap Just . inflateIntegral $
+  stride <- inflateMaybe 0 inflateIntegral $
     {#get SpvReflectArrayTraits->stride #} at
 
   pure Traits.Array{..}
 
--- * Atomic types
+-- * Primitive types
 
+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
+    x <- inflate $ itemsPtr `plusPtr` (itemSize * pos)
+    pure $! x
+
 inflateIntegral :: (Integral a, Num b) => IO a -> IO b
 inflateIntegral getIntegral =
-  getIntegral >>=
-      pure . fromIntegral
+  getIntegral >>= \i ->
+    pure $! fromIntegral i
 
 inflateEnum :: (Integral a, Enum b) => IO a -> IO b
 inflateEnum getEnum =
-  getEnum >>=
-      pure . toEnum . fromIntegral
+  getEnum >>= \i ->
+    pure $! toEnum (fromIntegral i)
 
 inflateFlags32 :: forall a b . (Integral a, Coercible Word32 b) => IO a -> IO b
 inflateFlags32 gitBits =
-  gitBits >>=
-      pure . coerce @Word32 @b . fromIntegral
+  gitBits >>= \i ->
+    pure $! coerce @Word32 @b (fromIntegral i)
 
 inflateText :: IO CString -> IO Text
 inflateText getPtr =
@@ -495,3 +551,9 @@
       case ptr of
         GHC.Ptr addr ->
           pure $! Text.unpackCString# addr
+
+inflateMaybe :: Eq b => b -> (IO a -> IO b) -> IO a -> IO (Maybe b)
+inflateMaybe nothingBurger inflate = fmap (\x -> if x == nothingBurger then Nothing else Just x) . inflate
+
+just :: a -> Maybe a
+just x = x `seq` Just x
diff --git a/spirv-reflect-ffi.cabal b/spirv-reflect-ffi.cabal
--- a/spirv-reflect-ffi.cabal
+++ b/spirv-reflect-ffi.cabal
@@ -1,11 +1,11 @@
 cabal-version: 1.12
 
--- This file has been generated from package.yaml by hpack version 0.34.4.
+-- This file has been generated from package.yaml by hpack version 0.36.0.
 --
 -- see: https://github.com/sol/hpack
 
 name:           spirv-reflect-ffi
-version:        0.2
+version:        0.3
 synopsis:       C-library loader for spirv-reflect tool.
 category:       Graphics
 author:         IC Rainbow
@@ -60,9 +60,11 @@
   build-depends:
       base >=4.7 && <5
     , bytestring
-    , spirv-reflect-types >=0.2
+    , spirv-enum ==0.1.*
+    , spirv-reflect-types ==0.3.*
     , text
     , vector
+    , vector-algorithms
   default-language: Haskell2010
 
 test-suite spirv-reflect-yaml-test
@@ -94,6 +96,6 @@
     , spirv-reflect-ffi
     , tasty
     , tasty-hunit
+  default-language: Haskell2010
   if !flag(tests)
     buildable: False
-  default-language: Haskell2010
diff --git a/test/Main.hs b/test/Main.hs
--- a/test/Main.hs
+++ b/test/Main.hs
@@ -5,6 +5,7 @@
 import Control.Monad (guard)
 import System.Directory (doesDirectoryExist, listDirectory)
 import System.FilePath (splitExtension, takeFileName, (</>))
+import System.Timeout (timeout)
 import Test.Tasty (TestTree, defaultMain, testGroup)
 import Test.Tasty.HUnit (testCase)
 
@@ -47,7 +48,12 @@
 mkTest (name, file) =
   testCase name do
     -- putStrLn $ file <> " >>>>"
-    !_loaded <- FFI.load file
+    !_loaded <- timeout 500000 $ FFI.load file
+    case _loaded of
+      Just _ ->
+        pure ()
+      Nothing ->
+        fail "loader timed out"
     -- writeFile (file <> "_ffi.hs") (show _loaded)
     pure ()
     -- print _loaded
