mirror of
https://github.com/bkaradzic/bgfx.git
synced 2026-02-17 20:52:36 +01:00
Updated spirv-cross.
This commit is contained in:
27
3rdparty/spirv-cross/main.cpp
vendored
27
3rdparty/spirv-cross/main.cpp
vendored
@@ -38,6 +38,11 @@
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <io.h>
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SPIRV_CROSS_GIT_VERSION
|
||||
#include "gitversion.h"
|
||||
#endif
|
||||
@@ -220,8 +225,27 @@ struct CLIParser
|
||||
#pragma warning(disable : 4996)
|
||||
#endif
|
||||
|
||||
static vector<uint32_t> read_spirv_file_stdin()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
setmode(fileno(stdin), O_BINARY);
|
||||
#endif
|
||||
|
||||
vector<uint32_t> buffer;
|
||||
uint32_t tmp[256];
|
||||
size_t ret;
|
||||
|
||||
while ((ret = fread(tmp, sizeof(uint32_t), 256, stdin)))
|
||||
buffer.insert(buffer.end(), tmp, tmp + ret);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static vector<uint32_t> read_spirv_file(const char *path)
|
||||
{
|
||||
if (path[0] == '-' && path[1] == '\0')
|
||||
return read_spirv_file_stdin();
|
||||
|
||||
FILE *file = fopen(path, "rb");
|
||||
if (!file)
|
||||
{
|
||||
@@ -849,7 +873,7 @@ static void print_help()
|
||||
// clang-format off
|
||||
fprintf(stderr, "Usage: spirv-cross <...>\n"
|
||||
"\nBasic:\n"
|
||||
"\t[SPIR-V file]\n"
|
||||
"\t[SPIR-V file] (- is stdin)\n"
|
||||
"\t[--output <output path>]: If not provided, prints output to stdout.\n"
|
||||
"\t[--dump-resources]:\n\t\tPrints a basic reflection of the SPIR-V module along with other output.\n"
|
||||
"\t[--help]:\n\t\tPrints this help message.\n"
|
||||
@@ -1548,6 +1572,7 @@ static int main_inner(int argc, char *argv[])
|
||||
cbs.add("--emit-line-directives", [&args](CLIParser &) { args.emit_line_directives = true; });
|
||||
|
||||
cbs.default_handler = [&args](const char *value) { args.input = value; };
|
||||
cbs.add("-", [&args](CLIParser &) { args.input = "-"; });
|
||||
cbs.error_handler = [] { print_help(); };
|
||||
|
||||
CLIParser parser{ move(cbs), argc - 1, argv + 1 };
|
||||
|
||||
108
3rdparty/spirv-cross/spirv.h
vendored
108
3rdparty/spirv-cross/spirv.h
vendored
@@ -54,11 +54,11 @@
|
||||
typedef unsigned int SpvId;
|
||||
|
||||
#define SPV_VERSION 0x10500
|
||||
#define SPV_REVISION 3
|
||||
#define SPV_REVISION 4
|
||||
|
||||
static const unsigned int SpvMagicNumber = 0x07230203;
|
||||
static const unsigned int SpvVersion = 0x00010500;
|
||||
static const unsigned int SpvRevision = 3;
|
||||
static const unsigned int SpvRevision = 4;
|
||||
static const unsigned int SpvOpCodeMask = 0xffff;
|
||||
static const unsigned int SpvWordCountShift = 16;
|
||||
|
||||
@@ -172,6 +172,10 @@ typedef enum SpvExecutionMode_ {
|
||||
SpvExecutionModeSampleInterlockUnorderedEXT = 5369,
|
||||
SpvExecutionModeShadingRateInterlockOrderedEXT = 5370,
|
||||
SpvExecutionModeShadingRateInterlockUnorderedEXT = 5371,
|
||||
SpvExecutionModeMaxWorkgroupSizeINTEL = 5893,
|
||||
SpvExecutionModeMaxWorkDimINTEL = 5894,
|
||||
SpvExecutionModeNoGlobalOffsetINTEL = 5895,
|
||||
SpvExecutionModeNumSIMDWorkitemsINTEL = 5896,
|
||||
SpvExecutionModeMax = 0x7fffffff,
|
||||
} SpvExecutionMode;
|
||||
|
||||
@@ -203,6 +207,7 @@ typedef enum SpvStorageClass_ {
|
||||
SpvStorageClassShaderRecordBufferNV = 5343,
|
||||
SpvStorageClassPhysicalStorageBuffer = 5349,
|
||||
SpvStorageClassPhysicalStorageBufferEXT = 5349,
|
||||
SpvStorageClassCodeSectionINTEL = 5605,
|
||||
SpvStorageClassMax = 0x7fffffff,
|
||||
} SpvStorageClass;
|
||||
|
||||
@@ -273,6 +278,8 @@ typedef enum SpvImageFormat_ {
|
||||
SpvImageFormatRg8ui = 37,
|
||||
SpvImageFormatR16ui = 38,
|
||||
SpvImageFormatR8ui = 39,
|
||||
SpvImageFormatR64ui = 40,
|
||||
SpvImageFormatR64i = 41,
|
||||
SpvImageFormatMax = 0x7fffffff,
|
||||
} SpvImageFormat;
|
||||
|
||||
@@ -481,11 +488,24 @@ typedef enum SpvDecoration_ {
|
||||
SpvDecorationRestrictPointerEXT = 5355,
|
||||
SpvDecorationAliasedPointer = 5356,
|
||||
SpvDecorationAliasedPointerEXT = 5356,
|
||||
SpvDecorationReferencedIndirectlyINTEL = 5602,
|
||||
SpvDecorationCounterBuffer = 5634,
|
||||
SpvDecorationHlslCounterBufferGOOGLE = 5634,
|
||||
SpvDecorationHlslSemanticGOOGLE = 5635,
|
||||
SpvDecorationUserSemantic = 5635,
|
||||
SpvDecorationUserTypeGOOGLE = 5636,
|
||||
SpvDecorationRegisterINTEL = 5825,
|
||||
SpvDecorationMemoryINTEL = 5826,
|
||||
SpvDecorationNumbanksINTEL = 5827,
|
||||
SpvDecorationBankwidthINTEL = 5828,
|
||||
SpvDecorationMaxPrivateCopiesINTEL = 5829,
|
||||
SpvDecorationSinglepumpINTEL = 5830,
|
||||
SpvDecorationDoublepumpINTEL = 5831,
|
||||
SpvDecorationMaxReplicatesINTEL = 5832,
|
||||
SpvDecorationSimpleDualPortINTEL = 5833,
|
||||
SpvDecorationMergeINTEL = 5834,
|
||||
SpvDecorationBankBitsINTEL = 5835,
|
||||
SpvDecorationForcePow2DepthINTEL = 5836,
|
||||
SpvDecorationMax = 0x7fffffff,
|
||||
} SpvDecoration;
|
||||
|
||||
@@ -544,8 +564,10 @@ typedef enum SpvBuiltIn_ {
|
||||
SpvBuiltInBaseVertex = 4424,
|
||||
SpvBuiltInBaseInstance = 4425,
|
||||
SpvBuiltInDrawIndex = 4426,
|
||||
SpvBuiltInPrimitiveShadingRateKHR = 4432,
|
||||
SpvBuiltInDeviceIndex = 4438,
|
||||
SpvBuiltInViewIndex = 4440,
|
||||
SpvBuiltInShadingRateKHR = 4444,
|
||||
SpvBuiltInBaryCoordNoPerspAMD = 4992,
|
||||
SpvBuiltInBaryCoordNoPerspCentroidAMD = 4993,
|
||||
SpvBuiltInBaryCoordNoPerspSampleAMD = 4994,
|
||||
@@ -596,7 +618,6 @@ typedef enum SpvBuiltIn_ {
|
||||
SpvBuiltInObjectToWorldNV = 5330,
|
||||
SpvBuiltInWorldToObjectKHR = 5331,
|
||||
SpvBuiltInWorldToObjectNV = 5331,
|
||||
SpvBuiltInHitTKHR = 5332,
|
||||
SpvBuiltInHitTNV = 5332,
|
||||
SpvBuiltInHitKindKHR = 5333,
|
||||
SpvBuiltInHitKindNV = 5333,
|
||||
@@ -632,6 +653,13 @@ typedef enum SpvLoopControlShift_ {
|
||||
SpvLoopControlIterationMultipleShift = 6,
|
||||
SpvLoopControlPeelCountShift = 7,
|
||||
SpvLoopControlPartialCountShift = 8,
|
||||
SpvLoopControlInitiationIntervalINTELShift = 16,
|
||||
SpvLoopControlMaxConcurrencyINTELShift = 17,
|
||||
SpvLoopControlDependencyArrayINTELShift = 18,
|
||||
SpvLoopControlPipelineEnableINTELShift = 19,
|
||||
SpvLoopControlLoopCoalesceINTELShift = 20,
|
||||
SpvLoopControlMaxInterleavingINTELShift = 21,
|
||||
SpvLoopControlSpeculatedIterationsINTELShift = 22,
|
||||
SpvLoopControlMax = 0x7fffffff,
|
||||
} SpvLoopControlShift;
|
||||
|
||||
@@ -646,6 +674,13 @@ typedef enum SpvLoopControlMask_ {
|
||||
SpvLoopControlIterationMultipleMask = 0x00000040,
|
||||
SpvLoopControlPeelCountMask = 0x00000080,
|
||||
SpvLoopControlPartialCountMask = 0x00000100,
|
||||
SpvLoopControlInitiationIntervalINTELMask = 0x00010000,
|
||||
SpvLoopControlMaxConcurrencyINTELMask = 0x00020000,
|
||||
SpvLoopControlDependencyArrayINTELMask = 0x00040000,
|
||||
SpvLoopControlPipelineEnableINTELMask = 0x00080000,
|
||||
SpvLoopControlLoopCoalesceINTELMask = 0x00100000,
|
||||
SpvLoopControlMaxInterleavingINTELMask = 0x00200000,
|
||||
SpvLoopControlSpeculatedIterationsINTELMask = 0x00400000,
|
||||
} SpvLoopControlMask;
|
||||
|
||||
typedef enum SpvFunctionControlShift_ {
|
||||
@@ -842,6 +877,7 @@ typedef enum SpvCapability_ {
|
||||
SpvCapabilityGroupNonUniformQuad = 68,
|
||||
SpvCapabilityShaderLayer = 69,
|
||||
SpvCapabilityShaderViewportIndex = 70,
|
||||
SpvCapabilityFragmentShadingRateKHR = 4422,
|
||||
SpvCapabilitySubgroupBallotKHR = 4423,
|
||||
SpvCapabilityDrawParameters = 4427,
|
||||
SpvCapabilitySubgroupVoteKHR = 4431,
|
||||
@@ -866,12 +902,15 @@ typedef enum SpvCapability_ {
|
||||
SpvCapabilityRoundingModeRTE = 4467,
|
||||
SpvCapabilityRoundingModeRTZ = 4468,
|
||||
SpvCapabilityRayQueryProvisionalKHR = 4471,
|
||||
SpvCapabilityRayTraversalPrimitiveCullingProvisionalKHR = 4478,
|
||||
SpvCapabilityRayQueryKHR = 4472,
|
||||
SpvCapabilityRayTraversalPrimitiveCullingKHR = 4478,
|
||||
SpvCapabilityRayTracingKHR = 4479,
|
||||
SpvCapabilityFloat16ImageAMD = 5008,
|
||||
SpvCapabilityImageGatherBiasLodAMD = 5009,
|
||||
SpvCapabilityFragmentMaskAMD = 5010,
|
||||
SpvCapabilityStencilExportEXT = 5013,
|
||||
SpvCapabilityImageReadWriteLodAMD = 5015,
|
||||
SpvCapabilityInt64ImageEXT = 5016,
|
||||
SpvCapabilityShaderClockKHR = 5055,
|
||||
SpvCapabilitySampleMaskOverrideCoverageNV = 5249,
|
||||
SpvCapabilityGeometryShaderPassthroughNV = 5251,
|
||||
@@ -932,9 +971,20 @@ typedef enum SpvCapability_ {
|
||||
SpvCapabilitySubgroupImageBlockIOINTEL = 5570,
|
||||
SpvCapabilitySubgroupImageMediaBlockIOINTEL = 5579,
|
||||
SpvCapabilityIntegerFunctions2INTEL = 5584,
|
||||
SpvCapabilityFunctionPointersINTEL = 5603,
|
||||
SpvCapabilityIndirectReferencesINTEL = 5604,
|
||||
SpvCapabilitySubgroupAvcMotionEstimationINTEL = 5696,
|
||||
SpvCapabilitySubgroupAvcMotionEstimationIntraINTEL = 5697,
|
||||
SpvCapabilitySubgroupAvcMotionEstimationChromaINTEL = 5698,
|
||||
SpvCapabilityFPGAMemoryAttributesINTEL = 5824,
|
||||
SpvCapabilityUnstructuredLoopControlsINTEL = 5886,
|
||||
SpvCapabilityFPGALoopControlsINTEL = 5888,
|
||||
SpvCapabilityKernelAttributesINTEL = 5892,
|
||||
SpvCapabilityFPGAKernelAttributesINTEL = 5897,
|
||||
SpvCapabilityBlockingPipesINTEL = 5945,
|
||||
SpvCapabilityFPGARegINTEL = 5948,
|
||||
SpvCapabilityAtomicFloat32AddEXT = 6033,
|
||||
SpvCapabilityAtomicFloat64AddEXT = 6034,
|
||||
SpvCapabilityMax = 0x7fffffff,
|
||||
} SpvCapability;
|
||||
|
||||
@@ -985,6 +1035,22 @@ typedef enum SpvRayQueryCandidateIntersectionType_ {
|
||||
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 SpvOp_ {
|
||||
SpvOpNop = 0,
|
||||
SpvOpUndef = 1,
|
||||
@@ -1330,13 +1396,19 @@ typedef enum SpvOp_ {
|
||||
SpvOpPtrEqual = 401,
|
||||
SpvOpPtrNotEqual = 402,
|
||||
SpvOpPtrDiff = 403,
|
||||
SpvOpTerminateInvocation = 4416,
|
||||
SpvOpSubgroupBallotKHR = 4421,
|
||||
SpvOpSubgroupFirstInvocationKHR = 4422,
|
||||
SpvOpSubgroupAllKHR = 4428,
|
||||
SpvOpSubgroupAnyKHR = 4429,
|
||||
SpvOpSubgroupAllEqualKHR = 4430,
|
||||
SpvOpSubgroupReadInvocationKHR = 4432,
|
||||
SpvOpTypeRayQueryProvisionalKHR = 4472,
|
||||
SpvOpTraceRayKHR = 4445,
|
||||
SpvOpExecuteCallableKHR = 4446,
|
||||
SpvOpConvertUToAccelerationStructureKHR = 4447,
|
||||
SpvOpIgnoreIntersectionKHR = 4448,
|
||||
SpvOpTerminateRayKHR = 4449,
|
||||
SpvOpTypeRayQueryKHR = 4472,
|
||||
SpvOpRayQueryInitializeKHR = 4473,
|
||||
SpvOpRayQueryTerminateKHR = 4474,
|
||||
SpvOpRayQueryGenerateIntersectionKHR = 4475,
|
||||
@@ -1359,15 +1431,11 @@ typedef enum SpvOp_ {
|
||||
SpvOpWritePackedPrimitiveIndices4x8NV = 5299,
|
||||
SpvOpReportIntersectionKHR = 5334,
|
||||
SpvOpReportIntersectionNV = 5334,
|
||||
SpvOpIgnoreIntersectionKHR = 5335,
|
||||
SpvOpIgnoreIntersectionNV = 5335,
|
||||
SpvOpTerminateRayKHR = 5336,
|
||||
SpvOpTerminateRayNV = 5336,
|
||||
SpvOpTraceNV = 5337,
|
||||
SpvOpTraceRayKHR = 5337,
|
||||
SpvOpTypeAccelerationStructureKHR = 5341,
|
||||
SpvOpTypeAccelerationStructureNV = 5341,
|
||||
SpvOpExecuteCallableKHR = 5344,
|
||||
SpvOpExecuteCallableNV = 5344,
|
||||
SpvOpTypeCooperativeMatrixNV = 5358,
|
||||
SpvOpCooperativeMatrixLoadNV = 5359,
|
||||
@@ -1402,6 +1470,8 @@ typedef enum SpvOp_ {
|
||||
SpvOpUSubSatINTEL = 5596,
|
||||
SpvOpIMul32x16INTEL = 5597,
|
||||
SpvOpUMul32x16INTEL = 5598,
|
||||
SpvOpFunctionPointerINTEL = 5600,
|
||||
SpvOpFunctionPointerCallINTEL = 5601,
|
||||
SpvOpDecorateString = 5632,
|
||||
SpvOpDecorateStringGOOGLE = 5632,
|
||||
SpvOpMemberDecorateString = 5633,
|
||||
@@ -1524,6 +1594,10 @@ typedef enum SpvOp_ {
|
||||
SpvOpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL = 5814,
|
||||
SpvOpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL = 5815,
|
||||
SpvOpSubgroupAvcSicGetInterRawSadsINTEL = 5816,
|
||||
SpvOpLoopControlINTEL = 5887,
|
||||
SpvOpReadPipeBlockingINTEL = 5946,
|
||||
SpvOpWritePipeBlockingINTEL = 5947,
|
||||
SpvOpFPGARegINTEL = 5949,
|
||||
SpvOpRayQueryGetRayTMinKHR = 6016,
|
||||
SpvOpRayQueryGetRayFlagsKHR = 6017,
|
||||
SpvOpRayQueryGetIntersectionTKHR = 6018,
|
||||
@@ -1541,6 +1615,7 @@ typedef enum SpvOp_ {
|
||||
SpvOpRayQueryGetWorldRayOriginKHR = 6030,
|
||||
SpvOpRayQueryGetIntersectionObjectToWorldKHR = 6031,
|
||||
SpvOpRayQueryGetIntersectionWorldToObjectKHR = 6032,
|
||||
SpvOpAtomicFAddEXT = 6035,
|
||||
SpvOpMax = 0x7fffffff,
|
||||
} SpvOp;
|
||||
|
||||
@@ -1893,13 +1968,19 @@ inline void SpvHasResultAndType(SpvOp opcode, bool *hasResult, bool *hasResultTy
|
||||
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 SpvOpSubgroupReadInvocationKHR: *hasResult = true; *hasResultType = true; break;
|
||||
case SpvOpTypeRayQueryProvisionalKHR: *hasResult = true; *hasResultType = false; 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 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;
|
||||
@@ -1959,6 +2040,8 @@ inline void SpvHasResultAndType(SpvOp opcode, bool *hasResult, bool *hasResultTy
|
||||
case SpvOpUSubSatINTEL: *hasResult = true; *hasResultType = true; break;
|
||||
case SpvOpIMul32x16INTEL: *hasResult = true; *hasResultType = true; break;
|
||||
case SpvOpUMul32x16INTEL: *hasResult = true; *hasResultType = true; break;
|
||||
case SpvOpFunctionPointerINTEL: *hasResult = true; *hasResultType = true; break;
|
||||
case SpvOpFunctionPointerCallINTEL: *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;
|
||||
@@ -2079,6 +2162,10 @@ inline void SpvHasResultAndType(SpvOp opcode, bool *hasResult, bool *hasResultTy
|
||||
case SpvOpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL: *hasResult = true; *hasResultType = true; break;
|
||||
case SpvOpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL: *hasResult = true; *hasResultType = true; break;
|
||||
case SpvOpSubgroupAvcSicGetInterRawSadsINTEL: *hasResult = true; *hasResultType = true; break;
|
||||
case SpvOpLoopControlINTEL: *hasResult = false; *hasResultType = false; 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;
|
||||
@@ -2096,6 +2183,7 @@ inline void SpvHasResultAndType(SpvOp opcode, bool *hasResult, bool *hasResultTy
|
||||
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;
|
||||
}
|
||||
}
|
||||
#endif /* SPV_ENABLE_UTILITY_CODE */
|
||||
|
||||
109
3rdparty/spirv-cross/spirv.hpp
vendored
109
3rdparty/spirv-cross/spirv.hpp
vendored
@@ -50,11 +50,11 @@ namespace spv {
|
||||
typedef unsigned int Id;
|
||||
|
||||
#define SPV_VERSION 0x10500
|
||||
#define SPV_REVISION 3
|
||||
#define SPV_REVISION 4
|
||||
|
||||
static const unsigned int MagicNumber = 0x07230203;
|
||||
static const unsigned int Version = 0x00010500;
|
||||
static const unsigned int Revision = 3;
|
||||
static const unsigned int Revision = 4;
|
||||
static const unsigned int OpCodeMask = 0xffff;
|
||||
static const unsigned int WordCountShift = 16;
|
||||
|
||||
@@ -168,6 +168,10 @@ enum ExecutionMode {
|
||||
ExecutionModeSampleInterlockUnorderedEXT = 5369,
|
||||
ExecutionModeShadingRateInterlockOrderedEXT = 5370,
|
||||
ExecutionModeShadingRateInterlockUnorderedEXT = 5371,
|
||||
ExecutionModeMaxWorkgroupSizeINTEL = 5893,
|
||||
ExecutionModeMaxWorkDimINTEL = 5894,
|
||||
ExecutionModeNoGlobalOffsetINTEL = 5895,
|
||||
ExecutionModeNumSIMDWorkitemsINTEL = 5896,
|
||||
ExecutionModeMax = 0x7fffffff,
|
||||
};
|
||||
|
||||
@@ -199,6 +203,7 @@ enum StorageClass {
|
||||
StorageClassShaderRecordBufferNV = 5343,
|
||||
StorageClassPhysicalStorageBuffer = 5349,
|
||||
StorageClassPhysicalStorageBufferEXT = 5349,
|
||||
StorageClassCodeSectionINTEL = 5605,
|
||||
StorageClassMax = 0x7fffffff,
|
||||
};
|
||||
|
||||
@@ -269,6 +274,8 @@ enum ImageFormat {
|
||||
ImageFormatRg8ui = 37,
|
||||
ImageFormatR16ui = 38,
|
||||
ImageFormatR8ui = 39,
|
||||
ImageFormatR64ui = 40,
|
||||
ImageFormatR64i = 41,
|
||||
ImageFormatMax = 0x7fffffff,
|
||||
};
|
||||
|
||||
@@ -477,11 +484,24 @@ enum Decoration {
|
||||
DecorationRestrictPointerEXT = 5355,
|
||||
DecorationAliasedPointer = 5356,
|
||||
DecorationAliasedPointerEXT = 5356,
|
||||
DecorationReferencedIndirectlyINTEL = 5602,
|
||||
DecorationCounterBuffer = 5634,
|
||||
DecorationHlslCounterBufferGOOGLE = 5634,
|
||||
DecorationHlslSemanticGOOGLE = 5635,
|
||||
DecorationUserSemantic = 5635,
|
||||
DecorationUserTypeGOOGLE = 5636,
|
||||
DecorationRegisterINTEL = 5825,
|
||||
DecorationMemoryINTEL = 5826,
|
||||
DecorationNumbanksINTEL = 5827,
|
||||
DecorationBankwidthINTEL = 5828,
|
||||
DecorationMaxPrivateCopiesINTEL = 5829,
|
||||
DecorationSinglepumpINTEL = 5830,
|
||||
DecorationDoublepumpINTEL = 5831,
|
||||
DecorationMaxReplicatesINTEL = 5832,
|
||||
DecorationSimpleDualPortINTEL = 5833,
|
||||
DecorationMergeINTEL = 5834,
|
||||
DecorationBankBitsINTEL = 5835,
|
||||
DecorationForcePow2DepthINTEL = 5836,
|
||||
DecorationMax = 0x7fffffff,
|
||||
};
|
||||
|
||||
@@ -540,8 +560,10 @@ enum BuiltIn {
|
||||
BuiltInBaseVertex = 4424,
|
||||
BuiltInBaseInstance = 4425,
|
||||
BuiltInDrawIndex = 4426,
|
||||
BuiltInPrimitiveShadingRateKHR = 4432,
|
||||
BuiltInDeviceIndex = 4438,
|
||||
BuiltInViewIndex = 4440,
|
||||
BuiltInShadingRateKHR = 4444,
|
||||
BuiltInBaryCoordNoPerspAMD = 4992,
|
||||
BuiltInBaryCoordNoPerspCentroidAMD = 4993,
|
||||
BuiltInBaryCoordNoPerspSampleAMD = 4994,
|
||||
@@ -592,7 +614,6 @@ enum BuiltIn {
|
||||
BuiltInObjectToWorldNV = 5330,
|
||||
BuiltInWorldToObjectKHR = 5331,
|
||||
BuiltInWorldToObjectNV = 5331,
|
||||
BuiltInHitTKHR = 5332,
|
||||
BuiltInHitTNV = 5332,
|
||||
BuiltInHitKindKHR = 5333,
|
||||
BuiltInHitKindNV = 5333,
|
||||
@@ -628,6 +649,13 @@ enum LoopControlShift {
|
||||
LoopControlIterationMultipleShift = 6,
|
||||
LoopControlPeelCountShift = 7,
|
||||
LoopControlPartialCountShift = 8,
|
||||
LoopControlInitiationIntervalINTELShift = 16,
|
||||
LoopControlMaxConcurrencyINTELShift = 17,
|
||||
LoopControlDependencyArrayINTELShift = 18,
|
||||
LoopControlPipelineEnableINTELShift = 19,
|
||||
LoopControlLoopCoalesceINTELShift = 20,
|
||||
LoopControlMaxInterleavingINTELShift = 21,
|
||||
LoopControlSpeculatedIterationsINTELShift = 22,
|
||||
LoopControlMax = 0x7fffffff,
|
||||
};
|
||||
|
||||
@@ -642,6 +670,13 @@ enum LoopControlMask {
|
||||
LoopControlIterationMultipleMask = 0x00000040,
|
||||
LoopControlPeelCountMask = 0x00000080,
|
||||
LoopControlPartialCountMask = 0x00000100,
|
||||
LoopControlInitiationIntervalINTELMask = 0x00010000,
|
||||
LoopControlMaxConcurrencyINTELMask = 0x00020000,
|
||||
LoopControlDependencyArrayINTELMask = 0x00040000,
|
||||
LoopControlPipelineEnableINTELMask = 0x00080000,
|
||||
LoopControlLoopCoalesceINTELMask = 0x00100000,
|
||||
LoopControlMaxInterleavingINTELMask = 0x00200000,
|
||||
LoopControlSpeculatedIterationsINTELMask = 0x00400000,
|
||||
};
|
||||
|
||||
enum FunctionControlShift {
|
||||
@@ -838,6 +873,7 @@ enum Capability {
|
||||
CapabilityGroupNonUniformQuad = 68,
|
||||
CapabilityShaderLayer = 69,
|
||||
CapabilityShaderViewportIndex = 70,
|
||||
CapabilityFragmentShadingRateKHR = 4422,
|
||||
CapabilitySubgroupBallotKHR = 4423,
|
||||
CapabilityDrawParameters = 4427,
|
||||
CapabilitySubgroupVoteKHR = 4431,
|
||||
@@ -862,12 +898,15 @@ enum Capability {
|
||||
CapabilityRoundingModeRTE = 4467,
|
||||
CapabilityRoundingModeRTZ = 4468,
|
||||
CapabilityRayQueryProvisionalKHR = 4471,
|
||||
CapabilityRayTraversalPrimitiveCullingProvisionalKHR = 4478,
|
||||
CapabilityRayQueryKHR = 4472,
|
||||
CapabilityRayTraversalPrimitiveCullingKHR = 4478,
|
||||
CapabilityRayTracingKHR = 4479,
|
||||
CapabilityFloat16ImageAMD = 5008,
|
||||
CapabilityImageGatherBiasLodAMD = 5009,
|
||||
CapabilityFragmentMaskAMD = 5010,
|
||||
CapabilityStencilExportEXT = 5013,
|
||||
CapabilityImageReadWriteLodAMD = 5015,
|
||||
CapabilityInt64ImageEXT = 5016,
|
||||
CapabilityShaderClockKHR = 5055,
|
||||
CapabilitySampleMaskOverrideCoverageNV = 5249,
|
||||
CapabilityGeometryShaderPassthroughNV = 5251,
|
||||
@@ -928,9 +967,20 @@ enum Capability {
|
||||
CapabilitySubgroupImageBlockIOINTEL = 5570,
|
||||
CapabilitySubgroupImageMediaBlockIOINTEL = 5579,
|
||||
CapabilityIntegerFunctions2INTEL = 5584,
|
||||
CapabilityFunctionPointersINTEL = 5603,
|
||||
CapabilityIndirectReferencesINTEL = 5604,
|
||||
CapabilitySubgroupAvcMotionEstimationINTEL = 5696,
|
||||
CapabilitySubgroupAvcMotionEstimationIntraINTEL = 5697,
|
||||
CapabilitySubgroupAvcMotionEstimationChromaINTEL = 5698,
|
||||
CapabilityFPGAMemoryAttributesINTEL = 5824,
|
||||
CapabilityUnstructuredLoopControlsINTEL = 5886,
|
||||
CapabilityFPGALoopControlsINTEL = 5888,
|
||||
CapabilityKernelAttributesINTEL = 5892,
|
||||
CapabilityFPGAKernelAttributesINTEL = 5897,
|
||||
CapabilityBlockingPipesINTEL = 5945,
|
||||
CapabilityFPGARegINTEL = 5948,
|
||||
CapabilityAtomicFloat32AddEXT = 6033,
|
||||
CapabilityAtomicFloat64AddEXT = 6034,
|
||||
CapabilityMax = 0x7fffffff,
|
||||
};
|
||||
|
||||
@@ -981,6 +1031,22 @@ enum RayQueryCandidateIntersectionType {
|
||||
RayQueryCandidateIntersectionTypeMax = 0x7fffffff,
|
||||
};
|
||||
|
||||
enum FragmentShadingRateShift {
|
||||
FragmentShadingRateVertical2PixelsShift = 0,
|
||||
FragmentShadingRateVertical4PixelsShift = 1,
|
||||
FragmentShadingRateHorizontal2PixelsShift = 2,
|
||||
FragmentShadingRateHorizontal4PixelsShift = 3,
|
||||
FragmentShadingRateMax = 0x7fffffff,
|
||||
};
|
||||
|
||||
enum FragmentShadingRateMask {
|
||||
FragmentShadingRateMaskNone = 0,
|
||||
FragmentShadingRateVertical2PixelsMask = 0x00000001,
|
||||
FragmentShadingRateVertical4PixelsMask = 0x00000002,
|
||||
FragmentShadingRateHorizontal2PixelsMask = 0x00000004,
|
||||
FragmentShadingRateHorizontal4PixelsMask = 0x00000008,
|
||||
};
|
||||
|
||||
enum Op {
|
||||
OpNop = 0,
|
||||
OpUndef = 1,
|
||||
@@ -1326,13 +1392,19 @@ enum Op {
|
||||
OpPtrEqual = 401,
|
||||
OpPtrNotEqual = 402,
|
||||
OpPtrDiff = 403,
|
||||
OpTerminateInvocation = 4416,
|
||||
OpSubgroupBallotKHR = 4421,
|
||||
OpSubgroupFirstInvocationKHR = 4422,
|
||||
OpSubgroupAllKHR = 4428,
|
||||
OpSubgroupAnyKHR = 4429,
|
||||
OpSubgroupAllEqualKHR = 4430,
|
||||
OpSubgroupReadInvocationKHR = 4432,
|
||||
OpTypeRayQueryProvisionalKHR = 4472,
|
||||
OpTraceRayKHR = 4445,
|
||||
OpExecuteCallableKHR = 4446,
|
||||
OpConvertUToAccelerationStructureKHR = 4447,
|
||||
OpIgnoreIntersectionKHR = 4448,
|
||||
OpTerminateRayKHR = 4449,
|
||||
OpTypeRayQueryKHR = 4472,
|
||||
OpRayQueryInitializeKHR = 4473,
|
||||
OpRayQueryTerminateKHR = 4474,
|
||||
OpRayQueryGenerateIntersectionKHR = 4475,
|
||||
@@ -1355,15 +1427,11 @@ enum Op {
|
||||
OpWritePackedPrimitiveIndices4x8NV = 5299,
|
||||
OpReportIntersectionKHR = 5334,
|
||||
OpReportIntersectionNV = 5334,
|
||||
OpIgnoreIntersectionKHR = 5335,
|
||||
OpIgnoreIntersectionNV = 5335,
|
||||
OpTerminateRayKHR = 5336,
|
||||
OpTerminateRayNV = 5336,
|
||||
OpTraceNV = 5337,
|
||||
OpTraceRayKHR = 5337,
|
||||
OpTypeAccelerationStructureKHR = 5341,
|
||||
OpTypeAccelerationStructureNV = 5341,
|
||||
OpExecuteCallableKHR = 5344,
|
||||
OpExecuteCallableNV = 5344,
|
||||
OpTypeCooperativeMatrixNV = 5358,
|
||||
OpCooperativeMatrixLoadNV = 5359,
|
||||
@@ -1398,6 +1466,8 @@ enum Op {
|
||||
OpUSubSatINTEL = 5596,
|
||||
OpIMul32x16INTEL = 5597,
|
||||
OpUMul32x16INTEL = 5598,
|
||||
OpFunctionPointerINTEL = 5600,
|
||||
OpFunctionPointerCallINTEL = 5601,
|
||||
OpDecorateString = 5632,
|
||||
OpDecorateStringGOOGLE = 5632,
|
||||
OpMemberDecorateString = 5633,
|
||||
@@ -1520,6 +1590,10 @@ enum Op {
|
||||
OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL = 5814,
|
||||
OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL = 5815,
|
||||
OpSubgroupAvcSicGetInterRawSadsINTEL = 5816,
|
||||
OpLoopControlINTEL = 5887,
|
||||
OpReadPipeBlockingINTEL = 5946,
|
||||
OpWritePipeBlockingINTEL = 5947,
|
||||
OpFPGARegINTEL = 5949,
|
||||
OpRayQueryGetRayTMinKHR = 6016,
|
||||
OpRayQueryGetRayFlagsKHR = 6017,
|
||||
OpRayQueryGetIntersectionTKHR = 6018,
|
||||
@@ -1537,6 +1611,7 @@ enum Op {
|
||||
OpRayQueryGetWorldRayOriginKHR = 6030,
|
||||
OpRayQueryGetIntersectionObjectToWorldKHR = 6031,
|
||||
OpRayQueryGetIntersectionWorldToObjectKHR = 6032,
|
||||
OpAtomicFAddEXT = 6035,
|
||||
OpMax = 0x7fffffff,
|
||||
};
|
||||
|
||||
@@ -1889,13 +1964,19 @@ inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) {
|
||||
case OpPtrEqual: *hasResult = true; *hasResultType = true; break;
|
||||
case OpPtrNotEqual: *hasResult = true; *hasResultType = true; break;
|
||||
case OpPtrDiff: *hasResult = true; *hasResultType = true; break;
|
||||
case OpTerminateInvocation: *hasResult = false; *hasResultType = false; break;
|
||||
case OpSubgroupBallotKHR: *hasResult = true; *hasResultType = true; break;
|
||||
case OpSubgroupFirstInvocationKHR: *hasResult = true; *hasResultType = true; break;
|
||||
case OpSubgroupAllKHR: *hasResult = true; *hasResultType = true; break;
|
||||
case OpSubgroupAnyKHR: *hasResult = true; *hasResultType = true; break;
|
||||
case OpSubgroupAllEqualKHR: *hasResult = true; *hasResultType = true; break;
|
||||
case OpSubgroupReadInvocationKHR: *hasResult = true; *hasResultType = true; break;
|
||||
case OpTypeRayQueryProvisionalKHR: *hasResult = true; *hasResultType = false; break;
|
||||
case OpTraceRayKHR: *hasResult = false; *hasResultType = false; break;
|
||||
case OpExecuteCallableKHR: *hasResult = false; *hasResultType = false; break;
|
||||
case OpConvertUToAccelerationStructureKHR: *hasResult = true; *hasResultType = true; break;
|
||||
case OpIgnoreIntersectionKHR: *hasResult = false; *hasResultType = false; break;
|
||||
case OpTerminateRayKHR: *hasResult = false; *hasResultType = false; break;
|
||||
case OpTypeRayQueryKHR: *hasResult = true; *hasResultType = false; break;
|
||||
case OpRayQueryInitializeKHR: *hasResult = false; *hasResultType = false; break;
|
||||
case OpRayQueryTerminateKHR: *hasResult = false; *hasResultType = false; break;
|
||||
case OpRayQueryGenerateIntersectionKHR: *hasResult = false; *hasResultType = false; break;
|
||||
@@ -1955,6 +2036,8 @@ inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) {
|
||||
case OpUSubSatINTEL: *hasResult = true; *hasResultType = true; break;
|
||||
case OpIMul32x16INTEL: *hasResult = true; *hasResultType = true; break;
|
||||
case OpUMul32x16INTEL: *hasResult = true; *hasResultType = true; break;
|
||||
case OpFunctionPointerINTEL: *hasResult = true; *hasResultType = true; break;
|
||||
case OpFunctionPointerCallINTEL: *hasResult = true; *hasResultType = true; break;
|
||||
case OpDecorateString: *hasResult = false; *hasResultType = false; break;
|
||||
case OpMemberDecorateString: *hasResult = false; *hasResultType = false; break;
|
||||
case OpVmeImageINTEL: *hasResult = true; *hasResultType = true; break;
|
||||
@@ -2075,6 +2158,10 @@ inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) {
|
||||
case OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL: *hasResult = true; *hasResultType = true; break;
|
||||
case OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL: *hasResult = true; *hasResultType = true; break;
|
||||
case OpSubgroupAvcSicGetInterRawSadsINTEL: *hasResult = true; *hasResultType = true; break;
|
||||
case OpLoopControlINTEL: *hasResult = false; *hasResultType = false; break;
|
||||
case OpReadPipeBlockingINTEL: *hasResult = true; *hasResultType = true; break;
|
||||
case OpWritePipeBlockingINTEL: *hasResult = true; *hasResultType = true; break;
|
||||
case OpFPGARegINTEL: *hasResult = true; *hasResultType = true; break;
|
||||
case OpRayQueryGetRayTMinKHR: *hasResult = true; *hasResultType = true; break;
|
||||
case OpRayQueryGetRayFlagsKHR: *hasResult = true; *hasResultType = true; break;
|
||||
case OpRayQueryGetIntersectionTKHR: *hasResult = true; *hasResultType = true; break;
|
||||
@@ -2092,6 +2179,7 @@ inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) {
|
||||
case OpRayQueryGetWorldRayOriginKHR: *hasResult = true; *hasResultType = true; break;
|
||||
case OpRayQueryGetIntersectionObjectToWorldKHR: *hasResult = true; *hasResultType = true; break;
|
||||
case OpRayQueryGetIntersectionWorldToObjectKHR: *hasResult = true; *hasResultType = true; break;
|
||||
case OpAtomicFAddEXT: *hasResult = true; *hasResultType = true; break;
|
||||
}
|
||||
}
|
||||
#endif /* SPV_ENABLE_UTILITY_CODE */
|
||||
@@ -2107,6 +2195,7 @@ inline MemorySemanticsMask operator|(MemorySemanticsMask a, MemorySemanticsMask
|
||||
inline MemoryAccessMask operator|(MemoryAccessMask a, MemoryAccessMask b) { return MemoryAccessMask(unsigned(a) | unsigned(b)); }
|
||||
inline KernelProfilingInfoMask operator|(KernelProfilingInfoMask a, KernelProfilingInfoMask b) { return KernelProfilingInfoMask(unsigned(a) | unsigned(b)); }
|
||||
inline RayFlagsMask operator|(RayFlagsMask a, RayFlagsMask b) { return RayFlagsMask(unsigned(a) | unsigned(b)); }
|
||||
inline FragmentShadingRateMask operator|(FragmentShadingRateMask a, FragmentShadingRateMask b) { return FragmentShadingRateMask(unsigned(a) | unsigned(b)); }
|
||||
|
||||
} // end namespace spv
|
||||
|
||||
|
||||
4
3rdparty/spirv-cross/spirv_common.hpp
vendored
4
3rdparty/spirv-cross/spirv_common.hpp
vendored
@@ -729,7 +729,9 @@ struct SPIRBlock : IVariant
|
||||
|
||||
Return, // Block ends with return.
|
||||
Unreachable, // Noop
|
||||
Kill // Discard
|
||||
Kill, // Discard
|
||||
IgnoreIntersection, // Ray Tracing
|
||||
TerminateRay // Ray Tracing
|
||||
};
|
||||
|
||||
enum Merge
|
||||
|
||||
109
3rdparty/spirv-cross/spirv_cross.cpp
vendored
109
3rdparty/spirv-cross/spirv_cross.cpp
vendored
@@ -96,7 +96,9 @@ bool Compiler::variable_storage_is_aliased(const SPIRVariable &v)
|
||||
bool Compiler::block_is_pure(const SPIRBlock &block)
|
||||
{
|
||||
// This is a global side effect of the function.
|
||||
if (block.terminator == SPIRBlock::Kill)
|
||||
if (block.terminator == SPIRBlock::Kill ||
|
||||
block.terminator == SPIRBlock::TerminateRay ||
|
||||
block.terminator == SPIRBlock::IgnoreIntersection)
|
||||
return false;
|
||||
|
||||
for (auto &i : block.ops)
|
||||
@@ -158,11 +160,13 @@ bool Compiler::block_is_pure(const SPIRBlock &block)
|
||||
return false;
|
||||
|
||||
// Ray tracing builtins are impure.
|
||||
case OpReportIntersectionNV:
|
||||
case OpReportIntersectionKHR:
|
||||
case OpIgnoreIntersectionNV:
|
||||
case OpTerminateRayNV:
|
||||
case OpTraceNV:
|
||||
case OpTraceRayKHR:
|
||||
case OpExecuteCallableNV:
|
||||
case OpExecuteCallableKHR:
|
||||
return false;
|
||||
|
||||
// OpExtInst is potentially impure depending on extension, but GLSL builtins are at least pure.
|
||||
@@ -805,9 +809,17 @@ unordered_set<VariableID> Compiler::get_active_interface_variables() const
|
||||
InterfaceVariableAccessHandler handler(*this, variables);
|
||||
traverse_all_reachable_opcodes(get<SPIRFunction>(ir.default_entry_point), handler);
|
||||
|
||||
// Make sure we preserve output variables which are only initialized, but never accessed by any code.
|
||||
ir.for_each_typed_id<SPIRVariable>([&](uint32_t, const SPIRVariable &var) {
|
||||
if (var.storage == StorageClassOutput && var.initializer != ID(0))
|
||||
if (var.storage != StorageClassOutput)
|
||||
return;
|
||||
if (!interface_variable_exists_in_entry_point(var.self))
|
||||
return;
|
||||
|
||||
// An output variable which is just declared (but uninitialized) might be read by subsequent stages
|
||||
// so we should force-enable these outputs,
|
||||
// since compilation will fail if a subsequent stage attempts to read from the variable in question.
|
||||
// Also, make sure we preserve output variables which are only initialized, but never accessed by any code.
|
||||
if (var.initializer != ID(0) || get_execution_model() != ExecutionModelFragment)
|
||||
variables.insert(var.self);
|
||||
});
|
||||
|
||||
@@ -2279,16 +2291,22 @@ SPIREntryPoint &Compiler::get_entry_point()
|
||||
bool Compiler::interface_variable_exists_in_entry_point(uint32_t id) const
|
||||
{
|
||||
auto &var = get<SPIRVariable>(id);
|
||||
if (var.storage != StorageClassInput && var.storage != StorageClassOutput &&
|
||||
var.storage != StorageClassUniformConstant)
|
||||
SPIRV_CROSS_THROW("Only Input, Output variables and Uniform constants are part of a shader linking interface.");
|
||||
|
||||
// This is to avoid potential problems with very old glslang versions which did
|
||||
// not emit input/output interfaces properly.
|
||||
// We can assume they only had a single entry point, and single entry point
|
||||
// shaders could easily be assumed to use every interface variable anyways.
|
||||
if (ir.entry_points.size() <= 1)
|
||||
return true;
|
||||
if (ir.get_spirv_version() < 0x10400)
|
||||
{
|
||||
if (var.storage != StorageClassInput && var.storage != StorageClassOutput &&
|
||||
var.storage != StorageClassUniformConstant)
|
||||
SPIRV_CROSS_THROW("Only Input, Output variables and Uniform constants are part of a shader linking interface.");
|
||||
|
||||
// This is to avoid potential problems with very old glslang versions which did
|
||||
// not emit input/output interfaces properly.
|
||||
// We can assume they only had a single entry point, and single entry point
|
||||
// shaders could easily be assumed to use every interface variable anyways.
|
||||
if (ir.entry_points.size() <= 1)
|
||||
return true;
|
||||
}
|
||||
|
||||
// In SPIR-V 1.4 and later, all global resource variables must be present.
|
||||
|
||||
auto &execution = get_entry_point();
|
||||
return find(begin(execution.interface_variables), end(execution.interface_variables), VariableID(id)) !=
|
||||
@@ -3839,23 +3857,55 @@ void Compiler::ActiveBuiltinHandler::handle_builtin(const SPIRType &type, BuiltI
|
||||
}
|
||||
}
|
||||
|
||||
bool Compiler::ActiveBuiltinHandler::handle(spv::Op opcode, const uint32_t *args, uint32_t length)
|
||||
void Compiler::ActiveBuiltinHandler::add_if_builtin(uint32_t id, bool allow_blocks)
|
||||
{
|
||||
const auto add_if_builtin = [&](uint32_t id) {
|
||||
// Only handles variables here.
|
||||
// Builtins which are part of a block are handled in AccessChain.
|
||||
auto *var = compiler.maybe_get<SPIRVariable>(id);
|
||||
auto &decorations = compiler.ir.meta[id].decoration;
|
||||
if (var && decorations.builtin)
|
||||
// Only handle plain variables here.
|
||||
// Builtins which are part of a block are handled in AccessChain.
|
||||
// If allow_blocks is used however, this is to handle initializers of blocks,
|
||||
// which implies that all members are written to.
|
||||
|
||||
auto *var = compiler.maybe_get<SPIRVariable>(id);
|
||||
auto *m = compiler.ir.find_meta(id);
|
||||
if (var && m)
|
||||
{
|
||||
auto &type = compiler.get<SPIRType>(var->basetype);
|
||||
auto &decorations = m->decoration;
|
||||
auto &flags = type.storage == StorageClassInput ?
|
||||
compiler.active_input_builtins : compiler.active_output_builtins;
|
||||
if (decorations.builtin)
|
||||
{
|
||||
auto &type = compiler.get<SPIRType>(var->basetype);
|
||||
auto &flags =
|
||||
type.storage == StorageClassInput ? compiler.active_input_builtins : compiler.active_output_builtins;
|
||||
flags.set(decorations.builtin_type);
|
||||
handle_builtin(type, decorations.builtin_type, decorations.decoration_flags);
|
||||
}
|
||||
};
|
||||
else if (allow_blocks && compiler.has_decoration(type.self, DecorationBlock))
|
||||
{
|
||||
uint32_t member_count = uint32_t(type.member_types.size());
|
||||
for (uint32_t i = 0; i < member_count; i++)
|
||||
{
|
||||
if (compiler.has_member_decoration(type.self, i, DecorationBuiltIn))
|
||||
{
|
||||
auto &member_type = compiler.get<SPIRType>(type.member_types[i]);
|
||||
BuiltIn builtin = BuiltIn(compiler.get_member_decoration(type.self, i, DecorationBuiltIn));
|
||||
flags.set(builtin);
|
||||
handle_builtin(member_type, builtin, compiler.get_member_decoration_bitset(type.self, i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Compiler::ActiveBuiltinHandler::add_if_builtin(uint32_t id)
|
||||
{
|
||||
add_if_builtin(id, false);
|
||||
}
|
||||
|
||||
void Compiler::ActiveBuiltinHandler::add_if_builtin_or_block(uint32_t id)
|
||||
{
|
||||
add_if_builtin(id, true);
|
||||
}
|
||||
|
||||
bool Compiler::ActiveBuiltinHandler::handle(spv::Op opcode, const uint32_t *args, uint32_t length)
|
||||
{
|
||||
switch (opcode)
|
||||
{
|
||||
case OpStore:
|
||||
@@ -3993,6 +4043,17 @@ void Compiler::update_active_builtins()
|
||||
clip_distance_count = 0;
|
||||
ActiveBuiltinHandler handler(*this);
|
||||
traverse_all_reachable_opcodes(get<SPIRFunction>(ir.default_entry_point), handler);
|
||||
|
||||
ir.for_each_typed_id<SPIRVariable>([&](uint32_t, const SPIRVariable &var) {
|
||||
if (var.storage != StorageClassOutput)
|
||||
return;
|
||||
if (!interface_variable_exists_in_entry_point(var.self))
|
||||
return;
|
||||
|
||||
// Also, make sure we preserve output variables which are only initialized, but never accessed by any code.
|
||||
if (var.initializer != ID(0))
|
||||
handler.add_if_builtin_or_block(var.self);
|
||||
});
|
||||
}
|
||||
|
||||
// Returns whether this shader uses a builtin of the storage class
|
||||
|
||||
3
3rdparty/spirv-cross/spirv_cross.hpp
vendored
3
3rdparty/spirv-cross/spirv_cross.hpp
vendored
@@ -833,6 +833,9 @@ protected:
|
||||
Compiler &compiler;
|
||||
|
||||
void handle_builtin(const SPIRType &type, spv::BuiltIn builtin, const Bitset &decoration_flags);
|
||||
void add_if_builtin(uint32_t id);
|
||||
void add_if_builtin_or_block(uint32_t id);
|
||||
void add_if_builtin(uint32_t id, bool allow_blocks);
|
||||
};
|
||||
|
||||
bool traverse_all_reachable_opcodes(const SPIRBlock &block, OpcodeHandler &handler) const;
|
||||
|
||||
@@ -235,6 +235,11 @@ bool ParsedIR::is_globally_reserved_identifier(std::string &str, bool allow_rese
|
||||
return is_reserved_identifier(str, false, allow_reserved_prefixes);
|
||||
}
|
||||
|
||||
uint32_t ParsedIR::get_spirv_version() const
|
||||
{
|
||||
return spirv[1];
|
||||
}
|
||||
|
||||
static string make_unreserved_identifier(const string &name)
|
||||
{
|
||||
if (is_reserved_prefix(name))
|
||||
|
||||
@@ -222,6 +222,8 @@ public:
|
||||
static void sanitize_identifier(std::string &str, bool member, bool allow_reserved_prefixes);
|
||||
static bool is_globally_reserved_identifier(std::string &str, bool allow_reserved_prefixes);
|
||||
|
||||
uint32_t get_spirv_version() const;
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
T &get(uint32_t id)
|
||||
|
||||
385
3rdparty/spirv-cross/spirv_glsl.cpp
vendored
385
3rdparty/spirv-cross/spirv_glsl.cpp
vendored
@@ -427,15 +427,37 @@ void CompilerGLSL::find_static_extensions()
|
||||
require_extension_internal("GL_ARB_tessellation_shader");
|
||||
break;
|
||||
|
||||
case ExecutionModelRayGenerationNV:
|
||||
case ExecutionModelIntersectionNV:
|
||||
case ExecutionModelAnyHitNV:
|
||||
case ExecutionModelClosestHitNV:
|
||||
case ExecutionModelMissNV:
|
||||
case ExecutionModelCallableNV:
|
||||
case ExecutionModelRayGenerationKHR:
|
||||
case ExecutionModelIntersectionKHR:
|
||||
case ExecutionModelAnyHitKHR:
|
||||
case ExecutionModelClosestHitKHR:
|
||||
case ExecutionModelMissKHR:
|
||||
case ExecutionModelCallableKHR:
|
||||
// NV enums are aliases.
|
||||
if (options.es || options.version < 460)
|
||||
SPIRV_CROSS_THROW("Ray tracing shaders require non-es profile with version 460 or above.");
|
||||
require_extension_internal("GL_NV_ray_tracing");
|
||||
if (!options.vulkan_semantics)
|
||||
SPIRV_CROSS_THROW("Ray tracing requires Vulkan semantics.");
|
||||
|
||||
// Need to figure out if we should target KHR or NV extension based on capabilities.
|
||||
for (auto &cap : ir.declared_capabilities)
|
||||
{
|
||||
if (cap == CapabilityRayTracingKHR || cap == CapabilityRayQueryKHR)
|
||||
{
|
||||
ray_tracing_is_khr = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ray_tracing_is_khr)
|
||||
{
|
||||
// In KHR ray tracing we pass payloads by pointer instead of location,
|
||||
// so make sure we assign locations properly.
|
||||
ray_tracing_khr_fixup_locations();
|
||||
require_extension_internal("GL_EXT_ray_tracing");
|
||||
}
|
||||
else
|
||||
require_extension_internal("GL_NV_ray_tracing");
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -512,6 +534,18 @@ void CompilerGLSL::find_static_extensions()
|
||||
}
|
||||
}
|
||||
|
||||
void CompilerGLSL::ray_tracing_khr_fixup_locations()
|
||||
{
|
||||
uint32_t location = 0;
|
||||
ir.for_each_typed_id<SPIRVariable>([&](uint32_t, SPIRVariable &var) {
|
||||
if (var.storage != StorageClassRayPayloadKHR && var.storage != StorageClassCallableDataKHR)
|
||||
return;
|
||||
if (!interface_variable_exists_in_entry_point(var.self))
|
||||
return;
|
||||
set_decoration(var.self, DecorationLocation, location++);
|
||||
});
|
||||
}
|
||||
|
||||
string CompilerGLSL::compile()
|
||||
{
|
||||
ir.fixup_reserved_names();
|
||||
@@ -1620,8 +1654,8 @@ string CompilerGLSL::layout_for_variable(const SPIRVariable &var)
|
||||
|
||||
if (options.vulkan_semantics && var.storage == StorageClassPushConstant)
|
||||
attr.push_back("push_constant");
|
||||
else if (var.storage == StorageClassShaderRecordBufferNV)
|
||||
attr.push_back("shaderRecordNV");
|
||||
else if (var.storage == StorageClassShaderRecordBufferKHR)
|
||||
attr.push_back(ray_tracing_is_khr ? "shaderRecordEXT" : "shaderRecordNV");
|
||||
|
||||
if (flags.get(DecorationRowMajor))
|
||||
attr.push_back("row_major");
|
||||
@@ -1777,14 +1811,14 @@ string CompilerGLSL::layout_for_variable(const SPIRVariable &var)
|
||||
|
||||
// Do not emit set = decoration in regular GLSL output, but
|
||||
// we need to preserve it in Vulkan GLSL mode.
|
||||
if (var.storage != StorageClassPushConstant && var.storage != StorageClassShaderRecordBufferNV)
|
||||
if (var.storage != StorageClassPushConstant && var.storage != StorageClassShaderRecordBufferKHR)
|
||||
{
|
||||
if (flags.get(DecorationDescriptorSet) && options.vulkan_semantics)
|
||||
attr.push_back(join("set = ", get_decoration(var.self, DecorationDescriptorSet)));
|
||||
}
|
||||
|
||||
bool push_constant_block = options.vulkan_semantics && var.storage == StorageClassPushConstant;
|
||||
bool ssbo_block = var.storage == StorageClassStorageBuffer || var.storage == StorageClassShaderRecordBufferNV ||
|
||||
bool ssbo_block = var.storage == StorageClassStorageBuffer || var.storage == StorageClassShaderRecordBufferKHR ||
|
||||
(var.storage == StorageClassUniform && typeflags.get(DecorationBufferBlock));
|
||||
bool emulated_ubo = var.storage == StorageClassPushConstant && options.emit_push_constant_as_uniform_buffer;
|
||||
bool ubo_block = var.storage == StorageClassUniform && typeflags.get(DecorationBlock);
|
||||
@@ -1806,7 +1840,7 @@ string CompilerGLSL::layout_for_variable(const SPIRVariable &var)
|
||||
if (!can_use_buffer_blocks && var.storage == StorageClassUniform)
|
||||
can_use_binding = false;
|
||||
|
||||
if (var.storage == StorageClassShaderRecordBufferNV)
|
||||
if (var.storage == StorageClassShaderRecordBufferKHR)
|
||||
can_use_binding = false;
|
||||
|
||||
if (can_use_binding && flags.get(DecorationBinding))
|
||||
@@ -2086,7 +2120,7 @@ void CompilerGLSL::emit_buffer_block_native(const SPIRVariable &var)
|
||||
auto &type = get<SPIRType>(var.basetype);
|
||||
|
||||
Bitset flags = ir.get_buffer_block_flags(var);
|
||||
bool ssbo = var.storage == StorageClassStorageBuffer || var.storage == StorageClassShaderRecordBufferNV ||
|
||||
bool ssbo = var.storage == StorageClassStorageBuffer || var.storage == StorageClassShaderRecordBufferKHR ||
|
||||
ir.meta[type.self].decoration.decoration_flags.get(DecorationBufferBlock);
|
||||
bool is_restrict = ssbo && flags.get(DecorationRestrict);
|
||||
bool is_writeonly = ssbo && flags.get(DecorationNonReadable);
|
||||
@@ -2201,25 +2235,25 @@ const char *CompilerGLSL::to_storage_qualifiers_glsl(const SPIRVariable &var)
|
||||
{
|
||||
return "uniform ";
|
||||
}
|
||||
else if (var.storage == StorageClassRayPayloadNV)
|
||||
else if (var.storage == StorageClassRayPayloadKHR)
|
||||
{
|
||||
return "rayPayloadNV ";
|
||||
return ray_tracing_is_khr ? "rayPayloadEXT " : "rayPayloadNV ";
|
||||
}
|
||||
else if (var.storage == StorageClassIncomingRayPayloadNV)
|
||||
else if (var.storage == StorageClassIncomingRayPayloadKHR)
|
||||
{
|
||||
return "rayPayloadInNV ";
|
||||
return ray_tracing_is_khr ? "rayPayloadInEXT " : "rayPayloadInNV ";
|
||||
}
|
||||
else if (var.storage == StorageClassHitAttributeNV)
|
||||
else if (var.storage == StorageClassHitAttributeKHR)
|
||||
{
|
||||
return "hitAttributeNV ";
|
||||
return ray_tracing_is_khr ? "hitAttributeEXT " : "hitAttributeNV ";
|
||||
}
|
||||
else if (var.storage == StorageClassCallableDataNV)
|
||||
else if (var.storage == StorageClassCallableDataKHR)
|
||||
{
|
||||
return "callableDataNV ";
|
||||
return ray_tracing_is_khr ? "callableDataEXT " : "callableDataNV ";
|
||||
}
|
||||
else if (var.storage == StorageClassIncomingCallableDataNV)
|
||||
else if (var.storage == StorageClassIncomingCallableDataKHR)
|
||||
{
|
||||
return "callableDataInNV ";
|
||||
return ray_tracing_is_khr ? "callableDataInEXT " : "callableDataInNV ";
|
||||
}
|
||||
|
||||
return "";
|
||||
@@ -2363,6 +2397,9 @@ void CompilerGLSL::emit_interface_block(const SPIRVariable &var)
|
||||
require_extension_internal("GL_EXT_shader_io_blocks");
|
||||
}
|
||||
|
||||
// Workaround to make sure we can emit "patch in/out" correctly.
|
||||
fixup_io_block_patch_qualifiers(var);
|
||||
|
||||
// Block names should never alias.
|
||||
auto block_name = to_name(type.self, false);
|
||||
|
||||
@@ -2384,7 +2421,8 @@ void CompilerGLSL::emit_interface_block(const SPIRVariable &var)
|
||||
// Instance names cannot alias block names.
|
||||
resource_names.insert(block_name);
|
||||
|
||||
statement(layout_for_variable(var), qual, block_name);
|
||||
bool is_patch = has_decoration(var.self, DecorationPatch);
|
||||
statement(layout_for_variable(var), (is_patch ? "patch " : ""), qual, block_name);
|
||||
begin_scope();
|
||||
|
||||
type.member_name_cache.clear();
|
||||
@@ -2441,14 +2479,6 @@ void CompilerGLSL::emit_interface_block(const SPIRVariable &var)
|
||||
swap(type.array.back(), old_array_size);
|
||||
swap(type.array_size_literal.back(), old_array_size_literal);
|
||||
}
|
||||
|
||||
// If a StorageClassOutput variable has an initializer, we need to initialize it in main().
|
||||
if (var.storage == StorageClassOutput && var.initializer)
|
||||
{
|
||||
auto &entry_func = this->get<SPIRFunction>(ir.default_entry_point);
|
||||
entry_func.fixup_hooks_in.push_back(
|
||||
[&]() { statement(to_name(var.self), " = ", to_expression(var.initializer), ";"); });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2551,7 +2581,17 @@ void CompilerGLSL::replace_illegal_names(const unordered_set<string> &keywords)
|
||||
return;
|
||||
|
||||
auto &m = meta->decoration;
|
||||
if (m.alias.compare(0, 3, "gl_") == 0 || keywords.find(m.alias) != end(keywords))
|
||||
if (keywords.find(m.alias) != end(keywords))
|
||||
m.alias = join("_", m.alias);
|
||||
});
|
||||
|
||||
ir.for_each_typed_id<SPIRFunction>([&](uint32_t, const SPIRFunction &func) {
|
||||
auto *meta = ir.find_meta(func.self);
|
||||
if (!meta)
|
||||
return;
|
||||
|
||||
auto &m = meta->decoration;
|
||||
if (keywords.find(m.alias) != end(keywords))
|
||||
m.alias = join("_", m.alias);
|
||||
});
|
||||
|
||||
@@ -2561,11 +2601,11 @@ void CompilerGLSL::replace_illegal_names(const unordered_set<string> &keywords)
|
||||
return;
|
||||
|
||||
auto &m = meta->decoration;
|
||||
if (m.alias.compare(0, 3, "gl_") == 0 || keywords.find(m.alias) != end(keywords))
|
||||
if (keywords.find(m.alias) != end(keywords))
|
||||
m.alias = join("_", m.alias);
|
||||
|
||||
for (auto &memb : meta->members)
|
||||
if (memb.alias.compare(0, 3, "gl_") == 0 || keywords.find(memb.alias) != end(keywords))
|
||||
if (keywords.find(memb.alias) != end(keywords))
|
||||
memb.alias = join("_", memb.alias);
|
||||
});
|
||||
}
|
||||
@@ -2795,6 +2835,13 @@ bool CompilerGLSL::should_force_emit_builtin_block(StorageClass storage)
|
||||
}
|
||||
});
|
||||
|
||||
// If we're declaring clip/cull planes with control points we need to force block declaration.
|
||||
if (get_execution_model() == ExecutionModelTessellationControl &&
|
||||
(clip_distance_count || cull_distance_count))
|
||||
{
|
||||
should_force = true;
|
||||
}
|
||||
|
||||
return should_force;
|
||||
}
|
||||
|
||||
@@ -3205,8 +3252,8 @@ void CompilerGLSL::emit_resources()
|
||||
// Special case, ray payload and hit attribute blocks are not really blocks, just regular structs.
|
||||
if (type->basetype == SPIRType::Struct && type->pointer &&
|
||||
has_decoration(type->self, DecorationBlock) &&
|
||||
(type->storage == StorageClassRayPayloadNV || type->storage == StorageClassIncomingRayPayloadNV ||
|
||||
type->storage == StorageClassHitAttributeNV))
|
||||
(type->storage == StorageClassRayPayloadKHR || type->storage == StorageClassIncomingRayPayloadKHR ||
|
||||
type->storage == StorageClassHitAttributeKHR))
|
||||
{
|
||||
type = &get<SPIRType>(type->parent_type);
|
||||
is_natural_struct = true;
|
||||
@@ -3282,7 +3329,7 @@ void CompilerGLSL::emit_resources()
|
||||
auto &type = this->get<SPIRType>(var.basetype);
|
||||
|
||||
bool is_block_storage = type.storage == StorageClassStorageBuffer || type.storage == StorageClassUniform ||
|
||||
type.storage == StorageClassShaderRecordBufferNV;
|
||||
type.storage == StorageClassShaderRecordBufferKHR;
|
||||
bool has_block_flags = ir.meta[type.self].decoration.decoration_flags.get(DecorationBlock) ||
|
||||
ir.meta[type.self].decoration.decoration_flags.get(DecorationBufferBlock);
|
||||
|
||||
@@ -3322,9 +3369,9 @@ void CompilerGLSL::emit_resources()
|
||||
|
||||
if (var.storage != StorageClassFunction && type.pointer &&
|
||||
(type.storage == StorageClassUniformConstant || type.storage == StorageClassAtomicCounter ||
|
||||
type.storage == StorageClassRayPayloadNV || type.storage == StorageClassIncomingRayPayloadNV ||
|
||||
type.storage == StorageClassCallableDataNV || type.storage == StorageClassIncomingCallableDataNV ||
|
||||
type.storage == StorageClassHitAttributeNV) &&
|
||||
type.storage == StorageClassRayPayloadKHR || type.storage == StorageClassIncomingRayPayloadKHR ||
|
||||
type.storage == StorageClassCallableDataKHR || type.storage == StorageClassIncomingCallableDataKHR ||
|
||||
type.storage == StorageClassHitAttributeKHR) &&
|
||||
!is_hidden_variable(var))
|
||||
{
|
||||
emit_uniform(var);
|
||||
@@ -3421,6 +3468,10 @@ void CompilerGLSL::emit_resources()
|
||||
emitted = true;
|
||||
}
|
||||
}
|
||||
else if (var.initializer && maybe_get<SPIRConstant>(var.initializer) != nullptr)
|
||||
{
|
||||
emit_output_variable_initializer(var);
|
||||
}
|
||||
}
|
||||
|
||||
if (emitted)
|
||||
@@ -3429,6 +3480,140 @@ void CompilerGLSL::emit_resources()
|
||||
declare_undefined_values();
|
||||
}
|
||||
|
||||
void CompilerGLSL::emit_output_variable_initializer(const SPIRVariable &var)
|
||||
{
|
||||
// If a StorageClassOutput variable has an initializer, we need to initialize it in main().
|
||||
auto &entry_func = this->get<SPIRFunction>(ir.default_entry_point);
|
||||
auto &type = get<SPIRType>(var.basetype);
|
||||
bool is_patch = has_decoration(var.self, DecorationPatch);
|
||||
bool is_block = has_decoration(type.self, DecorationBlock);
|
||||
bool is_control_point = get_execution_model() == ExecutionModelTessellationControl && !is_patch;
|
||||
|
||||
if (is_block)
|
||||
{
|
||||
uint32_t member_count = uint32_t(type.member_types.size());
|
||||
bool type_is_array = type.array.size() == 1;
|
||||
uint32_t array_size = 1;
|
||||
if (type_is_array)
|
||||
array_size = to_array_size_literal(type);
|
||||
uint32_t iteration_count = is_control_point ? 1 : array_size;
|
||||
|
||||
// If the initializer is a block, we must initialize each block member one at a time.
|
||||
for (uint32_t i = 0; i < member_count; i++)
|
||||
{
|
||||
// These outputs might not have been properly declared, so don't initialize them in that case.
|
||||
if (has_member_decoration(type.self, i, DecorationBuiltIn))
|
||||
{
|
||||
if (get_member_decoration(type.self, i, DecorationBuiltIn) == BuiltInCullDistance &&
|
||||
!cull_distance_count)
|
||||
continue;
|
||||
|
||||
if (get_member_decoration(type.self, i, DecorationBuiltIn) == BuiltInClipDistance &&
|
||||
!clip_distance_count)
|
||||
continue;
|
||||
}
|
||||
|
||||
// We need to build a per-member array first, essentially transposing from AoS to SoA.
|
||||
// This code path hits when we have an array of blocks.
|
||||
string lut_name;
|
||||
if (type_is_array)
|
||||
{
|
||||
lut_name = join("_", var.self, "_", i, "_init");
|
||||
uint32_t member_type_id = get<SPIRType>(var.basetype).member_types[i];
|
||||
auto &member_type = get<SPIRType>(member_type_id);
|
||||
auto array_type = member_type;
|
||||
array_type.parent_type = member_type_id;
|
||||
array_type.array.push_back(array_size);
|
||||
array_type.array_size_literal.push_back(true);
|
||||
|
||||
SmallVector<string> exprs;
|
||||
exprs.reserve(array_size);
|
||||
auto &c = get<SPIRConstant>(var.initializer);
|
||||
for (uint32_t j = 0; j < array_size; j++)
|
||||
exprs.push_back(to_expression(get<SPIRConstant>(c.subconstants[j]).subconstants[i]));
|
||||
statement("const ", type_to_glsl(array_type), " ", lut_name, type_to_array_glsl(array_type), " = ",
|
||||
type_to_glsl_constructor(array_type), "(", merge(exprs, ", "), ");");
|
||||
}
|
||||
|
||||
for (uint32_t j = 0; j < iteration_count; j++)
|
||||
{
|
||||
entry_func.fixup_hooks_in.push_back([=, &var]() {
|
||||
AccessChainMeta meta;
|
||||
auto &c = this->get<SPIRConstant>(var.initializer);
|
||||
|
||||
uint32_t invocation_id = 0;
|
||||
uint32_t member_index_id = 0;
|
||||
if (is_control_point)
|
||||
{
|
||||
uint32_t ids = ir.increase_bound_by(3);
|
||||
SPIRType uint_type;
|
||||
uint_type.basetype = SPIRType::UInt;
|
||||
uint_type.width = 32;
|
||||
set<SPIRType>(ids, uint_type);
|
||||
set<SPIRExpression>(ids + 1, builtin_to_glsl(BuiltInInvocationId, StorageClassInput), ids, true);
|
||||
set<SPIRConstant>(ids + 2, ids, i, false);
|
||||
invocation_id = ids + 1;
|
||||
member_index_id = ids + 2;
|
||||
}
|
||||
|
||||
if (is_patch)
|
||||
{
|
||||
statement("if (gl_InvocationID == 0)");
|
||||
begin_scope();
|
||||
}
|
||||
|
||||
if (type_is_array && !is_control_point)
|
||||
{
|
||||
uint32_t indices[2] = { j, i };
|
||||
auto chain = access_chain_internal(var.self, indices, 2, ACCESS_CHAIN_INDEX_IS_LITERAL_BIT, &meta);
|
||||
statement(chain, " = ", lut_name, "[", j, "];");
|
||||
}
|
||||
else if (is_control_point)
|
||||
{
|
||||
uint32_t indices[2] = { invocation_id, member_index_id };
|
||||
auto chain = access_chain_internal(var.self, indices, 2, 0, &meta);
|
||||
statement(chain, " = ", lut_name, "[", builtin_to_glsl(BuiltInInvocationId, StorageClassInput), "];");
|
||||
}
|
||||
else
|
||||
{
|
||||
auto chain =
|
||||
access_chain_internal(var.self, &i, 1, ACCESS_CHAIN_INDEX_IS_LITERAL_BIT, &meta);
|
||||
statement(chain, " = ", to_expression(c.subconstants[i]), ";");
|
||||
}
|
||||
|
||||
if (is_patch)
|
||||
end_scope();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (is_control_point)
|
||||
{
|
||||
auto lut_name = join("_", var.self, "_init");
|
||||
statement("const ", type_to_glsl(type), " ", lut_name, type_to_array_glsl(type),
|
||||
" = ", to_expression(var.initializer), ";");
|
||||
entry_func.fixup_hooks_in.push_back([&, lut_name]() {
|
||||
statement(to_expression(var.self), "[gl_InvocationID] = ", lut_name, "[gl_InvocationID];");
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
auto lut_name = join("_", var.self, "_init");
|
||||
statement("const ", type_to_glsl(type), " ", lut_name,
|
||||
type_to_array_glsl(type), " = ", to_expression(var.initializer), ";");
|
||||
entry_func.fixup_hooks_in.push_back([&, lut_name, is_patch]() {
|
||||
if (is_patch)
|
||||
{
|
||||
statement("if (gl_InvocationID == 0)");
|
||||
begin_scope();
|
||||
}
|
||||
statement(to_expression(var.self), " = ", lut_name, ";");
|
||||
if (is_patch)
|
||||
end_scope();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void CompilerGLSL::emit_extension_workarounds(spv::ExecutionModel model)
|
||||
{
|
||||
static const char *workaround_types[] = { "int", "ivec2", "ivec3", "ivec4", "uint", "uvec2", "uvec3", "uvec4",
|
||||
@@ -7987,34 +8172,35 @@ string CompilerGLSL::builtin_to_glsl(BuiltIn builtin, StorageClass storage)
|
||||
request_subgroup_feature(ShaderSubgroupSupportHelper::SubgroupMask);
|
||||
return "gl_SubgroupLtMask";
|
||||
|
||||
case BuiltInLaunchIdNV:
|
||||
return "gl_LaunchIDNV";
|
||||
case BuiltInLaunchSizeNV:
|
||||
return "gl_LaunchSizeNV";
|
||||
case BuiltInWorldRayOriginNV:
|
||||
return "gl_WorldRayOriginNV";
|
||||
case BuiltInWorldRayDirectionNV:
|
||||
return "gl_WorldRayDirectionNV";
|
||||
case BuiltInObjectRayOriginNV:
|
||||
return "gl_ObjectRayOriginNV";
|
||||
case BuiltInObjectRayDirectionNV:
|
||||
return "gl_ObjectRayDirectionNV";
|
||||
case BuiltInRayTminNV:
|
||||
return "gl_RayTminNV";
|
||||
case BuiltInRayTmaxNV:
|
||||
return "gl_RayTmaxNV";
|
||||
case BuiltInInstanceCustomIndexNV:
|
||||
return "gl_InstanceCustomIndexNV";
|
||||
case BuiltInObjectToWorldNV:
|
||||
return "gl_ObjectToWorldNV";
|
||||
case BuiltInWorldToObjectNV:
|
||||
return "gl_WorldToObjectNV";
|
||||
case BuiltInLaunchIdKHR:
|
||||
return ray_tracing_is_khr ? "gl_LaunchIDEXT" : "gl_LaunchIDNV";
|
||||
case BuiltInLaunchSizeKHR:
|
||||
return ray_tracing_is_khr ? "gl_LaunchSizeEXT" : "gl_LaunchSizeNV";
|
||||
case BuiltInWorldRayOriginKHR:
|
||||
return ray_tracing_is_khr ? "gl_WorldRayOriginEXT" : "gl_WorldRayOriginNV";
|
||||
case BuiltInWorldRayDirectionKHR:
|
||||
return ray_tracing_is_khr ? "gl_WorldRayDirectionEXT" : "gl_WorldRayDirectionNV";
|
||||
case BuiltInObjectRayOriginKHR:
|
||||
return ray_tracing_is_khr ? "gl_ObjectRayOriginEXT" : "gl_ObjectRayOriginNV";
|
||||
case BuiltInObjectRayDirectionKHR:
|
||||
return ray_tracing_is_khr ? "gl_ObjectRayDirectionEXT" : "gl_ObjectRayDirectionNV";
|
||||
case BuiltInRayTminKHR:
|
||||
return ray_tracing_is_khr ? "gl_RayTminEXT" : "gl_RayTminNV";
|
||||
case BuiltInRayTmaxKHR:
|
||||
return ray_tracing_is_khr ? "gl_RayTmaxEXT" : "gl_RayTmaxNV";
|
||||
case BuiltInInstanceCustomIndexKHR:
|
||||
return ray_tracing_is_khr ? "gl_InstanceCustomIndexEXT" : "gl_InstanceCustomIndexNV";
|
||||
case BuiltInObjectToWorldKHR:
|
||||
return ray_tracing_is_khr ? "gl_ObjectToWorldEXT" : "gl_ObjectToWorldNV";
|
||||
case BuiltInWorldToObjectKHR:
|
||||
return ray_tracing_is_khr ? "gl_WorldToObjectEXT" : "gl_WorldToObjectNV";
|
||||
case BuiltInHitTNV:
|
||||
// gl_HitTEXT is an alias of RayTMax in KHR.
|
||||
return "gl_HitTNV";
|
||||
case BuiltInHitKindNV:
|
||||
return "gl_HitKindNV";
|
||||
case BuiltInIncomingRayFlagsNV:
|
||||
return "gl_IncomingRayFlagsNV";
|
||||
case BuiltInHitKindKHR:
|
||||
return ray_tracing_is_khr ? "gl_HitKindEXT" : "gl_HitKindNV";
|
||||
case BuiltInIncomingRayFlagsKHR:
|
||||
return ray_tracing_is_khr ? "gl_IncomingRayFlagsEXT" : "gl_IncomingRayFlagsNV";
|
||||
|
||||
case BuiltInBaryCoordNV:
|
||||
{
|
||||
@@ -12010,15 +12196,22 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
|
||||
break;
|
||||
}
|
||||
|
||||
case OpReportIntersectionNV:
|
||||
statement("reportIntersectionNV(", to_expression(ops[0]), ", ", to_expression(ops[1]), ");");
|
||||
case OpReportIntersectionKHR:
|
||||
// NV is same opcode.
|
||||
forced_temporaries.insert(ops[1]);
|
||||
if (ray_tracing_is_khr)
|
||||
GLSL_BFOP(reportIntersectionEXT);
|
||||
else
|
||||
GLSL_BFOP(reportIntersectionNV);
|
||||
flush_control_dependent_expressions(current_emitting_block->self);
|
||||
break;
|
||||
case OpIgnoreIntersectionNV:
|
||||
// KHR variant is a terminator.
|
||||
statement("ignoreIntersectionNV();");
|
||||
flush_control_dependent_expressions(current_emitting_block->self);
|
||||
break;
|
||||
case OpTerminateRayNV:
|
||||
// KHR variant is a terminator.
|
||||
statement("terminateRayNV();");
|
||||
flush_control_dependent_expressions(current_emitting_block->self);
|
||||
break;
|
||||
@@ -12029,10 +12222,29 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
|
||||
to_expression(ops[9]), ", ", to_expression(ops[10]), ");");
|
||||
flush_control_dependent_expressions(current_emitting_block->self);
|
||||
break;
|
||||
case OpTraceRayKHR:
|
||||
if (!has_decoration(ops[10], DecorationLocation))
|
||||
SPIRV_CROSS_THROW("A memory declaration object must be used in TraceRayKHR.");
|
||||
statement("traceRayEXT(", to_expression(ops[0]), ", ", to_expression(ops[1]), ", ", to_expression(ops[2]), ", ",
|
||||
to_expression(ops[3]), ", ", to_expression(ops[4]), ", ", to_expression(ops[5]), ", ",
|
||||
to_expression(ops[6]), ", ", to_expression(ops[7]), ", ", to_expression(ops[8]), ", ",
|
||||
to_expression(ops[9]), ", ", get_decoration(ops[10], DecorationLocation), ");");
|
||||
flush_control_dependent_expressions(current_emitting_block->self);
|
||||
break;
|
||||
case OpExecuteCallableNV:
|
||||
statement("executeCallableNV(", to_expression(ops[0]), ", ", to_expression(ops[1]), ");");
|
||||
flush_control_dependent_expressions(current_emitting_block->self);
|
||||
break;
|
||||
case OpExecuteCallableKHR:
|
||||
if (!has_decoration(ops[1], DecorationLocation))
|
||||
SPIRV_CROSS_THROW("A memory declaration object must be used in ExecuteCallableKHR.");
|
||||
statement("executeCallableEXT(", to_expression(ops[0]), ", ", get_decoration(ops[1], DecorationLocation), ");");
|
||||
flush_control_dependent_expressions(current_emitting_block->self);
|
||||
break;
|
||||
|
||||
case OpConvertUToAccelerationStructureKHR:
|
||||
GLSL_UFOP(accelerationStructureEXT);
|
||||
break;
|
||||
|
||||
case OpConvertUToPtr:
|
||||
{
|
||||
@@ -12409,6 +12621,31 @@ const char *CompilerGLSL::to_precision_qualifiers_glsl(uint32_t id)
|
||||
return flags_to_qualifiers_glsl(type, ir.meta[id].decoration.decoration_flags);
|
||||
}
|
||||
|
||||
void CompilerGLSL::fixup_io_block_patch_qualifiers(const SPIRVariable &var)
|
||||
{
|
||||
// Works around weird behavior in glslangValidator where
|
||||
// a patch out block is translated to just block members getting the decoration.
|
||||
// To make glslang not complain when we compile again, we have to transform this back to a case where
|
||||
// the variable itself has Patch decoration, and not members.
|
||||
auto &type = get<SPIRType>(var.basetype);
|
||||
if (has_decoration(type.self, DecorationBlock))
|
||||
{
|
||||
uint32_t member_count = uint32_t(type.member_types.size());
|
||||
for (uint32_t i = 0; i < member_count; i++)
|
||||
{
|
||||
if (has_member_decoration(type.self, i, DecorationPatch))
|
||||
{
|
||||
set_decoration(var.self, DecorationPatch);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (has_decoration(var.self, DecorationPatch))
|
||||
for (uint32_t i = 0; i < member_count; i++)
|
||||
unset_member_decoration(type.self, i, DecorationPatch);
|
||||
}
|
||||
}
|
||||
|
||||
string CompilerGLSL::to_qualifiers_glsl(uint32_t id)
|
||||
{
|
||||
auto &flags = ir.meta[id].decoration.decoration_flags;
|
||||
@@ -12802,7 +13039,7 @@ string CompilerGLSL::type_to_glsl(const SPIRType &type, uint32_t id)
|
||||
return comparison_ids.count(id) ? "samplerShadow" : "sampler";
|
||||
|
||||
case SPIRType::AccelerationStructure:
|
||||
return "accelerationStructureNV";
|
||||
return ray_tracing_is_khr ? "accelerationStructureEXT" : "accelerationStructureNV";
|
||||
|
||||
case SPIRType::Void:
|
||||
return "void";
|
||||
@@ -14441,6 +14678,14 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block)
|
||||
emit_next_block = false;
|
||||
break;
|
||||
|
||||
case SPIRBlock::IgnoreIntersection:
|
||||
statement("ignoreIntersectionEXT;");
|
||||
break;
|
||||
|
||||
case SPIRBlock::TerminateRay:
|
||||
statement("terminateRayEXT;");
|
||||
break;
|
||||
|
||||
default:
|
||||
SPIRV_CROSS_THROW("Unimplemented block terminator.");
|
||||
}
|
||||
|
||||
4
3rdparty/spirv-cross/spirv_glsl.hpp
vendored
4
3rdparty/spirv-cross/spirv_glsl.hpp
vendored
@@ -711,6 +711,8 @@ protected:
|
||||
std::string type_to_glsl_constructor(const SPIRType &type);
|
||||
std::string argument_decl(const SPIRFunction::Parameter &arg);
|
||||
virtual std::string to_qualifiers_glsl(uint32_t id);
|
||||
void fixup_io_block_patch_qualifiers(const SPIRVariable &var);
|
||||
void emit_output_variable_initializer(const SPIRVariable &var);
|
||||
const char *to_precision_qualifiers_glsl(uint32_t id);
|
||||
virtual const char *to_storage_qualifiers_glsl(const SPIRVariable &var);
|
||||
const char *flags_to_qualifiers_glsl(const SPIRType &type, const Bitset &flags);
|
||||
@@ -815,6 +817,8 @@ protected:
|
||||
bool requires_transpose_2x2 = false;
|
||||
bool requires_transpose_3x3 = false;
|
||||
bool requires_transpose_4x4 = false;
|
||||
bool ray_tracing_is_khr = false;
|
||||
void ray_tracing_khr_fixup_locations();
|
||||
|
||||
bool args_will_forward(uint32_t id, const uint32_t *args, uint32_t num_args, bool pure);
|
||||
void register_call_out_argument(uint32_t id);
|
||||
|
||||
58
3rdparty/spirv-cross/spirv_hlsl.cpp
vendored
58
3rdparty/spirv-cross/spirv_hlsl.cpp
vendored
@@ -839,6 +839,21 @@ std::string CompilerHLSL::to_semantic(uint32_t location, ExecutionModel em, Stor
|
||||
return join("TEXCOORD", location);
|
||||
}
|
||||
|
||||
std::string CompilerHLSL::to_initializer_expression(const SPIRVariable &var)
|
||||
{
|
||||
// We cannot emit static const initializer for block constants for practical reasons,
|
||||
// so just inline the initializer.
|
||||
// FIXME: There is a theoretical problem here if someone tries to composite extract
|
||||
// into this initializer since we don't declare it properly, but that is somewhat non-sensical.
|
||||
auto &type = get<SPIRType>(var.basetype);
|
||||
bool is_block = has_decoration(type.self, DecorationBlock);
|
||||
auto *c = maybe_get<SPIRConstant>(var.initializer);
|
||||
if (is_block && c)
|
||||
return constant_expression(*c);
|
||||
else
|
||||
return CompilerGLSL::to_initializer_expression(var);
|
||||
}
|
||||
|
||||
void CompilerHLSL::emit_io_block(const SPIRVariable &var)
|
||||
{
|
||||
auto &execution = get_entry_point();
|
||||
@@ -1008,12 +1023,43 @@ void CompilerHLSL::emit_builtin_variables()
|
||||
|
||||
bool need_base_vertex_info = false;
|
||||
|
||||
std::unordered_map<uint32_t, ID> builtin_to_initializer;
|
||||
ir.for_each_typed_id<SPIRVariable>([&](uint32_t, SPIRVariable &var) {
|
||||
if (!is_builtin_variable(var) || var.storage != StorageClassOutput || !var.initializer)
|
||||
return;
|
||||
|
||||
auto *c = this->maybe_get<SPIRConstant>(var.initializer);
|
||||
if (!c)
|
||||
return;
|
||||
|
||||
auto &type = this->get<SPIRType>(var.basetype);
|
||||
if (type.basetype == SPIRType::Struct)
|
||||
{
|
||||
uint32_t member_count = uint32_t(type.member_types.size());
|
||||
for (uint32_t i = 0; i < member_count; i++)
|
||||
{
|
||||
if (has_member_decoration(type.self, i, DecorationBuiltIn))
|
||||
{
|
||||
builtin_to_initializer[get_member_decoration(type.self, i, DecorationBuiltIn)] =
|
||||
c->subconstants[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (has_decoration(var.self, DecorationBuiltIn))
|
||||
builtin_to_initializer[get_decoration(var.self, DecorationBuiltIn)] = var.initializer;
|
||||
});
|
||||
|
||||
// Emit global variables for the interface variables which are statically used by the shader.
|
||||
builtins.for_each_bit([&](uint32_t i) {
|
||||
const char *type = nullptr;
|
||||
auto builtin = static_cast<BuiltIn>(i);
|
||||
uint32_t array_size = 0;
|
||||
|
||||
string init_expr;
|
||||
auto init_itr = builtin_to_initializer.find(builtin);
|
||||
if (init_itr != builtin_to_initializer.end())
|
||||
init_expr = join(" = ", to_expression(init_itr->second));
|
||||
|
||||
switch (builtin)
|
||||
{
|
||||
case BuiltInFragCoord:
|
||||
@@ -1106,16 +1152,16 @@ void CompilerHLSL::emit_builtin_variables()
|
||||
if (type)
|
||||
{
|
||||
if (array_size)
|
||||
statement("static ", type, " ", builtin_to_glsl(builtin, storage), "[", array_size, "];");
|
||||
statement("static ", type, " ", builtin_to_glsl(builtin, storage), "[", array_size, "]", init_expr, ";");
|
||||
else
|
||||
statement("static ", type, " ", builtin_to_glsl(builtin, storage), ";");
|
||||
statement("static ", type, " ", builtin_to_glsl(builtin, storage), init_expr, ";");
|
||||
}
|
||||
|
||||
// SampleMask can be both in and out with sample builtin, in this case we have already
|
||||
// declared the input variable and we need to add the output one now.
|
||||
if (builtin == BuiltInSampleMask && storage == StorageClassInput && this->active_output_builtins.get(i))
|
||||
{
|
||||
statement("static ", type, " ", this->builtin_to_glsl(builtin, StorageClassOutput), ";");
|
||||
statement("static ", type, " ", this->builtin_to_glsl(builtin, StorageClassOutput), init_expr, ";");
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1141,7 +1187,11 @@ void CompilerHLSL::emit_composite_constants()
|
||||
return;
|
||||
|
||||
auto &type = this->get<SPIRType>(c.constant_type);
|
||||
if (type.basetype == SPIRType::Struct || !type.array.empty())
|
||||
|
||||
// Cannot declare block type constants here.
|
||||
// We do not have the struct type yet.
|
||||
bool is_block = has_decoration(type.self, DecorationBlock);
|
||||
if (!is_block && (type.basetype == SPIRType::Struct || !type.array.empty()))
|
||||
{
|
||||
auto name = to_name(c.self);
|
||||
statement("static const ", variable_decl(type, name), " = ", constant_expression(c), ";");
|
||||
|
||||
1
3rdparty/spirv-cross/spirv_hlsl.hpp
vendored
1
3rdparty/spirv-cross/spirv_hlsl.hpp
vendored
@@ -244,6 +244,7 @@ private:
|
||||
std::string to_resource_binding(const SPIRVariable &var);
|
||||
std::string to_resource_binding_sampler(const SPIRVariable &var);
|
||||
std::string to_resource_register(HLSLBindingFlagBits flag, char space, uint32_t binding, uint32_t set);
|
||||
std::string to_initializer_expression(const SPIRVariable &var) override;
|
||||
void emit_sampled_image_op(uint32_t result_type, uint32_t result_id, uint32_t image_id, uint32_t samp_id) override;
|
||||
void emit_access_chain(const Instruction &instruction);
|
||||
void emit_load(const Instruction &instruction);
|
||||
|
||||
251
3rdparty/spirv-cross/spirv_msl.cpp
vendored
251
3rdparty/spirv-cross/spirv_msl.cpp
vendored
@@ -198,9 +198,12 @@ void CompilerMSL::build_implicit_builtins()
|
||||
bool has_workgroup_size = false;
|
||||
uint32_t workgroup_id_type = 0;
|
||||
|
||||
// FIXME: Investigate the fact that there are no checks for the entry point interface variables.
|
||||
ir.for_each_typed_id<SPIRVariable>([&](uint32_t, SPIRVariable &var) {
|
||||
if (!ir.meta[var.self].decoration.builtin)
|
||||
if (var.storage != StorageClassInput && var.storage != StorageClassOutput)
|
||||
return;
|
||||
if (!interface_variable_exists_in_entry_point(var.self))
|
||||
return;
|
||||
if (!has_decoration(var.self, DecorationBuiltIn))
|
||||
return;
|
||||
|
||||
BuiltIn builtin = ir.meta[var.self].decoration.builtin_type;
|
||||
@@ -1180,6 +1183,7 @@ void CompilerMSL::emit_entry_point_declarations()
|
||||
|
||||
string CompilerMSL::compile()
|
||||
{
|
||||
replace_illegal_entry_point_names();
|
||||
ir.fixup_reserved_names();
|
||||
|
||||
// Do not deal with GLES-isms like precision, older extensions and such.
|
||||
@@ -1229,6 +1233,7 @@ string CompilerMSL::compile()
|
||||
|
||||
fixup_type_alias();
|
||||
replace_illegal_names();
|
||||
sync_entry_point_aliases_and_names();
|
||||
|
||||
build_function_control_flow_graphs_and_analyze();
|
||||
update_active_builtins();
|
||||
@@ -1992,8 +1997,22 @@ void CompilerMSL::add_plain_variable_to_interface_block(StorageClass storage, co
|
||||
}
|
||||
else
|
||||
{
|
||||
entry_func.fixup_hooks_in.push_back(
|
||||
[=, &var]() { statement(qual_var_name, " = ", to_expression(var.initializer), ";"); });
|
||||
if (meta.strip_array)
|
||||
{
|
||||
entry_func.fixup_hooks_in.push_back([=, &var]() {
|
||||
uint32_t index = get_extended_decoration(var.self, SPIRVCrossDecorationInterfaceMemberIndex);
|
||||
statement(to_expression(stage_out_ptr_var_id), "[",
|
||||
builtin_to_glsl(BuiltInInvocationId, StorageClassInput), "].",
|
||||
to_member_name(ib_type, index), " = ", to_expression(var.initializer), "[",
|
||||
builtin_to_glsl(BuiltInInvocationId, StorageClassInput), "];");
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
entry_func.fixup_hooks_in.push_back([=, &var]() {
|
||||
statement(qual_var_name, " = ", to_expression(var.initializer), ";");
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2510,6 +2529,8 @@ void CompilerMSL::add_plain_member_variable_to_interface_block(StorageClass stor
|
||||
qual_var_name += ".interpolate_at_center()";
|
||||
}
|
||||
|
||||
bool flatten_stage_out = false;
|
||||
|
||||
if (is_builtin && !meta.strip_array)
|
||||
{
|
||||
// For the builtin gl_PerVertex, we cannot treat it as a block anyways,
|
||||
@@ -2528,6 +2549,7 @@ void CompilerMSL::add_plain_member_variable_to_interface_block(StorageClass stor
|
||||
break;
|
||||
|
||||
case StorageClassOutput:
|
||||
flatten_stage_out = true;
|
||||
entry_func.fixup_hooks_out.push_back([=, &var, &var_type]() {
|
||||
statement(qual_var_name, " = ", to_name(var.self), ".", to_member_name(var_type, mbr_idx), ";");
|
||||
});
|
||||
@@ -2596,6 +2618,35 @@ void CompilerMSL::add_plain_member_variable_to_interface_block(StorageClass stor
|
||||
qual_pos_var_name = qual_var_name;
|
||||
}
|
||||
|
||||
const SPIRConstant *c = nullptr;
|
||||
if (!flatten_stage_out && var.storage == StorageClassOutput &&
|
||||
var.initializer != ID(0) && (c = maybe_get<SPIRConstant>(var.initializer)))
|
||||
{
|
||||
if (meta.strip_array)
|
||||
{
|
||||
entry_func.fixup_hooks_in.push_back([=, &var]() {
|
||||
auto &type = this->get<SPIRType>(var.basetype);
|
||||
uint32_t index = get_extended_decoration(var.self, SPIRVCrossDecorationInterfaceMemberIndex);
|
||||
index += mbr_idx;
|
||||
|
||||
AccessChainMeta chain_meta;
|
||||
auto constant_chain = access_chain_internal(var.initializer, &builtin_invocation_id_id, 1, 0, &chain_meta);
|
||||
|
||||
statement(to_expression(stage_out_ptr_var_id), "[",
|
||||
builtin_to_glsl(BuiltInInvocationId, StorageClassInput), "].",
|
||||
to_member_name(ib_type, index), " = ",
|
||||
constant_chain, ".", to_member_name(type, mbr_idx), ";");
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
entry_func.fixup_hooks_in.push_back([=]() {
|
||||
statement(qual_var_name, " = ", constant_expression(
|
||||
this->get<SPIRConstant>(c->subconstants[mbr_idx])), ";");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (storage != StorageClassInput || !pull_model_inputs.count(var.self))
|
||||
{
|
||||
// Copy interpolation decorations if needed
|
||||
@@ -2806,7 +2857,7 @@ void CompilerMSL::add_variable_to_interface_block(StorageClass storage, const st
|
||||
add_tess_level_input_to_interface_block(ib_var_ref, ib_type, var);
|
||||
}
|
||||
else if (var_type.basetype == SPIRType::Boolean || var_type.basetype == SPIRType::Char ||
|
||||
type_is_integral(var_type) || type_is_floating_point(var_type) || var_type.basetype == SPIRType::Boolean)
|
||||
type_is_integral(var_type) || type_is_floating_point(var_type))
|
||||
{
|
||||
if (!is_builtin || has_active_builtin(builtin, storage))
|
||||
{
|
||||
@@ -6102,6 +6153,15 @@ void CompilerMSL::emit_specialization_constants_and_structs()
|
||||
mark_scalar_layout_structs(type);
|
||||
});
|
||||
|
||||
bool builtin_block_type_is_required = false;
|
||||
// Very special case. If gl_PerVertex is initialized as an array (tessellation)
|
||||
// we have to potentially emit the gl_PerVertex struct type so that we can emit a constant LUT.
|
||||
ir.for_each_typed_id<SPIRConstant>([&](uint32_t, SPIRConstant &c) {
|
||||
auto &type = this->get<SPIRType>(c.constant_type);
|
||||
if (is_array(type) && has_decoration(type.self, DecorationBlock) && is_builtin_type(type))
|
||||
builtin_block_type_is_required = true;
|
||||
});
|
||||
|
||||
// Very particular use of the soft loop lock.
|
||||
// align_struct may need to create custom types on the fly, but we don't care about
|
||||
// these types for purpose of iterating over them in ir.ids_for_type and friends.
|
||||
@@ -6186,7 +6246,7 @@ void CompilerMSL::emit_specialization_constants_and_structs()
|
||||
has_decoration(type.self, DecorationBlock) || has_decoration(type.self, DecorationBufferBlock);
|
||||
|
||||
bool is_builtin_block = is_block && is_builtin_type(type);
|
||||
bool is_declarable_struct = is_struct && !is_builtin_block;
|
||||
bool is_declarable_struct = is_struct && (!is_builtin_block || builtin_block_type_is_required);
|
||||
|
||||
// We'll declare this later.
|
||||
if (stage_out_var_id && get_stage_out_struct_type().self == type_id)
|
||||
@@ -9849,7 +9909,14 @@ string CompilerMSL::to_struct_member(const SPIRType &type, uint32_t member_type_
|
||||
physical_type.basetype != SPIRType::SampledImage)
|
||||
{
|
||||
BuiltIn builtin = BuiltInMax;
|
||||
if (is_member_builtin(type, index, &builtin))
|
||||
|
||||
// Special handling. In [[stage_out]] or [[stage_in]] blocks,
|
||||
// we need flat arrays, but if we're somehow declaring gl_PerVertex for constant array reasons, we want
|
||||
// template array types to be declared.
|
||||
bool is_ib_in_out =
|
||||
((stage_out_var_id && get_stage_out_struct_type().self == type.self) ||
|
||||
(stage_in_var_id && get_stage_in_struct_type().self == type.self));
|
||||
if (is_ib_in_out && is_member_builtin(type, index, &builtin))
|
||||
is_using_builtin_array = true;
|
||||
array_type = type_to_array_glsl(physical_type);
|
||||
}
|
||||
@@ -10522,11 +10589,14 @@ void CompilerMSL::entry_point_args_builtin(string &ep_args)
|
||||
// Builtin variables
|
||||
SmallVector<pair<SPIRVariable *, BuiltIn>, 8> active_builtins;
|
||||
ir.for_each_typed_id<SPIRVariable>([&](uint32_t var_id, SPIRVariable &var) {
|
||||
if (var.storage != StorageClassInput)
|
||||
return;
|
||||
|
||||
auto bi_type = BuiltIn(get_decoration(var_id, DecorationBuiltIn));
|
||||
|
||||
// Don't emit SamplePosition as a separate parameter. In the entry
|
||||
// point, we get that by calling get_sample_position() on the sample ID.
|
||||
if (var.storage == StorageClassInput && is_builtin_variable(var) &&
|
||||
if (is_builtin_variable(var) &&
|
||||
get_variable_data_type(var).basetype != SPIRType::Struct &&
|
||||
get_variable_data_type(var).basetype != SPIRType::ControlPointArray)
|
||||
{
|
||||
@@ -10560,8 +10630,7 @@ void CompilerMSL::entry_point_args_builtin(string &ep_args)
|
||||
}
|
||||
}
|
||||
|
||||
if (var.storage == StorageClassInput &&
|
||||
has_extended_decoration(var_id, SPIRVCrossDecorationBuiltInDispatchBase))
|
||||
if (has_extended_decoration(var_id, SPIRVCrossDecorationBuiltInDispatchBase))
|
||||
{
|
||||
// This is a special implicit builtin, not corresponding to any SPIR-V builtin,
|
||||
// which holds the base that was passed to vkCmdDispatchBase() or vkCmdDrawIndexed(). If it's present,
|
||||
@@ -10573,8 +10642,7 @@ void CompilerMSL::entry_point_args_builtin(string &ep_args)
|
||||
ep_args += type_to_glsl(get_variable_data_type(var)) + " " + to_expression(var_id) + " [[grid_origin]]";
|
||||
}
|
||||
|
||||
if (var.storage == StorageClassInput &&
|
||||
has_extended_decoration(var_id, SPIRVCrossDecorationBuiltInStageInputSize))
|
||||
if (has_extended_decoration(var_id, SPIRVCrossDecorationBuiltInStageInputSize))
|
||||
{
|
||||
// This is another special implicit builtin, not corresponding to any SPIR-V builtin,
|
||||
// which holds the number of vertices and instances to draw. If it's present,
|
||||
@@ -10668,6 +10736,58 @@ void CompilerMSL::entry_point_args_builtin(string &ep_args)
|
||||
ep_args += ", ";
|
||||
ep_args += join("device ", get_tess_factor_struct_name(), "* ", tess_factor_buffer_var_name, " [[buffer(",
|
||||
convert_to_string(msl_options.shader_tess_factor_buffer_index), ")]]");
|
||||
|
||||
// Initializer for tess factors must be handled specially since it's never declared as a normal variable.
|
||||
uint32_t outer_factor_initializer_id = 0;
|
||||
uint32_t inner_factor_initializer_id = 0;
|
||||
ir.for_each_typed_id<SPIRVariable>([&](uint32_t, SPIRVariable &var) {
|
||||
if (!has_decoration(var.self, DecorationBuiltIn) || var.storage != StorageClassOutput || !var.initializer)
|
||||
return;
|
||||
|
||||
BuiltIn builtin = BuiltIn(get_decoration(var.self, DecorationBuiltIn));
|
||||
if (builtin == BuiltInTessLevelInner)
|
||||
inner_factor_initializer_id = var.initializer;
|
||||
else if (builtin == BuiltInTessLevelOuter)
|
||||
outer_factor_initializer_id = var.initializer;
|
||||
});
|
||||
|
||||
const SPIRConstant *c = nullptr;
|
||||
|
||||
if (outer_factor_initializer_id && (c = maybe_get<SPIRConstant>(outer_factor_initializer_id)))
|
||||
{
|
||||
auto &entry_func = get<SPIRFunction>(ir.default_entry_point);
|
||||
entry_func.fixup_hooks_in.push_back([=]() {
|
||||
uint32_t components = get_execution_mode_bitset().get(ExecutionModeTriangles) ? 3 : 4;
|
||||
for (uint32_t i = 0; i < components; i++)
|
||||
{
|
||||
statement(builtin_to_glsl(BuiltInTessLevelOuter, StorageClassOutput), "[", i, "] = ",
|
||||
"half(", to_expression(c->subconstants[i]), ");");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (inner_factor_initializer_id && (c = maybe_get<SPIRConstant>(inner_factor_initializer_id)))
|
||||
{
|
||||
auto &entry_func = get<SPIRFunction>(ir.default_entry_point);
|
||||
if (get_execution_mode_bitset().get(ExecutionModeTriangles))
|
||||
{
|
||||
entry_func.fixup_hooks_in.push_back([=]() {
|
||||
statement(builtin_to_glsl(BuiltInTessLevelInner, StorageClassOutput), " = ", "half(",
|
||||
to_expression(c->subconstants[0]), ");");
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
entry_func.fixup_hooks_in.push_back([=]() {
|
||||
for (uint32_t i = 0; i < 2; i++)
|
||||
{
|
||||
statement(builtin_to_glsl(BuiltInTessLevelInner, StorageClassOutput), "[", i, "] = ",
|
||||
"half(", to_expression(c->subconstants[i]), ");");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (stage_in_var_id)
|
||||
{
|
||||
if (!ep_args.empty())
|
||||
@@ -10786,12 +10906,7 @@ void CompilerMSL::entry_point_args_discrete_descriptors(string &ep_args)
|
||||
{
|
||||
auto &type = get_variable_data_type(var);
|
||||
|
||||
// Very specifically, image load-store in argument buffers are disallowed on MSL on iOS.
|
||||
// But we won't know when the argument buffer is encoded whether this image will have
|
||||
// a NonWritable decoration. So just use discrete arguments for all storage images
|
||||
// on iOS.
|
||||
if (!(msl_options.is_ios() && type.basetype == SPIRType::Image && type.image.sampled == 2) &&
|
||||
var.storage != StorageClassPushConstant)
|
||||
if (is_supported_argument_buffer_type(type) && var.storage != StorageClassPushConstant)
|
||||
{
|
||||
uint32_t desc_set = get_decoration(var_id, DecorationDescriptorSet);
|
||||
if (descriptor_set_is_argument_buffer(desc_set))
|
||||
@@ -11059,6 +11174,11 @@ void CompilerMSL::fix_up_shader_inputs_outputs()
|
||||
uint32_t var_id = var.self;
|
||||
BuiltIn bi_type = ir.meta[var_id].decoration.builtin_type;
|
||||
|
||||
if (var.storage != StorageClassInput && var.storage != StorageClassOutput)
|
||||
return;
|
||||
if (!interface_variable_exists_in_entry_point(var.self))
|
||||
return;
|
||||
|
||||
if (var.storage == StorageClassInput && is_builtin_variable(var) && active_input_builtins.get(bi_type))
|
||||
{
|
||||
switch (bi_type)
|
||||
@@ -11598,10 +11718,18 @@ uint32_t CompilerMSL::get_metal_resource_index(SPIRVariable &var, SPIRType::Base
|
||||
if (has_extended_decoration(var.self, resource_decoration))
|
||||
return get_extended_decoration(var.self, resource_decoration);
|
||||
|
||||
// Allow user to enable decoration binding
|
||||
if (msl_options.enable_decoration_binding)
|
||||
auto &type = get<SPIRType>(var.basetype);
|
||||
|
||||
if (type_is_msl_framebuffer_fetch(type))
|
||||
{
|
||||
// If there is no explicit mapping of bindings to MSL, use the declared binding.
|
||||
// Frame-buffer fetch gets its fallback resource index from the input attachment index,
|
||||
// which is then treated as color index.
|
||||
return get_decoration(var.self, DecorationInputAttachmentIndex);
|
||||
}
|
||||
else if (msl_options.enable_decoration_binding)
|
||||
{
|
||||
// Allow user to enable decoration binding.
|
||||
// If there is no explicit mapping of bindings to MSL, use the declared binding as a fallback.
|
||||
if (has_decoration(var.self, DecorationBinding))
|
||||
{
|
||||
var_binding = get_decoration(var.self, DecorationBinding);
|
||||
@@ -11620,7 +11748,6 @@ uint32_t CompilerMSL::get_metal_resource_index(SPIRVariable &var, SPIRType::Base
|
||||
allocate_argument_buffer_ids = descriptor_set_is_argument_buffer(var_desc_set);
|
||||
|
||||
uint32_t binding_stride = 1;
|
||||
auto &type = get<SPIRType>(var.basetype);
|
||||
for (uint32_t i = 0; i < uint32_t(type.array.size()); i++)
|
||||
binding_stride *= to_array_size_literal(type, i);
|
||||
|
||||
@@ -11629,13 +11756,7 @@ uint32_t CompilerMSL::get_metal_resource_index(SPIRVariable &var, SPIRType::Base
|
||||
// If a binding has not been specified, revert to incrementing resource indices.
|
||||
uint32_t resource_index;
|
||||
|
||||
if (type_is_msl_framebuffer_fetch(type))
|
||||
{
|
||||
// Frame-buffer fetch gets its fallback resource index from the input attachment index,
|
||||
// which is then treated as color index.
|
||||
resource_index = get_decoration(var.self, DecorationInputAttachmentIndex);
|
||||
}
|
||||
else if (allocate_argument_buffer_ids)
|
||||
if (allocate_argument_buffer_ids)
|
||||
{
|
||||
// Allocate from a flat ID binding space.
|
||||
resource_index = next_metal_resource_ids[var_desc_set];
|
||||
@@ -11884,11 +12005,8 @@ string CompilerMSL::ensure_valid_name(string name, string pfx)
|
||||
return (name.size() >= 2 && name[0] == '_' && isdigit(name[1])) ? (pfx + name) : name;
|
||||
}
|
||||
|
||||
// Replace all names that match MSL keywords or Metal Standard Library functions.
|
||||
void CompilerMSL::replace_illegal_names()
|
||||
const std::unordered_set<std::string> &CompilerMSL::get_reserved_keyword_set()
|
||||
{
|
||||
// FIXME: MSL and GLSL are doing two different things here.
|
||||
// Agree on convention and remove this override.
|
||||
static const unordered_set<string> keywords = {
|
||||
"kernel",
|
||||
"vertex",
|
||||
@@ -12022,6 +12140,11 @@ void CompilerMSL::replace_illegal_names()
|
||||
"quad_broadcast",
|
||||
};
|
||||
|
||||
return keywords;
|
||||
}
|
||||
|
||||
const std::unordered_set<std::string> &CompilerMSL::get_illegal_func_names()
|
||||
{
|
||||
static const unordered_set<string> illegal_func_names = {
|
||||
"main",
|
||||
"saturate",
|
||||
@@ -12148,6 +12271,17 @@ void CompilerMSL::replace_illegal_names()
|
||||
"M_SQRT1_2",
|
||||
};
|
||||
|
||||
return illegal_func_names;
|
||||
}
|
||||
|
||||
// Replace all names that match MSL keywords or Metal Standard Library functions.
|
||||
void CompilerMSL::replace_illegal_names()
|
||||
{
|
||||
// FIXME: MSL and GLSL are doing two different things here.
|
||||
// Agree on convention and remove this override.
|
||||
auto &keywords = get_reserved_keyword_set();
|
||||
auto &illegal_func_names = get_illegal_func_names();
|
||||
|
||||
ir.for_each_typed_id<SPIRVariable>([&](uint32_t self, SPIRVariable &) {
|
||||
auto *meta = ir.find_meta(self);
|
||||
if (!meta)
|
||||
@@ -12178,6 +12312,16 @@ void CompilerMSL::replace_illegal_names()
|
||||
mbr_dec.alias += "0";
|
||||
});
|
||||
|
||||
CompilerGLSL::replace_illegal_names();
|
||||
}
|
||||
|
||||
void CompilerMSL::replace_illegal_entry_point_names()
|
||||
{
|
||||
auto &illegal_func_names = get_illegal_func_names();
|
||||
|
||||
// It is important to this before we fixup identifiers,
|
||||
// since if ep_name is reserved, we will need to fix that up,
|
||||
// and then copy alias back into entry.name after the fixup.
|
||||
for (auto &entry : ir.entry_points)
|
||||
{
|
||||
// Change both the entry point name and the alias, to keep them synced.
|
||||
@@ -12185,11 +12329,14 @@ void CompilerMSL::replace_illegal_names()
|
||||
if (illegal_func_names.find(ep_name) != end(illegal_func_names))
|
||||
ep_name += "0";
|
||||
|
||||
// Always write this because entry point might have been renamed earlier.
|
||||
ir.meta[entry.first].decoration.alias = ep_name;
|
||||
}
|
||||
}
|
||||
|
||||
CompilerGLSL::replace_illegal_names();
|
||||
void CompilerMSL::sync_entry_point_aliases_and_names()
|
||||
{
|
||||
for (auto &entry : ir.entry_points)
|
||||
entry.second.name = ir.meta[entry.first].decoration.alias;
|
||||
}
|
||||
|
||||
string CompilerMSL::to_member_reference(uint32_t base, const SPIRType &type, uint32_t index, bool ptr_chain)
|
||||
@@ -14445,6 +14592,17 @@ bool CompilerMSL::descriptor_set_is_argument_buffer(uint32_t desc_set) const
|
||||
return (argument_buffer_discrete_mask & (1u << desc_set)) == 0;
|
||||
}
|
||||
|
||||
bool CompilerMSL::is_supported_argument_buffer_type(const SPIRType &type) const
|
||||
{
|
||||
// Very specifically, image load-store in argument buffers are disallowed on MSL on iOS.
|
||||
// But we won't know when the argument buffer is encoded whether this image will have
|
||||
// a NonWritable decoration. So just use discrete arguments for all storage images
|
||||
// on iOS.
|
||||
bool is_storage_image = type.basetype == SPIRType::Image && type.image.sampled == 2;
|
||||
bool is_supported_type = !msl_options.is_ios() || !is_storage_image;
|
||||
return !type_is_msl_framebuffer_fetch(type) && is_supported_type;
|
||||
}
|
||||
|
||||
void CompilerMSL::analyze_argument_buffers()
|
||||
{
|
||||
// Gather all used resources and sort them out into argument buffers.
|
||||
@@ -14527,23 +14685,20 @@ void CompilerMSL::analyze_argument_buffers()
|
||||
{
|
||||
inline_block_vars.push_back(var_id);
|
||||
}
|
||||
else if (!constexpr_sampler)
|
||||
else if (!constexpr_sampler && is_supported_argument_buffer_type(type))
|
||||
{
|
||||
// constexpr samplers are not declared as resources.
|
||||
// Inline uniform blocks are always emitted at the end.
|
||||
if (!msl_options.is_ios() || type.basetype != SPIRType::Image || type.image.sampled != 2)
|
||||
{
|
||||
add_resource_name(var_id);
|
||||
resources_in_set[desc_set].push_back(
|
||||
{ &var, to_name(var_id), type.basetype, get_metal_resource_index(var, type.basetype), 0 });
|
||||
add_resource_name(var_id);
|
||||
resources_in_set[desc_set].push_back(
|
||||
{ &var, to_name(var_id), type.basetype, get_metal_resource_index(var, type.basetype), 0 });
|
||||
|
||||
// Emulate texture2D atomic operations
|
||||
if (atomic_image_vars.count(var.self))
|
||||
{
|
||||
uint32_t buffer_resource_index = get_metal_resource_index(var, SPIRType::AtomicCounter, 0);
|
||||
resources_in_set[desc_set].push_back(
|
||||
{ &var, to_name(var_id) + "_atomic", SPIRType::Struct, buffer_resource_index, 0 });
|
||||
}
|
||||
// Emulate texture2D atomic operations
|
||||
if (atomic_image_vars.count(var.self))
|
||||
{
|
||||
uint32_t buffer_resource_index = get_metal_resource_index(var, SPIRType::AtomicCounter, 0);
|
||||
resources_in_set[desc_set].push_back(
|
||||
{ &var, to_name(var_id) + "_atomic", SPIRType::Struct, buffer_resource_index, 0 });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
7
3rdparty/spirv-cross/spirv_msl.hpp
vendored
7
3rdparty/spirv-cross/spirv_msl.hpp
vendored
@@ -735,6 +735,12 @@ protected:
|
||||
void declare_undefined_values() override;
|
||||
void declare_constant_arrays();
|
||||
|
||||
void replace_illegal_entry_point_names();
|
||||
void sync_entry_point_aliases_and_names();
|
||||
|
||||
static const std::unordered_set<std::string> &get_reserved_keyword_set();
|
||||
static const std::unordered_set<std::string> &get_illegal_func_names();
|
||||
|
||||
// Constant arrays of non-primitive types (i.e. matrices) won't link properly into Metal libraries
|
||||
void declare_complex_constant_arrays();
|
||||
|
||||
@@ -1020,6 +1026,7 @@ protected:
|
||||
void activate_argument_buffer_resources();
|
||||
|
||||
bool type_is_msl_framebuffer_fetch(const SPIRType &type) const;
|
||||
bool is_supported_argument_buffer_type(const SPIRType &type) const;
|
||||
|
||||
// OpcodeHandler that handles several MSL preprocessing operations.
|
||||
struct OpCodePreprocessor : OpcodeHandler
|
||||
|
||||
18
3rdparty/spirv-cross/spirv_parser.cpp
vendored
18
3rdparty/spirv-cross/spirv_parser.cpp
vendored
@@ -727,7 +727,7 @@ void Parser::parse(const Instruction &instruction)
|
||||
break;
|
||||
}
|
||||
|
||||
case OpTypeRayQueryProvisionalKHR:
|
||||
case OpTypeRayQueryKHR:
|
||||
{
|
||||
uint32_t id = ops[0];
|
||||
auto &type = set<SPIRType>(id);
|
||||
@@ -992,6 +992,22 @@ void Parser::parse(const Instruction &instruction)
|
||||
break;
|
||||
}
|
||||
|
||||
case OpTerminateRayKHR:
|
||||
// NV variant is not a terminator.
|
||||
if (!current_block)
|
||||
SPIRV_CROSS_THROW("Trying to end a non-existing block.");
|
||||
current_block->terminator = SPIRBlock::TerminateRay;
|
||||
current_block = nullptr;
|
||||
break;
|
||||
|
||||
case OpIgnoreIntersectionKHR:
|
||||
// NV variant is not a terminator.
|
||||
if (!current_block)
|
||||
SPIRV_CROSS_THROW("Trying to end a non-existing block.");
|
||||
current_block->terminator = SPIRBlock::IgnoreIntersection;
|
||||
current_block = nullptr;
|
||||
break;
|
||||
|
||||
case OpReturn:
|
||||
{
|
||||
if (!current_block)
|
||||
|
||||
Reference in New Issue
Block a user