update spirv-cross

This commit is contained in:
Alex Szpakowski
2021-03-23 21:35:54 -03:00
parent 319faf5bc3
commit cc140ed1ad
27 changed files with 7496 additions and 1837 deletions
+98 -10
View File
@@ -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 */
+99 -10
View File
@@ -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
+8 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2016-2020 Arm Limited
* Copyright 2016-2021 Arm Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,6 +14,13 @@
* limitations under the License.
*/
/*
* At your option, you may choose to accept this material under either:
* 1. The Apache License, Version 2.0, found at <http://www.apache.org/licenses/LICENSE-2.0>, or
* 2. The MIT License, found at <http://opensource.org/licenses/MIT>.
* SPDX-License-Identifier: Apache-2.0 OR MIT.
*/
#include "spirv_cfg.hpp"
#include "spirv_cross.hpp"
#include <algorithm>
+8 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2016-2020 Arm Limited
* Copyright 2016-2021 Arm Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,6 +14,13 @@
* limitations under the License.
*/
/*
* At your option, you may choose to accept this material under either:
* 1. The Apache License, Version 2.0, found at <http://www.apache.org/licenses/LICENSE-2.0>, or
* 2. The MIT License, found at <http://opensource.org/licenses/MIT>.
* SPDX-License-Identifier: Apache-2.0 OR MIT.
*/
#ifndef SPIRV_CROSS_CFG_HPP
#define SPIRV_CROSS_CFG_HPP
+82 -49
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2015-2020 Arm Limited
* Copyright 2015-2021 Arm Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,6 +14,13 @@
* limitations under the License.
*/
/*
* At your option, you may choose to accept this material under either:
* 1. The Apache License, Version 2.0, found at <http://www.apache.org/licenses/LICENSE-2.0>, or
* 2. The MIT License, found at <http://opensource.org/licenses/MIT>.
* SPDX-License-Identifier: Apache-2.0 OR MIT.
*/
#ifndef SPIRV_CROSS_COMMON_HPP
#define SPIRV_CROSS_COMMON_HPP
@@ -262,6 +269,29 @@ inline std::string convert_to_string(double t, char locale_radix_point)
return buf;
}
template <typename T>
struct ValueSaver
{
explicit ValueSaver(T &current_)
: current(current_)
, saved(current_)
{
}
void release()
{
current = saved;
}
~ValueSaver()
{
release();
}
T &current;
T saved;
};
#if defined(__clang__) || defined(__GNUC__)
#pragma GCC diagnostic pop
#elif defined(_MSC_VER)
@@ -272,8 +302,20 @@ struct Instruction
{
uint16_t op = 0;
uint16_t count = 0;
// If offset is 0 (not a valid offset into the instruction stream),
// we have an instruction stream which is embedded in the object.
uint32_t offset = 0;
uint32_t length = 0;
inline bool is_embedded() const
{
return offset == 0;
}
};
struct EmbeddedInstruction : Instruction
{
SmallVector<uint32_t> ops;
};
enum Types
@@ -334,28 +376,6 @@ public:
return TypedID<U>(*this);
}
bool operator==(const TypedID &other) const
{
return id == other.id;
}
bool operator!=(const TypedID &other) const
{
return id != other.id;
}
template <Types type>
bool operator==(const TypedID<type> &other) const
{
return id == uint32_t(other);
}
template <Types type>
bool operator!=(const TypedID<type> &other) const
{
return id != uint32_t(other);
}
private:
uint32_t id = 0;
};
@@ -380,26 +400,6 @@ public:
return id;
}
bool operator==(const TypedID &other) const
{
return id == other.id;
}
bool operator!=(const TypedID &other) const
{
return id != other.id;
}
bool operator==(const TypedID<TypeNone> &other) const
{
return id == uint32_t(other);
}
bool operator!=(const TypedID<TypeNone> &other) const
{
return id != uint32_t(other);
}
private:
uint32_t id = 0;
};
@@ -535,6 +535,7 @@ struct SPIRType : IVariant
// Keep internal types at the end.
ControlPointArray,
Interpolant,
Char
};
@@ -641,7 +642,7 @@ struct SPIREntryPoint
SmallVector<VariableID> interface_variables;
Bitset flags;
struct
struct WorkgroupSize
{
uint32_t x = 0, y = 0, z = 0;
uint32_t constant = 0; // Workgroup size can be expressed as a constant/spec-constant instead.
@@ -699,6 +700,9 @@ struct SPIRExpression : IVariant
// Used by access chain Store and Load since we read multiple expressions in this case.
SmallVector<ID> implied_read_expressions;
// The expression was emitted at a certain scope. Lets us track when an expression read means multiple reads.
uint32_t emitted_loop_level = 0;
SPIRV_CROSS_DECLARE_CLONE(SPIRExpression)
};
@@ -737,7 +741,9 @@ struct SPIRBlock : IVariant
Return, // Block ends with return.
Unreachable, // Noop
Kill // Discard
Kill, // Discard
IgnoreIntersection, // Ray Tracing
TerminateRay // Ray Tracing
};
enum Merge
@@ -1069,7 +1075,8 @@ struct SPIRConstant : IVariant
type = TypeConstant
};
union Constant {
union Constant
{
uint32_t u32;
int32_t i32;
float f32;
@@ -1107,7 +1114,8 @@ struct SPIRConstant : IVariant
int e = (u16_value >> 10) & 0x1f;
int m = (u16_value >> 0) & 0x3ff;
union {
union
{
float f32;
uint32_t u32;
} u;
@@ -1526,6 +1534,7 @@ struct AccessChainMeta
bool need_transpose = false;
bool storage_is_packed = false;
bool storage_is_invariant = false;
bool flattened_struct = false;
};
enum ExtendedDecorations
@@ -1560,8 +1569,10 @@ enum ExtendedDecorations
// Marks a buffer block for using explicit offsets (GLSL/HLSL).
SPIRVCrossDecorationExplicitOffset,
// Apply to a variable in the Input storage class; marks it as holding the base group passed to vkCmdDispatchBase().
// In MSL, this is used to adjust the WorkgroupId and GlobalInvocationId variables.
// Apply to a variable in the Input storage class; marks it as holding the base group passed to vkCmdDispatchBase(),
// or the base vertex and instance indices passed to vkCmdDrawIndexed().
// In MSL, this is used to adjust the WorkgroupId and GlobalInvocationId variables in compute shaders,
// and to hold the BaseVertex and BaseInstance variables in vertex shaders.
SPIRVCrossDecorationBuiltInDispatchBase,
// Apply to a variable that is a function parameter; marks it as being a "dynamic"
@@ -1570,6 +1581,27 @@ enum ExtendedDecorations
// Y'CbCr conversion.
SPIRVCrossDecorationDynamicImageSampler,
// Apply to a variable in the Input storage class; marks it as holding the size of the stage
// input grid.
// In MSL, this is used to hold the vertex and instance counts in a tessellation pipeline
// vertex shader.
SPIRVCrossDecorationBuiltInStageInputSize,
// Apply to any access chain of a tessellation I/O variable; stores the type of the sub-object
// that was chained to, as recorded in the input variable itself. This is used in case the pointer
// is itself used as the base of an access chain, to calculate the original type of the sub-object
// chained to, in case a swizzle needs to be applied. This should not happen normally with valid
// SPIR-V, but the MSL backend can change the type of input variables, necessitating the
// addition of swizzles to keep the generated code compiling.
SPIRVCrossDecorationTessIOOriginalInputTypeID,
// Apply to any access chain of an interface variable used with pull-model interpolation, where the variable is a
// vector but the resulting pointer is a scalar; stores the component index that is to be accessed by the chain.
// This is used when emitting calls to interpolation functions on the chain in MSL: in this case, the component
// must be applied to the result, since pull-model interpolants in MSL cannot be swizzled directly, but the
// results of interpolation can.
SPIRVCrossDecorationInterpolantComponentExpr,
SPIRVCrossDecorationCount
};
@@ -1589,6 +1621,7 @@ struct Meta
uint32_t offset = 0;
uint32_t xfb_buffer = 0;
uint32_t xfb_stride = 0;
uint32_t stream = 0;
uint32_t array_stride = 0;
uint32_t matrix_stride = 0;
uint32_t input_attachment = 0;
+10 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2015-2020 Arm Limited
* Copyright 2015-2021 Arm Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,6 +14,13 @@
* limitations under the License.
*/
/*
* At your option, you may choose to accept this material under either:
* 1. The Apache License, Version 2.0, found at <http://www.apache.org/licenses/LICENSE-2.0>, or
* 2. The MIT License, found at <http://opensource.org/licenses/MIT>.
* SPDX-License-Identifier: Apache-2.0 OR MIT.
*/
#include "spirv_cpp.hpp"
using namespace spv;
@@ -306,6 +313,8 @@ void CompilerCPP::emit_resources()
string CompilerCPP::compile()
{
ir.fixup_reserved_names();
// Do not deal with ES-isms like precision, older extensions and such.
options.es = false;
options.version = 450;
+8 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2015-2020 Arm Limited
* Copyright 2015-2021 Arm Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,6 +14,13 @@
* limitations under the License.
*/
/*
* At your option, you may choose to accept this material under either:
* 1. The Apache License, Version 2.0, found at <http://www.apache.org/licenses/LICENSE-2.0>, or
* 2. The MIT License, found at <http://opensource.org/licenses/MIT>.
* SPDX-License-Identifier: Apache-2.0 OR MIT.
*/
#ifndef SPIRV_CROSS_CPP_HPP
#define SPIRV_CROSS_CPP_HPP
+331 -39
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2015-2020 Arm Limited
* Copyright 2015-2021 Arm Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,6 +14,13 @@
* limitations under the License.
*/
/*
* At your option, you may choose to accept this material under either:
* 1. The Apache License, Version 2.0, found at <http://www.apache.org/licenses/LICENSE-2.0>, or
* 2. The MIT License, found at <http://opensource.org/licenses/MIT>.
* SPDX-License-Identifier: Apache-2.0 OR MIT.
*/
#include "spirv_cross.hpp"
#include "GLSL.std.450.h"
#include "spirv_cfg.hpp"
@@ -89,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)
@@ -151,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.
@@ -273,11 +284,27 @@ SPIRVariable *Compiler::maybe_get_backing_variable(uint32_t chain)
return var;
}
StorageClass Compiler::get_backing_variable_storage(uint32_t ptr)
StorageClass Compiler::get_expression_effective_storage_class(uint32_t ptr)
{
auto *var = maybe_get_backing_variable(ptr);
if (var)
return var->storage;
// If the expression has been lowered to a temporary, we need to use the Generic storage class.
// We're looking for the effective storage class of a given expression.
// An access chain or forwarded OpLoads from such access chains
// will generally have the storage class of the underlying variable, but if the load was not forwarded
// we have lost any address space qualifiers.
bool forced_temporary = ir.ids[ptr].get_type() == TypeExpression && !get<SPIRExpression>(ptr).access_chain &&
(forced_temporaries.count(ptr) != 0 || forwarded_temporaries.count(ptr) == 0);
if (var && !forced_temporary)
{
// Normalize SSBOs to StorageBuffer here.
if (var->storage == StorageClassUniform &&
has_decoration(get<SPIRType>(var->basetype).self, DecorationBufferBlock))
return StorageClassStorageBuffer;
else
return var->storage;
}
else
return expression_type(ptr).storage;
}
@@ -519,10 +546,16 @@ bool Compiler::is_hidden_variable(const SPIRVariable &var, bool include_builtins
return false;
}
bool hidden = false;
if (check_active_interface_variables && storage_class_is_interface(var.storage))
hidden = active_interface_variables.find(var.self) == end(active_interface_variables);
return hidden;
// In SPIR-V 1.4 and up we must also use the active variable interface to disable global variables
// which are not part of the entry point.
if (ir.get_spirv_version() >= 0x10400 && var.storage != spv::StorageClassGeneric &&
var.storage != spv::StorageClassFunction && !interface_variable_exists_in_entry_point(var.self))
{
return true;
}
return check_active_interface_variables && storage_class_is_interface(var.storage) &&
active_interface_variables.find(var.self) == end(active_interface_variables);
}
bool Compiler::is_builtin_type(const SPIRType &type) const
@@ -683,8 +716,31 @@ bool Compiler::InterfaceVariableAccessHandler::handle(Op opcode, const uint32_t
{
if (length < 5)
return false;
uint32_t extension_set = args[2];
if (compiler.get<SPIRExtension>(extension_set).ext == SPIRExtension::SPV_AMD_shader_explicit_vertex_parameter)
auto &extension_set = compiler.get<SPIRExtension>(args[2]);
switch (extension_set.ext)
{
case SPIRExtension::GLSL:
{
auto op = static_cast<GLSLstd450>(args[3]);
switch (op)
{
case GLSLstd450InterpolateAtCentroid:
case GLSLstd450InterpolateAtSample:
case GLSLstd450InterpolateAtOffset:
{
auto *var = compiler.maybe_get<SPIRVariable>(args[4]);
if (var && storage_class_is_interface(var->storage))
variables.insert(args[4]);
break;
}
default:
break;
}
break;
}
case SPIRExtension::SPV_AMD_shader_explicit_vertex_parameter:
{
enum AMDShaderExplicitVertexParameter
{
@@ -706,6 +762,10 @@ bool Compiler::InterfaceVariableAccessHandler::handle(Op opcode, const uint32_t
default:
break;
}
break;
}
default:
break;
}
break;
}
@@ -755,9 +815,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);
});
@@ -1636,6 +1704,161 @@ size_t Compiler::get_declared_struct_size_runtime_array(const SPIRType &type, si
return size;
}
uint32_t Compiler::evaluate_spec_constant_u32(const SPIRConstantOp &spec) const
{
auto &result_type = get<SPIRType>(spec.basetype);
if (result_type.basetype != SPIRType::UInt && result_type.basetype != SPIRType::Int &&
result_type.basetype != SPIRType::Boolean)
{
SPIRV_CROSS_THROW(
"Only 32-bit integers and booleans are currently supported when evaluating specialization constants.\n");
}
if (!is_scalar(result_type))
SPIRV_CROSS_THROW("Spec constant evaluation must be a scalar.\n");
uint32_t value = 0;
const auto eval_u32 = [&](uint32_t id) -> uint32_t {
auto &type = expression_type(id);
if (type.basetype != SPIRType::UInt && type.basetype != SPIRType::Int && type.basetype != SPIRType::Boolean)
{
SPIRV_CROSS_THROW("Only 32-bit integers and booleans are currently supported when evaluating "
"specialization constants.\n");
}
if (!is_scalar(type))
SPIRV_CROSS_THROW("Spec constant evaluation must be a scalar.\n");
if (const auto *c = this->maybe_get<SPIRConstant>(id))
return c->scalar();
else
return evaluate_spec_constant_u32(this->get<SPIRConstantOp>(id));
};
#define binary_spec_op(op, binary_op) \
case Op##op: \
value = eval_u32(spec.arguments[0]) binary_op eval_u32(spec.arguments[1]); \
break
#define binary_spec_op_cast(op, binary_op, type) \
case Op##op: \
value = uint32_t(type(eval_u32(spec.arguments[0])) binary_op type(eval_u32(spec.arguments[1]))); \
break
// Support the basic opcodes which are typically used when computing array sizes.
switch (spec.opcode)
{
binary_spec_op(IAdd, +);
binary_spec_op(ISub, -);
binary_spec_op(IMul, *);
binary_spec_op(BitwiseAnd, &);
binary_spec_op(BitwiseOr, |);
binary_spec_op(BitwiseXor, ^);
binary_spec_op(LogicalAnd, &);
binary_spec_op(LogicalOr, |);
binary_spec_op(ShiftLeftLogical, <<);
binary_spec_op(ShiftRightLogical, >>);
binary_spec_op_cast(ShiftRightArithmetic, >>, int32_t);
binary_spec_op(LogicalEqual, ==);
binary_spec_op(LogicalNotEqual, !=);
binary_spec_op(IEqual, ==);
binary_spec_op(INotEqual, !=);
binary_spec_op(ULessThan, <);
binary_spec_op(ULessThanEqual, <=);
binary_spec_op(UGreaterThan, >);
binary_spec_op(UGreaterThanEqual, >=);
binary_spec_op_cast(SLessThan, <, int32_t);
binary_spec_op_cast(SLessThanEqual, <=, int32_t);
binary_spec_op_cast(SGreaterThan, >, int32_t);
binary_spec_op_cast(SGreaterThanEqual, >=, int32_t);
#undef binary_spec_op
#undef binary_spec_op_cast
case OpLogicalNot:
value = uint32_t(!eval_u32(spec.arguments[0]));
break;
case OpNot:
value = ~eval_u32(spec.arguments[0]);
break;
case OpSNegate:
value = uint32_t(-int32_t(eval_u32(spec.arguments[0])));
break;
case OpSelect:
value = eval_u32(spec.arguments[0]) ? eval_u32(spec.arguments[1]) : eval_u32(spec.arguments[2]);
break;
case OpUMod:
{
uint32_t a = eval_u32(spec.arguments[0]);
uint32_t b = eval_u32(spec.arguments[1]);
if (b == 0)
SPIRV_CROSS_THROW("Undefined behavior in UMod, b == 0.\n");
value = a % b;
break;
}
case OpSRem:
{
auto a = int32_t(eval_u32(spec.arguments[0]));
auto b = int32_t(eval_u32(spec.arguments[1]));
if (b == 0)
SPIRV_CROSS_THROW("Undefined behavior in SRem, b == 0.\n");
value = a % b;
break;
}
case OpSMod:
{
auto a = int32_t(eval_u32(spec.arguments[0]));
auto b = int32_t(eval_u32(spec.arguments[1]));
if (b == 0)
SPIRV_CROSS_THROW("Undefined behavior in SMod, b == 0.\n");
auto v = a % b;
// Makes sure we match the sign of b, not a.
if ((b < 0 && v > 0) || (b > 0 && v < 0))
v += b;
value = v;
break;
}
case OpUDiv:
{
uint32_t a = eval_u32(spec.arguments[0]);
uint32_t b = eval_u32(spec.arguments[1]);
if (b == 0)
SPIRV_CROSS_THROW("Undefined behavior in UDiv, b == 0.\n");
value = a / b;
break;
}
case OpSDiv:
{
auto a = int32_t(eval_u32(spec.arguments[0]));
auto b = int32_t(eval_u32(spec.arguments[1]));
if (b == 0)
SPIRV_CROSS_THROW("Undefined behavior in SDiv, b == 0.\n");
value = a / b;
break;
}
default:
SPIRV_CROSS_THROW("Unsupported spec constant opcode for evaluation.\n");
}
return value;
}
uint32_t Compiler::evaluate_constant_u32(uint32_t id) const
{
if (const auto *c = maybe_get<SPIRConstant>(id))
return c->scalar();
else
return evaluate_spec_constant_u32(get<SPIRConstantOp>(id));
}
size_t Compiler::get_declared_struct_member_size(const SPIRType &struct_type, uint32_t index) const
{
if (struct_type.member_types.empty())
@@ -1670,7 +1893,7 @@ size_t Compiler::get_declared_struct_member_size(const SPIRType &struct_type, ui
{
// For arrays, we can use ArrayStride to get an easy check.
bool array_size_literal = type.array_size_literal.back();
uint32_t array_size = array_size_literal ? type.array.back() : get<SPIRConstant>(type.array.back()).scalar();
uint32_t array_size = array_size_literal ? type.array.back() : evaluate_constant_u32(type.array.back());
return type_struct_member_array_stride(struct_type, index) * array_size;
}
else if (type.basetype == SPIRType::Struct)
@@ -1904,6 +2127,13 @@ bool Compiler::is_tessellation_shader(ExecutionModel model)
return model == ExecutionModelTessellationControl || model == ExecutionModelTessellationEvaluation;
}
bool Compiler::is_vertex_like_shader() const
{
auto model = get_execution_model();
return model == ExecutionModelVertex || model == ExecutionModelGeometry ||
model == ExecutionModelTessellationControl || model == ExecutionModelTessellationEvaluation;
}
bool Compiler::is_tessellation_shader() const
{
return is_tessellation_shader(get_execution_model());
@@ -2067,16 +2297,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)) !=
@@ -2599,7 +2835,8 @@ const SPIRConstant &Compiler::get_constant(ConstantID id) const
return get<SPIRConstant>(id);
}
static bool exists_unaccessed_path_to_return(const CFG &cfg, uint32_t block, const unordered_set<uint32_t> &blocks)
static bool exists_unaccessed_path_to_return(const CFG &cfg, uint32_t block, const unordered_set<uint32_t> &blocks,
unordered_set<uint32_t> &visit_cache)
{
// This block accesses the variable.
if (blocks.find(block) != end(blocks))
@@ -2611,8 +2848,14 @@ static bool exists_unaccessed_path_to_return(const CFG &cfg, uint32_t block, con
// If any of our successors have a path to the end, there exists a path from block.
for (auto &succ : cfg.get_succeeding_edges(block))
if (exists_unaccessed_path_to_return(cfg, succ, blocks))
return true;
{
if (visit_cache.count(succ) == 0)
{
if (exists_unaccessed_path_to_return(cfg, succ, blocks, visit_cache))
return true;
visit_cache.insert(succ);
}
}
return false;
}
@@ -2669,7 +2912,8 @@ void Compiler::analyze_parameter_preservation(
// void foo(int &var) { if (cond) var = 10; }
// Using read/write counts, we will think it's just an out variable, but it really needs to be inout,
// because if we don't write anything whatever we put into the function must return back to the caller.
if (exists_unaccessed_path_to_return(cfg, entry.entry_block, itr->second))
unordered_set<uint32_t> visit_cache;
if (exists_unaccessed_path_to_return(cfg, entry.entry_block, itr->second, visit_cache))
arg.read_count++;
}
}
@@ -3627,23 +3871,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:
@@ -3781,6 +4057,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
@@ -4658,3 +4945,8 @@ bool Compiler::flush_phi_required(BlockID from, BlockID to) const
return true;
return false;
}
void Compiler::add_loop_level()
{
current_loop_level++;
}
+49 -5
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2015-2020 Arm Limited
* Copyright 2015-2021 Arm Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,6 +14,13 @@
* limitations under the License.
*/
/*
* At your option, you may choose to accept this material under either:
* 1. The Apache License, Version 2.0, found at <http://www.apache.org/licenses/LICENSE-2.0>, or
* 2. The MIT License, found at <http://opensource.org/licenses/MIT>.
* SPDX-License-Identifier: Apache-2.0 OR MIT.
*/
#ifndef SPIRV_CROSS_HPP
#define SPIRV_CROSS_HPP
@@ -491,6 +498,12 @@ public:
// The most common use here is to check if a buffer is readonly or writeonly.
Bitset get_buffer_block_flags(VariableID id) const;
// Returns whether the position output is invariant
bool is_position_invariant() const
{
return position_invariant;
}
protected:
const uint32_t *stream(const Instruction &instr) const
{
@@ -500,9 +513,18 @@ protected:
if (!instr.length)
return nullptr;
if (instr.offset + instr.length > ir.spirv.size())
SPIRV_CROSS_THROW("Compiler::stream() out of range.");
return &ir.spirv[instr.offset];
if (instr.is_embedded())
{
auto &embedded = static_cast<const EmbeddedInstruction &>(instr);
assert(embedded.ops.size() == instr.length);
return embedded.ops.data();
}
else
{
if (instr.offset + instr.length > ir.spirv.size())
SPIRV_CROSS_THROW("Compiler::stream() out of range.");
return &ir.spirv[instr.offset];
}
}
ParsedIR ir;
@@ -513,9 +535,22 @@ protected:
SPIRFunction *current_function = nullptr;
SPIRBlock *current_block = nullptr;
uint32_t current_loop_level = 0;
std::unordered_set<VariableID> active_interface_variables;
bool check_active_interface_variables = false;
void add_loop_level();
void set_initializers(SPIRExpression &e)
{
e.emitted_loop_level = current_loop_level;
}
template <typename T>
void set_initializers(const T &)
{
}
// If our IDs are out of range here as part of opcodes, throw instead of
// undefined behavior.
template <typename T, typename... P>
@@ -524,6 +559,7 @@ protected:
ir.add_typed_id(static_cast<Types>(T::type), id);
auto &var = variant_set<T>(ir.ids[id], std::forward<P>(args)...);
var.self = id;
set_initializers(var);
return var;
}
@@ -611,7 +647,7 @@ protected:
bool expression_is_lvalue(uint32_t id) const;
bool variable_storage_is_aliased(const SPIRVariable &var);
SPIRVariable *maybe_get_backing_variable(uint32_t chain);
spv::StorageClass get_backing_variable_storage(uint32_t ptr);
spv::StorageClass get_expression_effective_storage_class(uint32_t ptr);
void register_read(uint32_t expr, uint32_t chain, bool forwarded);
void register_write(uint32_t chain);
@@ -812,6 +848,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;
@@ -1046,6 +1085,11 @@ protected:
bool flush_phi_required(BlockID from, BlockID to) const;
uint32_t evaluate_spec_constant_u32(const SPIRConstantOp &spec) const;
uint32_t evaluate_constant_u32(uint32_t id) const;
bool is_vertex_like_shader() const;
private:
// Used only to implement the old deprecated get_entry_point() interface.
const SPIREntryPoint &get_first_entry_point(const std::string &name) const;
+157 -9
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Hans-Kristian Arntzen
* Copyright 2019-2021 Hans-Kristian Arntzen
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,6 +14,13 @@
* limitations under the License.
*/
/*
* At your option, you may choose to accept this material under either:
* 1. The Apache License, Version 2.0, found at <http://www.apache.org/licenses/LICENSE-2.0>, or
* 2. The MIT License, found at <http://opensource.org/licenses/MIT>.
* SPDX-License-Identifier: Apache-2.0 OR MIT.
*/
#include "spirv_cross_c.h"
#if SPIRV_CROSS_C_API_CPP
@@ -459,6 +466,9 @@ spvc_result spvc_compiler_options_set_uint(spvc_compiler_options options, spvc_c
case SPVC_COMPILER_OPTION_GLSL_EMIT_UNIFORM_BUFFER_AS_PLAIN_UNIFORMS:
options->glsl.emit_uniform_buffer_as_plain_uniforms = value != 0;
break;
case SPVC_COMPILER_OPTION_GLSL_FORCE_FLATTENED_IO_BLOCKS:
options->glsl.force_flattened_io_blocks = value != 0;
break;
#endif
#if SPIRV_CROSS_C_API_HLSL
@@ -489,6 +499,10 @@ spvc_result spvc_compiler_options_set_uint(spvc_compiler_options options, spvc_c
case SPVC_COMPILER_OPTION_HLSL_ENABLE_16BIT_TYPES:
options->hlsl.enable_16bit_types = value != 0;
break;
case SPVC_COMPILER_OPTION_HLSL_FLATTEN_MATRIX_VERTEX_INPUT_SEMANTICS:
options->hlsl.flatten_matrix_vertex_input_semantics = value != 0;
break;
#endif
#if SPIRV_CROSS_C_API_MSL
@@ -596,8 +610,8 @@ spvc_result spvc_compiler_options_set_uint(spvc_compiler_options options, spvc_c
options->msl.enable_base_index_zero = value != 0;
break;
case SPVC_COMPILER_OPTION_MSL_IOS_FRAMEBUFFER_FETCH_SUBPASS:
options->msl.ios_use_framebuffer_fetch_subpasses = value != 0;
case SPVC_COMPILER_OPTION_MSL_FRAMEBUFFER_FETCH_SUBPASS:
options->msl.use_framebuffer_fetch_subpasses = value != 0;
break;
case SPVC_COMPILER_OPTION_MSL_INVARIANT_FP_MATH:
@@ -635,6 +649,62 @@ spvc_result spvc_compiler_options_set_uint(spvc_compiler_options options, spvc_c
case SPVC_COMPILER_OPTION_MSL_ENABLE_CLIP_DISTANCE_USER_VARYING:
options->msl.enable_clip_distance_user_varying = value != 0;
break;
case SPVC_COMPILER_OPTION_MSL_MULTI_PATCH_WORKGROUP:
options->msl.multi_patch_workgroup = value != 0;
break;
case SPVC_COMPILER_OPTION_MSL_SHADER_INPUT_BUFFER_INDEX:
options->msl.shader_input_buffer_index = value;
break;
case SPVC_COMPILER_OPTION_MSL_SHADER_INDEX_BUFFER_INDEX:
options->msl.shader_index_buffer_index = value;
break;
case SPVC_COMPILER_OPTION_MSL_VERTEX_FOR_TESSELLATION:
options->msl.vertex_for_tessellation = value != 0;
break;
case SPVC_COMPILER_OPTION_MSL_VERTEX_INDEX_TYPE:
options->msl.vertex_index_type = static_cast<CompilerMSL::Options::IndexType>(value);
break;
case SPVC_COMPILER_OPTION_MSL_MULTIVIEW_LAYERED_RENDERING:
options->msl.multiview_layered_rendering = value != 0;
break;
case SPVC_COMPILER_OPTION_MSL_ARRAYED_SUBPASS_INPUT:
options->msl.arrayed_subpass_input = value != 0;
break;
case SPVC_COMPILER_OPTION_MSL_R32UI_LINEAR_TEXTURE_ALIGNMENT:
options->msl.r32ui_linear_texture_alignment = value;
break;
case SPVC_COMPILER_OPTION_MSL_R32UI_ALIGNMENT_CONSTANT_ID:
options->msl.r32ui_alignment_constant_id = value;
break;
case SPVC_COMPILER_OPTION_MSL_IOS_USE_SIMDGROUP_FUNCTIONS:
options->msl.ios_use_simdgroup_functions = value != 0;
break;
case SPVC_COMPILER_OPTION_MSL_EMULATE_SUBGROUPS:
options->msl.emulate_subgroups = value != 0;
break;
case SPVC_COMPILER_OPTION_MSL_FIXED_SUBGROUP_SIZE:
options->msl.fixed_subgroup_size = value;
break;
case SPVC_COMPILER_OPTION_MSL_FORCE_SAMPLE_RATE_SHADING:
options->msl.force_sample_rate_shading = value != 0;
break;
case SPVC_COMPILER_OPTION_MSL_IOS_SUPPORT_BASE_VERTEX_INSTANCE:
options->msl.ios_support_base_vertex_instance = value != 0;
break;
#endif
default:
@@ -1019,11 +1089,11 @@ spvc_result spvc_compiler_msl_add_vertex_attribute(spvc_compiler compiler, const
}
auto &msl = *static_cast<CompilerMSL *>(compiler->compiler.get());
MSLVertexAttr attr;
MSLShaderInput attr;
attr.location = va->location;
attr.format = static_cast<MSLVertexFormat>(va->format);
attr.format = static_cast<MSLShaderInputFormat>(va->format);
attr.builtin = static_cast<spv::BuiltIn>(va->builtin);
msl.add_msl_vertex_attribute(attr);
msl.add_msl_shader_input(attr);
return SPVC_SUCCESS;
#else
(void)va;
@@ -1032,6 +1102,30 @@ spvc_result spvc_compiler_msl_add_vertex_attribute(spvc_compiler compiler, const
#endif
}
spvc_result spvc_compiler_msl_add_shader_input(spvc_compiler compiler, const spvc_msl_shader_input *si)
{
#if SPIRV_CROSS_C_API_MSL
if (compiler->backend != SPVC_BACKEND_MSL)
{
compiler->context->report_error("MSL function used on a non-MSL backend.");
return SPVC_ERROR_INVALID_ARGUMENT;
}
auto &msl = *static_cast<CompilerMSL *>(compiler->compiler.get());
MSLShaderInput input;
input.location = si->location;
input.format = static_cast<MSLShaderInputFormat>(si->format);
input.builtin = static_cast<spv::BuiltIn>(si->builtin);
input.vecsize = si->vecsize;
msl.add_msl_shader_input(input);
return SPVC_SUCCESS;
#else
(void)si;
compiler->context->report_error("MSL function used on a non-MSL backend.");
return SPVC_ERROR_INVALID_ARGUMENT;
#endif
}
spvc_result spvc_compiler_msl_add_resource_binding(spvc_compiler compiler,
const spvc_msl_resource_binding *binding)
{
@@ -1139,7 +1233,7 @@ spvc_result spvc_compiler_msl_set_argument_buffer_device_address_space(spvc_comp
#endif
}
spvc_bool spvc_compiler_msl_is_vertex_attribute_used(spvc_compiler compiler, unsigned location)
spvc_bool spvc_compiler_msl_is_shader_input_used(spvc_compiler compiler, unsigned location)
{
#if SPIRV_CROSS_C_API_MSL
if (compiler->backend != SPVC_BACKEND_MSL)
@@ -1149,7 +1243,7 @@ spvc_bool spvc_compiler_msl_is_vertex_attribute_used(spvc_compiler compiler, uns
}
auto &msl = *static_cast<CompilerMSL *>(compiler->compiler.get());
return msl.is_msl_vertex_attribute_used(location) ? SPVC_TRUE : SPVC_FALSE;
return msl.is_msl_shader_input_used(location) ? SPVC_TRUE : SPVC_FALSE;
#else
(void)location;
compiler->context->report_error("MSL function used on a non-MSL backend.");
@@ -1157,6 +1251,11 @@ spvc_bool spvc_compiler_msl_is_vertex_attribute_used(spvc_compiler compiler, uns
#endif
}
spvc_bool spvc_compiler_msl_is_vertex_attribute_used(spvc_compiler compiler, unsigned location)
{
return spvc_compiler_msl_is_shader_input_used(compiler, location);
}
spvc_bool spvc_compiler_msl_is_resource_used(spvc_compiler compiler, SpvExecutionModel model, unsigned set,
unsigned binding)
{
@@ -1179,6 +1278,42 @@ spvc_bool spvc_compiler_msl_is_resource_used(spvc_compiler compiler, SpvExecutio
#endif
}
spvc_result spvc_compiler_msl_set_combined_sampler_suffix(spvc_compiler compiler, const char *suffix)
{
#if SPIRV_CROSS_C_API_MSL
if (compiler->backend != SPVC_BACKEND_MSL)
{
compiler->context->report_error("MSL function used on a non-MSL backend.");
return SPVC_ERROR_INVALID_ARGUMENT;
}
auto &msl = *static_cast<CompilerMSL *>(compiler->compiler.get());
msl.set_combined_sampler_suffix(suffix);
return SPVC_SUCCESS;
#else
(void)suffix;
compiler->context->report_error("MSL function used on a non-MSL backend.");
return SPVC_ERROR_INVALID_ARGUMENT;
#endif
}
const char *spvc_compiler_msl_get_combined_sampler_suffix(spvc_compiler compiler)
{
#if SPIRV_CROSS_C_API_MSL
if (compiler->backend != SPVC_BACKEND_MSL)
{
compiler->context->report_error("MSL function used on a non-MSL backend.");
return "";
}
auto &msl = *static_cast<CompilerMSL *>(compiler->compiler.get());
return msl.get_combined_sampler_suffix();
#else
compiler->context->report_error("MSL function used on a non-MSL backend.");
return "";
#endif
}
#if SPIRV_CROSS_C_API_MSL
static void spvc_convert_msl_sampler(MSLConstexprSampler &samp, const spvc_msl_constexpr_sampler *sampler)
{
@@ -2258,7 +2393,7 @@ void spvc_msl_vertex_attribute_init(spvc_msl_vertex_attribute *attr)
{
#if SPIRV_CROSS_C_API_MSL
// Crude, but works.
MSLVertexAttr attr_default;
MSLShaderInput attr_default;
attr->location = attr_default.location;
attr->format = static_cast<spvc_msl_vertex_format>(attr_default.format);
attr->builtin = static_cast<SpvBuiltIn>(attr_default.builtin);
@@ -2267,6 +2402,19 @@ void spvc_msl_vertex_attribute_init(spvc_msl_vertex_attribute *attr)
#endif
}
void spvc_msl_shader_input_init(spvc_msl_shader_input *input)
{
#if SPIRV_CROSS_C_API_MSL
MSLShaderInput input_default;
input->location = input_default.location;
input->format = static_cast<spvc_msl_shader_input_format>(input_default.format);
input->builtin = static_cast<SpvBuiltIn>(input_default.builtin);
input->vecsize = input_default.vecsize;
#else
memset(input, 0, sizeof(*input));
#endif
}
void spvc_msl_resource_binding_init(spvc_msl_resource_binding *binding)
{
#if SPIRV_CROSS_C_API_MSL
+80 -7
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Hans-Kristian Arntzen
* Copyright 2019-2021 Hans-Kristian Arntzen
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,6 +14,13 @@
* limitations under the License.
*/
/*
* At your option, you may choose to accept this material under either:
* 1. The Apache License, Version 2.0, found at <http://www.apache.org/licenses/LICENSE-2.0>, or
* 2. The MIT License, found at <http://opensource.org/licenses/MIT>.
* SPDX-License-Identifier: Apache-2.0 OR MIT.
*/
#ifndef SPIRV_CROSS_C_API_H
#define SPIRV_CROSS_C_API_H
@@ -33,7 +40,7 @@ extern "C" {
/* Bumped if ABI or API breaks backwards compatibility. */
#define SPVC_C_API_VERSION_MAJOR 0
/* Bumped if APIs or enumerations are added in a backwards compatible way. */
#define SPVC_C_API_VERSION_MINOR 34
#define SPVC_C_API_VERSION_MINOR 45
/* Bumped if internal implementation details change. */
#define SPVC_C_API_VERSION_PATCH 0
@@ -259,14 +266,32 @@ typedef enum spvc_msl_platform
} spvc_msl_platform;
/* Maps to C++ API. */
typedef enum spvc_msl_vertex_format
typedef enum spvc_msl_index_type
{
SPVC_MSL_VERTEX_FORMAT_OTHER = 0,
SPVC_MSL_VERTEX_FORMAT_UINT8 = 1,
SPVC_MSL_VERTEX_FORMAT_UINT16 = 2
} spvc_msl_vertex_format;
SPVC_MSL_INDEX_TYPE_NONE = 0,
SPVC_MSL_INDEX_TYPE_UINT16 = 1,
SPVC_MSL_INDEX_TYPE_UINT32 = 2,
SPVC_MSL_INDEX_TYPE_MAX_INT = 0x7fffffff
} spvc_msl_index_type;
/* Maps to C++ API. */
typedef enum spvc_msl_shader_input_format
{
SPVC_MSL_SHADER_INPUT_FORMAT_OTHER = 0,
SPVC_MSL_SHADER_INPUT_FORMAT_UINT8 = 1,
SPVC_MSL_SHADER_INPUT_FORMAT_UINT16 = 2,
SPVC_MSL_SHADER_INPUT_FORMAT_ANY16 = 3,
SPVC_MSL_SHADER_INPUT_FORMAT_ANY32 = 4,
/* Deprecated names. */
SPVC_MSL_VERTEX_FORMAT_OTHER = SPVC_MSL_SHADER_INPUT_FORMAT_OTHER,
SPVC_MSL_VERTEX_FORMAT_UINT8 = SPVC_MSL_SHADER_INPUT_FORMAT_UINT8,
SPVC_MSL_VERTEX_FORMAT_UINT16 = SPVC_MSL_SHADER_INPUT_FORMAT_UINT16,
SPVC_MSL_SHADER_INPUT_FORMAT_INT_MAX = 0x7fffffff
} spvc_msl_shader_input_format, spvc_msl_vertex_format;
/* Maps to C++ API. Deprecated; use spvc_msl_shader_input. */
typedef struct spvc_msl_vertex_attribute
{
unsigned location;
@@ -289,6 +314,20 @@ typedef struct spvc_msl_vertex_attribute
*/
SPVC_PUBLIC_API void spvc_msl_vertex_attribute_init(spvc_msl_vertex_attribute *attr);
/* Maps to C++ API. */
typedef struct spvc_msl_shader_input
{
unsigned location;
spvc_msl_vertex_format format;
SpvBuiltIn builtin;
unsigned vecsize;
} spvc_msl_shader_input;
/*
* Initializes the shader input struct.
*/
SPVC_PUBLIC_API void spvc_msl_shader_input_init(spvc_msl_shader_input *input);
/* Maps to C++ API. */
typedef struct spvc_msl_resource_binding
{
@@ -574,7 +613,11 @@ typedef enum spvc_compiler_option
SPVC_COMPILER_OPTION_MSL_DYNAMIC_OFFSETS_BUFFER_INDEX = 43 | SPVC_COMPILER_OPTION_MSL_BIT,
SPVC_COMPILER_OPTION_MSL_TEXTURE_1D_AS_2D = 44 | SPVC_COMPILER_OPTION_MSL_BIT,
SPVC_COMPILER_OPTION_MSL_ENABLE_BASE_INDEX_ZERO = 45 | SPVC_COMPILER_OPTION_MSL_BIT,
/* Obsolete. Use MSL_FRAMEBUFFER_FETCH_SUBPASS instead. */
SPVC_COMPILER_OPTION_MSL_IOS_FRAMEBUFFER_FETCH_SUBPASS = 46 | SPVC_COMPILER_OPTION_MSL_BIT,
SPVC_COMPILER_OPTION_MSL_FRAMEBUFFER_FETCH_SUBPASS = 46 | SPVC_COMPILER_OPTION_MSL_BIT,
SPVC_COMPILER_OPTION_MSL_INVARIANT_FP_MATH = 47 | SPVC_COMPILER_OPTION_MSL_BIT,
SPVC_COMPILER_OPTION_MSL_EMULATE_CUBEMAP_ARRAY = 48 | SPVC_COMPILER_OPTION_MSL_BIT,
SPVC_COMPILER_OPTION_MSL_ENABLE_DECORATION_BINDING = 49 | SPVC_COMPILER_OPTION_MSL_BIT,
@@ -596,6 +639,27 @@ typedef enum spvc_compiler_option
SPVC_COMPILER_OPTION_HLSL_ENABLE_16BIT_TYPES = 60 | SPVC_COMPILER_OPTION_HLSL_BIT,
SPVC_COMPILER_OPTION_MSL_MULTI_PATCH_WORKGROUP = 61 | SPVC_COMPILER_OPTION_MSL_BIT,
SPVC_COMPILER_OPTION_MSL_SHADER_INPUT_BUFFER_INDEX = 62 | SPVC_COMPILER_OPTION_MSL_BIT,
SPVC_COMPILER_OPTION_MSL_SHADER_INDEX_BUFFER_INDEX = 63 | SPVC_COMPILER_OPTION_MSL_BIT,
SPVC_COMPILER_OPTION_MSL_VERTEX_FOR_TESSELLATION = 64 | SPVC_COMPILER_OPTION_MSL_BIT,
SPVC_COMPILER_OPTION_MSL_VERTEX_INDEX_TYPE = 65 | SPVC_COMPILER_OPTION_MSL_BIT,
SPVC_COMPILER_OPTION_GLSL_FORCE_FLATTENED_IO_BLOCKS = 66 | SPVC_COMPILER_OPTION_GLSL_BIT,
SPVC_COMPILER_OPTION_MSL_MULTIVIEW_LAYERED_RENDERING = 67 | SPVC_COMPILER_OPTION_MSL_BIT,
SPVC_COMPILER_OPTION_MSL_ARRAYED_SUBPASS_INPUT = 68 | SPVC_COMPILER_OPTION_MSL_BIT,
SPVC_COMPILER_OPTION_MSL_R32UI_LINEAR_TEXTURE_ALIGNMENT = 69 | SPVC_COMPILER_OPTION_MSL_BIT,
SPVC_COMPILER_OPTION_MSL_R32UI_ALIGNMENT_CONSTANT_ID = 70 | SPVC_COMPILER_OPTION_MSL_BIT,
SPVC_COMPILER_OPTION_HLSL_FLATTEN_MATRIX_VERTEX_INPUT_SEMANTICS = 71 | SPVC_COMPILER_OPTION_HLSL_BIT,
SPVC_COMPILER_OPTION_MSL_IOS_USE_SIMDGROUP_FUNCTIONS = 72 | SPVC_COMPILER_OPTION_MSL_BIT,
SPVC_COMPILER_OPTION_MSL_EMULATE_SUBGROUPS = 73 | SPVC_COMPILER_OPTION_MSL_BIT,
SPVC_COMPILER_OPTION_MSL_FIXED_SUBGROUP_SIZE = 74 | SPVC_COMPILER_OPTION_MSL_BIT,
SPVC_COMPILER_OPTION_MSL_FORCE_SAMPLE_RATE_SHADING = 75 | SPVC_COMPILER_OPTION_MSL_BIT,
SPVC_COMPILER_OPTION_MSL_IOS_SUPPORT_BASE_VERTEX_INSTANCE = 76 | SPVC_COMPILER_OPTION_MSL_BIT,
SPVC_COMPILER_OPTION_INT_MAX = 0x7fffffff
} spvc_compiler_option;
@@ -698,9 +762,15 @@ SPVC_PUBLIC_API spvc_result spvc_compiler_msl_add_vertex_attribute(spvc_compiler
const spvc_msl_vertex_attribute *attrs);
SPVC_PUBLIC_API spvc_result spvc_compiler_msl_add_resource_binding(spvc_compiler compiler,
const spvc_msl_resource_binding *binding);
SPVC_PUBLIC_API spvc_result spvc_compiler_msl_add_shader_input(spvc_compiler compiler,
const spvc_msl_shader_input *input);
SPVC_PUBLIC_API spvc_result spvc_compiler_msl_add_discrete_descriptor_set(spvc_compiler compiler, unsigned desc_set);
SPVC_PUBLIC_API spvc_result spvc_compiler_msl_set_argument_buffer_device_address_space(spvc_compiler compiler, unsigned desc_set, spvc_bool device_address);
/* Obsolete, use is_shader_input_used. */
SPVC_PUBLIC_API spvc_bool spvc_compiler_msl_is_vertex_attribute_used(spvc_compiler compiler, unsigned location);
SPVC_PUBLIC_API spvc_bool spvc_compiler_msl_is_shader_input_used(spvc_compiler compiler, unsigned location);
SPVC_PUBLIC_API spvc_bool spvc_compiler_msl_is_resource_used(spvc_compiler compiler,
SpvExecutionModel model,
unsigned set,
@@ -718,6 +788,9 @@ SPVC_PUBLIC_API spvc_result spvc_compiler_msl_add_dynamic_buffer(spvc_compiler c
SPVC_PUBLIC_API spvc_result spvc_compiler_msl_add_inline_uniform_block(spvc_compiler compiler, unsigned desc_set, unsigned binding);
SPVC_PUBLIC_API spvc_result spvc_compiler_msl_set_combined_sampler_suffix(spvc_compiler compiler, const char *suffix);
SPVC_PUBLIC_API const char *spvc_compiler_msl_get_combined_sampler_suffix(spvc_compiler compiler);
/*
* Reflect resources.
* Maps almost 1:1 to C++ API.
@@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Hans-Kristian Arntzen
* Copyright 2019-2021 Hans-Kristian Arntzen
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,6 +14,13 @@
* limitations under the License.
*/
/*
* At your option, you may choose to accept this material under either:
* 1. The Apache License, Version 2.0, found at <http://www.apache.org/licenses/LICENSE-2.0>, or
* 2. The MIT License, found at <http://opensource.org/licenses/MIT>.
* SPDX-License-Identifier: Apache-2.0 OR MIT.
*/
#ifndef SPIRV_CROSS_CONTAINERS_HPP
#define SPIRV_CROSS_CONTAINERS_HPP
@@ -63,7 +70,8 @@ public:
private:
#if defined(_MSC_VER) && _MSC_VER < 1900
// MSVC 2013 workarounds, sigh ...
union {
union
{
char aligned_char[sizeof(T) * N];
double dummy_aligner;
} u;
@@ -211,6 +219,10 @@ public:
this->buffer_size = count;
}
SmallVector(std::initializer_list<T> init) SPIRV_CROSS_NOEXCEPT : SmallVector(init.begin(), init.end())
{
}
SmallVector(SmallVector &&other) SPIRV_CROSS_NOEXCEPT : SmallVector()
{
*this = std::move(other);
@@ -327,8 +339,9 @@ public:
size_t target_capacity = buffer_capacity;
if (target_capacity == 0)
target_capacity = 1;
if (target_capacity < N)
target_capacity = N;
// Weird parens works around macro issues on Windows if NOMINMAX is not used.
target_capacity = (std::max)(target_capacity, N);
// Need to ensure there is a POT value of target capacity which is larger than count,
// otherwise this will overflow.
@@ -1,5 +1,5 @@
/*
* Copyright 2015-2020 Arm Limited
* Copyright 2015-2021 Arm Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,6 +14,13 @@
* limitations under the License.
*/
/*
* At your option, you may choose to accept this material under either:
* 1. The Apache License, Version 2.0, found at <http://www.apache.org/licenses/LICENSE-2.0>, or
* 2. The MIT License, found at <http://opensource.org/licenses/MIT>.
* SPDX-License-Identifier: Apache-2.0 OR MIT.
*/
#ifndef SPIRV_CROSS_ERROR_HANDLING
#define SPIRV_CROSS_ERROR_HANDLING
@@ -1,5 +1,5 @@
/*
* Copyright 2018-2020 Arm Limited
* Copyright 2018-2021 Arm Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,6 +14,13 @@
* limitations under the License.
*/
/*
* At your option, you may choose to accept this material under either:
* 1. The Apache License, Version 2.0, found at <http://www.apache.org/licenses/LICENSE-2.0>, or
* 2. The MIT License, found at <http://opensource.org/licenses/MIT>.
* SPDX-License-Identifier: Apache-2.0 OR MIT.
*/
#include "spirv_cross_parsed_ir.hpp"
#include <algorithm>
#include <assert.h>
@@ -74,6 +81,8 @@ ParsedIR &ParsedIR::operator=(ParsedIR &&other) SPIRV_CROSS_NOEXCEPT
source = other.source;
loop_iteration_depth_hard = other.loop_iteration_depth_hard;
loop_iteration_depth_soft = other.loop_iteration_depth_soft;
meta_needing_name_fixup = std::move(other.meta_needing_name_fixup);
}
return *this;
}
@@ -106,6 +115,8 @@ ParsedIR &ParsedIR::operator=(const ParsedIR &other)
addressing_model = other.addressing_model;
memory_model = other.memory_model;
meta_needing_name_fixup = other.meta_needing_name_fixup;
// Very deliberate copying of IDs. There is no default copy constructor, nor a simple default constructor.
// Construct object first so we have the correct allocator set-up, then we can copy object into our new pool group.
ids.clear();
@@ -134,42 +145,151 @@ static bool is_alpha(char c)
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
}
static bool is_alphanumeric(char c)
static bool is_numeric(char c)
{
return is_alpha(c) || (c >= '0' && c <= '9');
return c >= '0' && c <= '9';
}
static string ensure_valid_identifier(const string &name, bool member)
static bool is_alphanumeric(char c)
{
return is_alpha(c) || is_numeric(c);
}
static bool is_valid_identifier(const string &name)
{
if (name.empty())
return true;
if (is_numeric(name[0]))
return false;
for (auto c : name)
if (!is_alphanumeric(c) && c != '_')
return false;
bool saw_underscore = false;
// Two underscores in a row is not a valid identifier either.
// Technically reserved, but it's easier to treat it as invalid.
for (auto c : name)
{
bool is_underscore = c == '_';
if (is_underscore && saw_underscore)
return false;
saw_underscore = is_underscore;
}
return true;
}
static bool is_reserved_prefix(const string &name)
{
// Generic reserved identifiers used by the implementation.
return name.compare(0, 3, "gl_", 3) == 0 ||
// Ignore this case for now, might rewrite internal code to always use spv prefix.
//name.compare(0, 11, "SPIRV_Cross", 11) == 0 ||
name.compare(0, 3, "spv", 3) == 0;
}
static bool is_reserved_identifier(const string &name, bool member, bool allow_reserved_prefixes)
{
if (!allow_reserved_prefixes && is_reserved_prefix(name))
return true;
if (member)
{
// Reserved member identifiers come in one form:
// _m[0-9]+$.
if (name.size() < 3)
return false;
if (name.compare(0, 2, "_m", 2) != 0)
return false;
size_t index = 2;
while (index < name.size() && is_numeric(name[index]))
index++;
return index == name.size();
}
else
{
// Reserved non-member identifiers come in two forms:
// _[0-9]+$, used for temporaries which map directly to a SPIR-V ID.
// _[0-9]+_, used for auxillary temporaries which derived from a SPIR-V ID.
if (name.size() < 2)
return false;
if (name[0] != '_' || !is_numeric(name[1]))
return false;
size_t index = 2;
while (index < name.size() && is_numeric(name[index]))
index++;
return index == name.size() || (index < name.size() && name[index] == '_');
}
}
bool ParsedIR::is_globally_reserved_identifier(std::string &str, bool allow_reserved_prefixes)
{
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))
return "_RESERVED_IDENTIFIER_FIXUP_" + name;
else
return "_RESERVED_IDENTIFIER_FIXUP" + name;
}
void ParsedIR::sanitize_underscores(std::string &str)
{
// Compact adjacent underscores to make it valid.
auto dst = str.begin();
auto src = dst;
bool saw_underscore = false;
while (src != str.end())
{
bool is_underscore = *src == '_';
if (saw_underscore && is_underscore)
{
src++;
}
else
{
if (dst != src)
*dst = *src;
dst++;
src++;
saw_underscore = is_underscore;
}
}
str.erase(dst, str.end());
}
static string ensure_valid_identifier(const string &name)
{
// Functions in glslangValidator are mangled with name(<mangled> stuff.
// Normally, we would never see '(' in any legal identifiers, so just strip them out.
auto str = name.substr(0, name.find('('));
for (uint32_t i = 0; i < str.size(); i++)
{
auto &c = str[i];
if (str.empty())
return str;
if (member)
{
// _m<num> variables are reserved by the internal implementation,
// otherwise, make sure the name is a valid identifier.
if (i == 0)
c = is_alpha(c) ? c : '_';
else if (i == 2 && str[0] == '_' && str[1] == 'm')
c = is_alpha(c) ? c : '_';
else
c = is_alphanumeric(c) ? c : '_';
}
else
{
// _<num> variables are reserved by the internal implementation,
// otherwise, make sure the name is a valid identifier.
if (i == 0 || (str[0] == '_' && i == 1))
c = is_alpha(c) ? c : '_';
else
c = is_alphanumeric(c) ? c : '_';
}
}
if (is_numeric(str[0]))
str[0] = '_';
for (auto &c : str)
if (!is_alphanumeric(c) && c != '_')
c = '_';
ParsedIR::sanitize_underscores(str);
return str;
}
@@ -195,35 +315,41 @@ const string &ParsedIR::get_member_name(TypeID id, uint32_t index) const
return empty_string;
}
void ParsedIR::sanitize_identifier(std::string &name, bool member, bool allow_reserved_prefixes)
{
if (!is_valid_identifier(name))
name = ensure_valid_identifier(name);
if (is_reserved_identifier(name, member, allow_reserved_prefixes))
name = make_unreserved_identifier(name);
}
void ParsedIR::fixup_reserved_names()
{
for (uint32_t id : meta_needing_name_fixup)
{
auto &m = meta[id];
sanitize_identifier(m.decoration.alias, false, false);
for (auto &memb : m.members)
sanitize_identifier(memb.alias, true, false);
}
meta_needing_name_fixup.clear();
}
void ParsedIR::set_name(ID id, const string &name)
{
auto &str = meta[id].decoration.alias;
str.clear();
if (name.empty())
return;
// Reserved for temporaries.
if (name[0] == '_' && name.size() >= 2 && isdigit(name[1]))
return;
str = ensure_valid_identifier(name, false);
auto &m = meta[id];
m.decoration.alias = name;
if (!is_valid_identifier(name) || is_reserved_identifier(name, false, false))
meta_needing_name_fixup.insert(id);
}
void ParsedIR::set_member_name(TypeID id, uint32_t index, const string &name)
{
meta[id].members.resize(max(meta[id].members.size(), size_t(index) + 1));
auto &str = meta[id].members[index].alias;
str.clear();
if (name.empty())
return;
// Reserved for unnamed members.
if (name[0] == '_' && name.size() >= 3 && name[1] == 'm' && isdigit(name[2]))
return;
str = ensure_valid_identifier(name, true);
auto &m = meta[id];
m.members.resize(max(meta[id].members.size(), size_t(index) + 1));
m.members[index].alias = name;
if (!is_valid_identifier(name) || is_reserved_identifier(name, true, false))
meta_needing_name_fixup.insert(id);
}
void ParsedIR::set_decoration_string(ID id, Decoration decoration, const string &argument)
@@ -274,6 +400,10 @@ void ParsedIR::set_decoration(ID id, Decoration decoration, uint32_t argument)
dec.xfb_stride = argument;
break;
case DecorationStream:
dec.stream = argument;
break;
case DecorationArrayStride:
dec.array_stride = argument;
break;
@@ -353,6 +483,10 @@ void ParsedIR::set_member_decoration(TypeID id, uint32_t index, Decoration decor
dec.xfb_stride = argument;
break;
case DecorationStream:
dec.stream = argument;
break;
case DecorationSpecId:
dec.spec_id = argument;
break;
@@ -404,6 +538,17 @@ void ParsedIR::mark_used_as_array_length(ID id)
}
}
Bitset ParsedIR::get_buffer_block_type_flags(const SPIRType &type) const
{
if (type.member_types.empty())
return {};
Bitset all_members_flags = get_member_decoration_bitset(type.self, 0);
for (uint32_t i = 1; i < uint32_t(type.member_types.size()); i++)
all_members_flags.merge_and(get_member_decoration_bitset(type.self, i));
return all_members_flags;
}
Bitset ParsedIR::get_buffer_block_flags(const SPIRVariable &var) const
{
auto &type = get<SPIRType>(var.basetype);
@@ -420,10 +565,7 @@ Bitset ParsedIR::get_buffer_block_flags(const SPIRVariable &var) const
if (type.member_types.empty())
return base_flags;
Bitset all_members_flags = get_member_decoration_bitset(type.self, 0);
for (uint32_t i = 1; i < uint32_t(type.member_types.size()); i++)
all_members_flags.merge_and(get_member_decoration_bitset(type.self, i));
auto all_members_flags = get_buffer_block_type_flags(type);
base_flags.merge_or(all_members_flags);
return base_flags;
}
@@ -470,6 +612,8 @@ uint32_t ParsedIR::get_decoration(ID id, Decoration decoration) const
return dec.xfb_buffer;
case DecorationXfbStride:
return dec.xfb_stride;
case DecorationStream:
return dec.stream;
case DecorationBinding:
return dec.binding;
case DecorationDescriptorSet:
@@ -542,6 +686,10 @@ void ParsedIR::unset_decoration(ID id, Decoration decoration)
dec.xfb_stride = 0;
break;
case DecorationStream:
dec.stream = 0;
break;
case DecorationBinding:
dec.binding = 0;
break;
@@ -616,6 +764,8 @@ uint32_t ParsedIR::get_member_decoration(TypeID id, uint32_t index, Decoration d
return dec.xfb_buffer;
case DecorationXfbStride:
return dec.xfb_stride;
case DecorationStream:
return dec.stream;
case DecorationSpecId:
return dec.spec_id;
case DecorationIndex:
@@ -712,6 +862,10 @@ void ParsedIR::unset_member_decoration(TypeID id, uint32_t index, Decoration dec
dec.xfb_stride = 0;
break;
case DecorationStream:
dec.stream = 0;
break;
case DecorationSpecId:
dec.spec_id = 0;
break;
@@ -1,5 +1,5 @@
/*
* Copyright 2018-2020 Arm Limited
* Copyright 2018-2021 Arm Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,6 +14,13 @@
* limitations under the License.
*/
/*
* At your option, you may choose to accept this material under either:
* 1. The Apache License, Version 2.0, found at <http://www.apache.org/licenses/LICENSE-2.0>, or
* 2. The MIT License, found at <http://opensource.org/licenses/MIT>.
* SPDX-License-Identifier: Apache-2.0 OR MIT.
*/
#ifndef SPIRV_CROSS_PARSED_IR_HPP
#define SPIRV_CROSS_PARSED_IR_HPP
@@ -139,6 +146,7 @@ public:
void mark_used_as_array_length(ID id);
uint32_t increase_bound_by(uint32_t count);
Bitset get_buffer_block_flags(const SPIRVariable &var) const;
Bitset get_buffer_block_type_flags(const SPIRType &type) const;
void add_typed_id(Types type, ID id);
void remove_typed_id(Types type, ID id);
@@ -208,6 +216,14 @@ public:
void make_constant_null(uint32_t id, uint32_t type, bool add_to_typed_id_set);
void fixup_reserved_names();
static void sanitize_underscores(std::string &str);
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)
@@ -225,6 +241,8 @@ private:
mutable uint32_t loop_iteration_depth_soft = 0;
std::string empty_string;
Bitset cleared_bitset;
std::unordered_set<uint32_t> meta_needing_name_fixup;
};
} // namespace SPIRV_CROSS_NAMESPACE
@@ -1,5 +1,5 @@
/*
* Copyright 2015-2020 Arm Limited
* Copyright 2015-2021 Arm Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,6 +14,13 @@
* limitations under the License.
*/
/*
* At your option, you may choose to accept this material under either:
* 1. The Apache License, Version 2.0, found at <http://www.apache.org/licenses/LICENSE-2.0>, or
* 2. The MIT License, found at <http://opensource.org/licenses/MIT>.
* SPDX-License-Identifier: Apache-2.0 OR MIT.
*/
#include "spirv_cross_util.hpp"
#include "spirv_common.hpp"
@@ -1,5 +1,5 @@
/*
* Copyright 2015-2020 Arm Limited
* Copyright 2015-2021 Arm Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,6 +14,13 @@
* limitations under the License.
*/
/*
* At your option, you may choose to accept this material under either:
* 1. The Apache License, Version 2.0, found at <http://www.apache.org/licenses/LICENSE-2.0>, or
* 2. The MIT License, found at <http://opensource.org/licenses/MIT>.
* SPDX-License-Identifier: Apache-2.0 OR MIT.
*/
#ifndef SPIRV_CROSS_UTIL_HPP
#define SPIRV_CROSS_UTIL_HPP
File diff suppressed because it is too large Load Diff
+182 -30
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2015-2020 Arm Limited
* Copyright 2015-2021 Arm Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,6 +14,13 @@
* limitations under the License.
*/
/*
* At your option, you may choose to accept this material under either:
* 1. The Apache License, Version 2.0, found at <http://www.apache.org/licenses/LICENSE-2.0>, or
* 2. The MIT License, found at <http://opensource.org/licenses/MIT>.
* SPDX-License-Identifier: Apache-2.0 OR MIT.
*/
#ifndef SPIRV_CROSS_GLSL_HPP
#define SPIRV_CROSS_GLSL_HPP
@@ -57,7 +64,8 @@ enum AccessChainFlagBits
ACCESS_CHAIN_CHAIN_ONLY_BIT = 1 << 1,
ACCESS_CHAIN_PTR_CHAIN_BIT = 1 << 2,
ACCESS_CHAIN_SKIP_REGISTER_EXPRESSION_READ_BIT = 1 << 3,
ACCESS_CHAIN_LITERAL_MSB_FORCE_ID = 1 << 4
ACCESS_CHAIN_LITERAL_MSB_FORCE_ID = 1 << 4,
ACCESS_CHAIN_FLATTEN_ALL_MEMBERS_BIT = 1 << 5
};
typedef uint32_t AccessChainFlags;
@@ -120,6 +128,10 @@ public:
// which would otherwise be uninitialized will now be initialized to 0 instead.
bool force_zero_initialized_variables = false;
// In GLSL, force use of I/O block flattening, similar to
// what happens on legacy GLSL targets for blocks and structs.
bool force_flattened_io_blocks = false;
enum Precision
{
DontCare,
@@ -128,14 +140,16 @@ public:
Highp
};
struct
struct VertexOptions
{
// GLSL: In vertex shaders, rewrite [0, w] depth (Vulkan/D3D style) to [-w, w] depth (GL style).
// MSL: In vertex shaders, rewrite [-w, w] depth (GL style) to [0, w] depth.
// HLSL: In vertex shaders, rewrite [-w, w] depth (GL style) to [0, w] depth.
// "Vertex-like shader" here is any shader stage that can write BuiltInPosition.
// GLSL: In vertex-like shaders, rewrite [0, w] depth (Vulkan/D3D style) to [-w, w] depth (GL style).
// MSL: In vertex-like shaders, rewrite [-w, w] depth (GL style) to [0, w] depth.
// HLSL: In vertex-like shaders, rewrite [-w, w] depth (GL style) to [0, w] depth.
bool fixup_clipspace = false;
// Inverts gl_Position.y or equivalent.
// In vertex-like shaders, inverts gl_Position.y or equivalent.
bool flip_vert_y = false;
// GLSL only, for HLSL version of this option, see CompilerHLSL.
@@ -145,7 +159,7 @@ public:
bool support_nonzero_base_instance = true;
} vertex;
struct
struct FragmentOptions
{
// Add precision mediump float in ES targets when emitting GLES source.
// Add precision highp int in ES targets when emitting GLES source.
@@ -237,6 +251,82 @@ public:
bool variable_is_depth_or_compare(VariableID id) const;
protected:
struct ShaderSubgroupSupportHelper
{
// lower enum value = greater priority
enum Candidate
{
KHR_shader_subgroup_ballot,
KHR_shader_subgroup_basic,
KHR_shader_subgroup_vote,
NV_gpu_shader_5,
NV_shader_thread_group,
NV_shader_thread_shuffle,
ARB_shader_ballot,
ARB_shader_group_vote,
AMD_gcn_shader,
CandidateCount
};
static const char *get_extension_name(Candidate c);
static SmallVector<std::string> get_extra_required_extension_names(Candidate c);
static const char *get_extra_required_extension_predicate(Candidate c);
enum Feature
{
SubgroupMask = 0,
SubgroupSize = 1,
SubgroupInvocationID = 2,
SubgroupID = 3,
NumSubgroups = 4,
SubgroupBroadcast_First = 5,
SubgroupBallotFindLSB_MSB = 6,
SubgroupAll_Any_AllEqualBool = 7,
SubgroupAllEqualT = 8,
SubgroupElect = 9,
SubgroupBarrier = 10,
SubgroupMemBarrier = 11,
SubgroupBallot = 12,
SubgroupInverseBallot_InclBitCount_ExclBitCout = 13,
SubgroupBallotBitExtract = 14,
SubgroupBallotBitCount = 15,
FeatureCount
};
using FeatureMask = uint32_t;
static_assert(sizeof(FeatureMask) * 8u >= FeatureCount, "Mask type needs more bits.");
using CandidateVector = SmallVector<Candidate, CandidateCount>;
using FeatureVector = SmallVector<Feature>;
static FeatureVector get_feature_dependencies(Feature feature);
static FeatureMask get_feature_dependency_mask(Feature feature);
static bool can_feature_be_implemented_without_extensions(Feature feature);
static Candidate get_KHR_extension_for_feature(Feature feature);
struct Result
{
Result();
uint32_t weights[CandidateCount];
};
void request_feature(Feature feature);
bool is_feature_requested(Feature feature) const;
Result resolve() const;
static CandidateVector get_candidates_for_feature(Feature ft, const Result &r);
private:
static CandidateVector get_candidates_for_feature(Feature ft);
static FeatureMask build_mask(const SmallVector<Feature> &features);
FeatureMask feature_mask = 0;
};
// TODO remove this function when all subgroup ops are supported (or make it always return true)
static bool is_supported_subgroup_op_in_opengl(spv::Op op);
void reset();
void emit_function(SPIRFunction &func, const Bitset &return_flags);
@@ -267,9 +357,11 @@ protected:
void build_workgroup_size(SmallVector<std::string> &arguments, const SpecializationConstant &x,
const SpecializationConstant &y, const SpecializationConstant &z);
void request_subgroup_feature(ShaderSubgroupSupportHelper::Feature feature);
virtual void emit_sampled_image_op(uint32_t result_type, uint32_t result_id, uint32_t image_id, uint32_t samp_id);
virtual void emit_texture_op(const Instruction &i);
virtual std::string to_texture_op(const Instruction &i, bool *forward,
virtual void emit_texture_op(const Instruction &i, bool sparse);
virtual std::string to_texture_op(const Instruction &i, bool sparse, bool *forward,
SmallVector<uint32_t> &inherited_expressions);
virtual void emit_subgroup_op(const Instruction &i);
virtual std::string type_to_glsl(const SPIRType &type, uint32_t id = 0);
@@ -284,14 +376,42 @@ protected:
virtual void emit_fixup();
virtual std::string variable_decl(const SPIRType &type, const std::string &name, uint32_t id = 0);
virtual std::string to_func_call_arg(const SPIRFunction::Parameter &arg, uint32_t id);
virtual std::string to_function_name(VariableID img, const SPIRType &imgtype, bool is_fetch, bool is_gather,
bool is_proj, bool has_array_offsets, bool has_offset, bool has_grad,
bool has_dref, uint32_t lod, uint32_t minlod);
virtual std::string to_function_args(VariableID img, const SPIRType &imgtype, bool is_fetch, bool is_gather,
bool is_proj, uint32_t coord, uint32_t coord_components, uint32_t dref,
uint32_t grad_x, uint32_t grad_y, uint32_t lod, uint32_t coffset,
uint32_t offset, uint32_t bias, uint32_t comp, uint32_t sample,
uint32_t minlod, bool *p_forward);
struct TextureFunctionBaseArguments
{
// GCC 4.8 workarounds, it doesn't understand '{}' constructor here, use explicit default constructor.
TextureFunctionBaseArguments() = default;
VariableID img = 0;
const SPIRType *imgtype = nullptr;
bool is_fetch = false, is_gather = false, is_proj = false;
};
struct TextureFunctionNameArguments
{
// GCC 4.8 workarounds, it doesn't understand '{}' constructor here, use explicit default constructor.
TextureFunctionNameArguments() = default;
TextureFunctionBaseArguments base;
bool has_array_offsets = false, has_offset = false, has_grad = false;
bool has_dref = false, is_sparse_feedback = false, has_min_lod = false;
uint32_t lod = 0;
};
virtual std::string to_function_name(const TextureFunctionNameArguments &args);
struct TextureFunctionArguments
{
// GCC 4.8 workarounds, it doesn't understand '{}' constructor here, use explicit default constructor.
TextureFunctionArguments() = default;
TextureFunctionBaseArguments base;
uint32_t coord = 0, coord_components = 0, dref = 0;
uint32_t grad_x = 0, grad_y = 0, lod = 0, coffset = 0, offset = 0;
uint32_t bias = 0, component = 0, sample = 0, sparse_texel = 0, min_lod = 0;
bool nonuniform_expression = false;
};
virtual std::string to_function_args(const TextureFunctionArguments &args, bool *p_forward);
void emit_sparse_feedback_temporaries(uint32_t result_type_id, uint32_t id, uint32_t &feedback_id,
uint32_t &texel_id);
uint32_t get_sparse_feedback_texel_id(uint32_t id) const;
virtual void emit_buffer_block(const SPIRVariable &type);
virtual void emit_push_constant_block(const SPIRVariable &var);
virtual void emit_uniform(const SPIRVariable &var);
@@ -441,25 +561,34 @@ protected:
bool supports_extensions = false;
bool supports_empty_struct = false;
bool array_is_value_type = true;
bool buffer_offset_array_is_value_type = true;
bool comparison_image_samples_scalar = false;
bool native_pointers = false;
bool support_small_type_sampling_result = false;
bool support_case_fallthrough = true;
bool use_array_constructor = false;
bool needs_row_major_load_workaround = false;
bool support_pointer_to_pointer = false;
} backend;
void emit_struct(SPIRType &type);
void emit_resources();
void emit_extension_workarounds(spv::ExecutionModel model);
void emit_buffer_block_native(const SPIRVariable &var);
void emit_buffer_reference_block(SPIRType &type, bool forward_declaration);
void emit_buffer_block_legacy(const SPIRVariable &var);
void emit_buffer_block_flattened(const SPIRVariable &type);
void fixup_implicit_builtin_block_names();
void emit_declared_builtin_block(spv::StorageClass storage, spv::ExecutionModel model);
bool should_force_emit_builtin_block(spv::StorageClass storage);
void emit_push_constant_block_vulkan(const SPIRVariable &var);
void emit_push_constant_block_glsl(const SPIRVariable &var);
void emit_interface_block(const SPIRVariable &type);
void emit_flattened_io_block(const SPIRVariable &var, const char *qual);
void emit_flattened_io_block_struct(const std::string &basename, const SPIRType &type, const char *qual,
const SmallVector<uint32_t> &indices);
void emit_flattened_io_block_member(const std::string &basename, const SPIRType &type, const char *qual,
const SmallVector<uint32_t> &indices);
void emit_block_chain(SPIRBlock &block);
void emit_hoisted_temporaries(SmallVector<std::pair<TypeID, ID>> &temporaries);
std::string constant_value_macro_name(uint32_t id);
@@ -522,6 +651,7 @@ protected:
void emit_unary_op(uint32_t result_type, uint32_t result_id, uint32_t op0, const char *op);
bool expression_is_forwarded(uint32_t id) const;
bool expression_suppresses_usage_tracking(uint32_t id) const;
bool expression_read_implies_multiple_reads(uint32_t id) const;
SPIRExpression &emit_op(uint32_t result_type, uint32_t result_id, const std::string &rhs, bool forward_rhs,
bool suppress_usage_tracking = false);
@@ -531,6 +661,9 @@ protected:
std::string access_chain_internal(uint32_t base, const uint32_t *indices, uint32_t count, AccessChainFlags flags,
AccessChainMeta *meta);
virtual void prepare_access_chain_for_scalar_access(std::string &expr, const SPIRType &type,
spv::StorageClass storage, bool &is_packed);
std::string access_chain(uint32_t base, const uint32_t *indices, uint32_t count, const SPIRType &target_type,
AccessChainMeta *meta = nullptr, bool ptr_chain = false);
@@ -559,7 +692,7 @@ protected:
SPIRExpression &emit_uninitialized_temporary_expression(uint32_t type, uint32_t id);
void append_global_func_args(const SPIRFunction &func, uint32_t index, SmallVector<std::string> &arglist);
std::string to_expression(uint32_t id, bool register_expression_read = true);
std::string to_composite_constructor_expression(uint32_t id);
std::string to_composite_constructor_expression(uint32_t id, bool uses_buffer_offset);
std::string to_rerolled_array_expression(const std::string &expr, const SPIRType &type);
std::string to_enclosed_expression(uint32_t id, bool register_expression_read = true);
std::string to_unpacked_expression(uint32_t id, bool register_expression_read = true);
@@ -569,15 +702,20 @@ protected:
std::string to_pointer_expression(uint32_t id, bool register_expression_read = true);
std::string to_enclosed_pointer_expression(uint32_t id, bool register_expression_read = true);
std::string to_extract_component_expression(uint32_t id, uint32_t index);
std::string to_extract_constant_composite_expression(uint32_t result_type, const SPIRConstant &c,
const uint32_t *chain, uint32_t length);
std::string enclose_expression(const std::string &expr);
std::string dereference_expression(const SPIRType &expression_type, const std::string &expr);
std::string address_of_expression(const std::string &expr);
void strip_enclosed_expression(std::string &expr);
std::string to_member_name(const SPIRType &type, uint32_t index);
virtual std::string to_member_reference(uint32_t base, const SPIRType &type, uint32_t index, bool ptr_chain);
std::string to_multi_member_reference(const SPIRType &type, const SmallVector<uint32_t> &indices);
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);
@@ -624,8 +762,7 @@ protected:
void replace_fragment_output(SPIRVariable &var);
void replace_fragment_outputs();
bool check_explicit_lod_allowed(uint32_t lod);
std::string legacy_tex_op(const std::string &op, const SPIRType &imgtype, uint32_t lod, uint32_t id);
std::string legacy_tex_op(const std::string &op, const SPIRType &imgtype, uint32_t id);
uint32_t indent = 0;
@@ -635,11 +772,16 @@ protected:
std::unordered_set<uint32_t> flushed_phi_variables;
std::unordered_set<uint32_t> flattened_buffer_blocks;
std::unordered_set<uint32_t> flattened_structs;
std::unordered_map<uint32_t, bool> flattened_structs;
std::string load_flattened_struct(SPIRVariable &var);
std::string to_flattened_struct_member(const SPIRVariable &var, uint32_t index);
void store_flattened_struct(SPIRVariable &var, uint32_t value);
ShaderSubgroupSupportHelper shader_subgroup_supporter;
std::string load_flattened_struct(const std::string &basename, const SPIRType &type);
std::string to_flattened_struct_member(const std::string &basename, const SPIRType &type, uint32_t index);
void store_flattened_struct(uint32_t lhs_id, uint32_t value);
void store_flattened_struct(const std::string &basename, uint32_t rhs, const SPIRType &type,
const SmallVector<uint32_t> &indices);
std::string to_flattened_access_chain_expression(uint32_t id);
// Usage tracking. If a temporary is used more than once, use the temporary instead to
// avoid AST explosion when SPIRV is generated with pure SSA and doesn't write stuff to variables.
@@ -654,6 +796,10 @@ protected:
// Currently used by NMin/Max/Clamp implementations.
std::unordered_map<uint32_t, uint32_t> extra_sub_expressions;
SmallVector<TypeID> workaround_ubo_load_overload_types;
void request_workaround_wrapper_overload(TypeID id);
void rewrite_load_for_wrapped_row_major(std::string &expr, TypeID loaded_type, ID ptr);
uint32_t statement_count = 0;
inline bool is_legacy() const
@@ -671,6 +817,12 @@ protected:
return !options.es && options.version < 130;
}
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);
void register_impure_function_call();
@@ -712,8 +864,6 @@ protected:
virtual void declare_undefined_values();
static std::string sanitize_underscores(const std::string &str);
bool can_use_io_location(spv::StorageClass storage, bool block);
const Instruction *get_next_instruction_in_block(const Instruction &instr);
static uint32_t mask_relevant_memory_semantics(uint32_t semantics);
@@ -726,16 +876,18 @@ protected:
// Builtins in GLSL are always specific signedness, but the SPIR-V can declare them
// as either unsigned or signed.
// Sometimes we will need to automatically perform bitcasts on load and store to make this work.
virtual void bitcast_to_builtin_store(uint32_t target_id, std::string &expr, const SPIRType &expr_type);
virtual void bitcast_from_builtin_load(uint32_t source_id, std::string &expr, const SPIRType &expr_type);
// Sometimes we will need to automatically perform casts on load and store to make this work.
virtual void cast_to_builtin_store(uint32_t target_id, std::string &expr, const SPIRType &expr_type);
virtual void cast_from_builtin_load(uint32_t source_id, std::string &expr, const SPIRType &expr_type);
void unroll_array_from_complex_load(uint32_t target_id, uint32_t source_id, std::string &expr);
bool unroll_array_to_complex_store(uint32_t target_id, uint32_t source_id);
void convert_non_uniform_expression(const SPIRType &type, std::string &expr);
void handle_store_to_invariant_variable(uint32_t store_id, uint32_t value_id);
void disallow_forwarding_in_expression_chain(const SPIRExpression &expr);
bool expression_is_constant_null(uint32_t id) const;
bool expression_is_non_value_type_array(uint32_t ptr);
virtual void emit_store_statement(uint32_t lhs_expression, uint32_t rhs_expression);
uint32_t get_integer_width_for_instruction(const Instruction &instr) const;
File diff suppressed because it is too large Load Diff
+21 -3
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2016-2020 Robert Konrad
* Copyright 2016-2021 Robert Konrad
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,6 +14,13 @@
* limitations under the License.
*/
/*
* At your option, you may choose to accept this material under either:
* 1. The Apache License, Version 2.0, found at <http://www.apache.org/licenses/LICENSE-2.0>, or
* 2. The MIT License, found at <http://opensource.org/licenses/MIT>.
* SPDX-License-Identifier: Apache-2.0 OR MIT.
*/
#ifndef SPIRV_HLSL_HPP
#define SPIRV_HLSL_HPP
@@ -124,6 +131,12 @@ public:
// Uses half/int16_t/uint16_t instead of min16* types.
// Also adds support for 16-bit load-store from (RW)ByteAddressBuffer.
bool enable_16bit_types = false;
// If matrices are used as IO variables, flatten the attribute declaration to use
// TEXCOORD{N,N+1,N+2,...} rather than TEXCOORDN_{0,1,2,3}.
// If add_vertex_attribute_remap is used and this feature is used,
// the semantic name will be queried once per active location.
bool flatten_matrix_vertex_input_semantics = false;
};
explicit CompilerHLSL(std::vector<uint32_t> spirv_)
@@ -209,7 +222,7 @@ private:
void emit_interface_block_in_struct(const SPIRVariable &type, std::unordered_set<uint32_t> &active_locations);
void emit_builtin_inputs_in_struct();
void emit_builtin_outputs_in_struct();
void emit_texture_op(const Instruction &i) override;
void emit_texture_op(const Instruction &i, bool sparse) override;
void emit_instruction(const Instruction &instruction) override;
void emit_glsl_op(uint32_t result_type, uint32_t result_id, uint32_t op, const uint32_t *args,
uint32_t count) override;
@@ -231,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);
@@ -291,7 +305,8 @@ private:
} required_texture_size_variants;
void require_texture_query_variant(uint32_t var_id);
void emit_texture_size_variants(uint64_t variant_mask, const char *vecsize_qualifier, bool uav, const char *type_qualifier);
void emit_texture_size_variants(uint64_t variant_mask, const char *vecsize_qualifier, bool uav,
const char *type_qualifier);
enum TextureQueryVariantDim
{
@@ -351,6 +366,9 @@ private:
void remap_hlsl_resource_binding(HLSLBindingFlagBits type, uint32_t &desc_set, uint32_t &binding);
std::unordered_set<SetBindingPair, InternalHasher> force_uav_buffer_bindings;
// Returns true for BuiltInSampleMask because gl_SampleMask[] is an array in SPIR-V, but SV_Coverage is a scalar in HLSL.
bool builtin_translates_to_nonarray(spv::BuiltIn builtin) const override;
};
} // namespace SPIRV_CROSS_NAMESPACE
File diff suppressed because it is too large Load Diff
+191 -41
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2016-2020 The Brenwill Workshop Ltd.
* Copyright 2016-2021 The Brenwill Workshop Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,6 +14,13 @@
* limitations under the License.
*/
/*
* At your option, you may choose to accept this material under either:
* 1. The Apache License, Version 2.0, found at <http://www.apache.org/licenses/LICENSE-2.0>, or
* 2. The MIT License, found at <http://opensource.org/licenses/MIT>.
* SPDX-License-Identifier: Apache-2.0 OR MIT.
*/
#ifndef SPIRV_CROSS_MSL_HPP
#define SPIRV_CROSS_MSL_HPP
@@ -27,29 +34,44 @@
namespace SPIRV_CROSS_NAMESPACE
{
// Indicates the format of the vertex attribute. Currently limited to specifying
// if the attribute is an 8-bit unsigned integer, 16-bit unsigned integer, or
// Indicates the format of a shader input. Currently limited to specifying
// if the input is an 8-bit unsigned integer, 16-bit unsigned integer, or
// some other format.
enum MSLVertexFormat
enum MSLShaderInputFormat
{
MSL_VERTEX_FORMAT_OTHER = 0,
MSL_VERTEX_FORMAT_UINT8 = 1,
MSL_VERTEX_FORMAT_UINT16 = 2,
MSL_VERTEX_FORMAT_INT_MAX = 0x7fffffff
MSL_SHADER_INPUT_FORMAT_OTHER = 0,
MSL_SHADER_INPUT_FORMAT_UINT8 = 1,
MSL_SHADER_INPUT_FORMAT_UINT16 = 2,
MSL_SHADER_INPUT_FORMAT_ANY16 = 3,
MSL_SHADER_INPUT_FORMAT_ANY32 = 4,
// Deprecated aliases.
MSL_VERTEX_FORMAT_OTHER = MSL_SHADER_INPUT_FORMAT_OTHER,
MSL_VERTEX_FORMAT_UINT8 = MSL_SHADER_INPUT_FORMAT_UINT8,
MSL_VERTEX_FORMAT_UINT16 = MSL_SHADER_INPUT_FORMAT_UINT16,
MSL_SHADER_INPUT_FORMAT_INT_MAX = 0x7fffffff
};
// Defines MSL characteristics of a vertex attribute at a particular location.
// Defines MSL characteristics of an input variable at a particular location.
// After compilation, it is possible to query whether or not this location was used.
struct MSLVertexAttr
// If vecsize is nonzero, it must be greater than or equal to the vecsize declared in the shader,
// or behavior is undefined.
struct MSLShaderInput
{
uint32_t location = 0;
MSLVertexFormat format = MSL_VERTEX_FORMAT_OTHER;
MSLShaderInputFormat format = MSL_SHADER_INPUT_FORMAT_OTHER;
spv::BuiltIn builtin = spv::BuiltInMax;
uint32_t vecsize = 0;
};
// Matches the binding index of a MSL resource for a binding within a descriptor set.
// Taken together, the stage, desc_set and binding combine to form a reference to a resource
// descriptor used in a particular shading stage.
// descriptor used in a particular shading stage. The count field indicates the number of
// resources consumed by this binding, if the binding represents an array of resources.
// If the resource array is a run-time-sized array, which are legal in GLSL or SPIR-V, this value
// will be used to declare the array size in MSL, which does not support run-time-sized arrays.
// For resources that are not held in a run-time-sized array, the count field does not need to be populated.
// If using MSL 2.0 argument buffers, the descriptor set is not marked as a discrete descriptor set,
// and (for iOS only) the resource is not a storage image (sampled != 2), the binding reference we
// remap to will become an [[id(N)]] attribute within the "descriptor set" argument buffer structure.
@@ -60,6 +82,7 @@ struct MSLResourceBinding
spv::ExecutionModel stage = spv::ExecutionModelMax;
uint32_t desc_set = 0;
uint32_t binding = 0;
uint32_t count = 0;
uint32_t msl_buffer = 0;
uint32_t msl_texture = 0;
uint32_t msl_sampler = 0;
@@ -238,6 +261,9 @@ static const uint32_t kArgumentBufferBinding = ~(3u);
static const uint32_t kMaxArgumentBuffers = 8;
// The arbitrary maximum for the nesting of array of array copies.
static const uint32_t kArrayCopyMultidimMax = 6;
// Decompiles SPIR-V to Metal Shading Language
class CompilerMSL : public CompilerGLSL
{
@@ -254,6 +280,8 @@ public:
Platform platform = macOS;
uint32_t msl_version = make_msl_version(1, 2);
uint32_t texel_buffer_texture_width = 4096; // Width of 2D Metal textures used as 1D texel buffers
uint32_t r32ui_linear_texture_alignment = 4;
uint32_t r32ui_alignment_constant_id = 65535;
uint32_t swizzle_buffer_index = 30;
uint32_t indirect_params_buffer_index = 29;
uint32_t shader_output_buffer_index = 28;
@@ -262,9 +290,15 @@ public:
uint32_t buffer_size_buffer_index = 25;
uint32_t view_mask_buffer_index = 24;
uint32_t dynamic_offsets_buffer_index = 23;
uint32_t shader_input_buffer_index = 22;
uint32_t shader_index_buffer_index = 21;
uint32_t shader_input_wg_index = 0;
uint32_t device_index = 0;
uint32_t enable_frag_output_mask = 0xffffffff;
// Metal doesn't allow setting a fixed sample mask directly in the pipeline.
// We can evade this restriction by ANDing the internal sample_mask output
// of the shader with the additional fixed sample mask.
uint32_t additional_fixed_sample_mask = 0xffffffff;
bool enable_point_size_builtin = true;
bool enable_frag_depth_builtin = true;
bool enable_frag_stencil_ref_builtin = true;
@@ -273,6 +307,7 @@ public:
bool swizzle_texture_samples = false;
bool tess_domain_origin_lower_left = false;
bool multiview = false;
bool multiview_layered_rendering = true;
bool view_index_from_device_index = false;
bool dispatch_base = false;
bool texture_1D_as_2D = false;
@@ -292,7 +327,7 @@ public:
bool ios_support_base_vertex_instance = false;
// Use Metal's native frame-buffer fetch API for subpass inputs.
bool ios_use_framebuffer_fetch_subpasses = false;
bool use_framebuffer_fetch_subpasses = false;
// Enables use of "fma" intrinsic for invariant float math
bool invariant_float_math = false;
@@ -320,6 +355,64 @@ public:
// can be read in subsequent stages.
bool enable_clip_distance_user_varying = true;
// In a tessellation control shader, assume that more than one patch can be processed in a
// single workgroup. This requires changes to the way the InvocationId and PrimitiveId
// builtins are processed, but should result in more efficient usage of the GPU.
bool multi_patch_workgroup = false;
// If set, a vertex shader will be compiled as part of a tessellation pipeline.
// It will be translated as a compute kernel, so it can use the global invocation ID
// to index the output buffer.
bool vertex_for_tessellation = false;
// Assume that SubpassData images have multiple layers. Layered input attachments
// are addressed relative to the Layer output from the vertex pipeline. This option
// has no effect with multiview, since all input attachments are assumed to be layered
// and will be addressed using the current ViewIndex.
bool arrayed_subpass_input = false;
// Whether to use SIMD-group or quadgroup functions to implement group nnon-uniform
// operations. Some GPUs on iOS do not support the SIMD-group functions, only the
// quadgroup functions.
bool ios_use_simdgroup_functions = false;
// If set, the subgroup size will be assumed to be one, and subgroup-related
// builtins and operations will be emitted accordingly. This mode is intended to
// be used by MoltenVK on hardware/software configurations which do not provide
// sufficient support for subgroups.
bool emulate_subgroups = false;
// If nonzero, a fixed subgroup size to assume. Metal, similarly to VK_EXT_subgroup_size_control,
// allows the SIMD-group size (aka thread execution width) to vary depending on
// register usage and requirements. In certain circumstances--for example, a pipeline
// in MoltenVK without VK_PIPELINE_SHADER_STAGE_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT_EXT--
// this is undesirable. This fixes the value of the SubgroupSize builtin, instead of
// mapping it to the Metal builtin [[thread_execution_width]]. If the thread
// execution width is reduced, the extra invocations will appear to be inactive.
// If zero, the SubgroupSize will be allowed to vary, and the builtin will be mapped
// to the Metal [[thread_execution_width]] builtin.
uint32_t fixed_subgroup_size = 0;
enum class IndexType
{
None = 0,
UInt16 = 1,
UInt32 = 2
};
// The type of index in the index buffer, if present. For a compute shader, Metal
// requires specifying the indexing at pipeline creation, rather than at draw time
// as with graphics pipelines. This means we must create three different pipelines,
// for no indexing, 16-bit indices, and 32-bit indices. Each requires different
// handling for the gl_VertexIndex builtin. We may as well, then, create three
// different shaders for these three scenarios.
IndexType vertex_index_type = IndexType::None;
// If set, a dummy [[sample_id]] input is added to a fragment shader if none is present.
// This will force the shader to run at sample rate, assuming Metal does not optimize
// the extra threads away.
bool force_sample_rate_shading = false;
bool is_ios() const
{
return platform == iOS;
@@ -419,11 +512,10 @@ public:
explicit CompilerMSL(const ParsedIR &ir);
explicit CompilerMSL(ParsedIR &&ir);
// attr is a vertex attribute binding used to match
// vertex content locations to MSL attributes. If vertex attributes are provided,
// is_msl_vertex_attribute_used() will return true after calling ::compile() if
// the location was used by the MSL code.
void add_msl_vertex_attribute(const MSLVertexAttr &attr);
// input is a shader input description used to fix up shader input variables.
// If shader inputs are provided, is_msl_shader_input_used() will return true after
// calling ::compile() if the location was used by the MSL code.
void add_msl_shader_input(const MSLShaderInput &input);
// resource is a resource binding to indicate the MSL buffer,
// texture or sampler index to use for a particular SPIR-V description set
@@ -455,8 +547,15 @@ public:
// constant. Opt-in to this behavior here on a per set basis.
void set_argument_buffer_device_address_space(uint32_t desc_set, bool device_storage);
// Query after compilation is done. This allows you to check if a location or set/binding combination was used by the shader.
bool is_msl_vertex_attribute_used(uint32_t location);
// Query after compilation is done. This allows you to check if an input location was used by the shader.
bool is_msl_shader_input_used(uint32_t location);
// If not using add_msl_shader_input, it's possible
// that certain builtin attributes need to be automatically assigned locations.
// This is typical for tessellation builtin inputs such as tess levels, gl_Position, etc.
// This returns k_unknown_location if the location was explicitly assigned with
// add_msl_shader_input or the builtin is not used, otherwise returns N in [[attribute(N)]].
uint32_t get_automatic_builtin_input_location(spv::BuiltIn builtin) const;
// NOTE: Only resources which are remapped using add_msl_resource_binding will be reported here.
// Constexpr samplers are always assumed to be emitted.
@@ -475,6 +574,7 @@ public:
// Same as get_automatic_msl_resource_binding, but should only be used for combined image samplers, in which case the
// sampler's binding is returned instead. For any other resource type, -1 is returned.
// Secondary bindings are also used for the auxillary image atomic buffer.
uint32_t get_automatic_msl_resource_binding_secondary(uint32_t id) const;
// Same as get_automatic_msl_resource_binding, but should only be used for combined image samplers for multiplanar images,
@@ -505,6 +605,9 @@ public:
// to use for a particular location. The default is 4 if number of components is not overridden.
void set_fragment_output_components(uint32_t location, uint32_t components);
void set_combined_sampler_suffix(const char *suffix);
const char *get_combined_sampler_suffix() const;
protected:
// An enum of SPIR-V functions that are implemented in additional
// source code that is added to the shader if necessary.
@@ -544,12 +647,20 @@ protected:
SPVFuncImplTextureSwizzle,
SPVFuncImplGatherSwizzle,
SPVFuncImplGatherCompareSwizzle,
SPVFuncImplSubgroupBroadcast,
SPVFuncImplSubgroupBroadcastFirst,
SPVFuncImplSubgroupBallot,
SPVFuncImplSubgroupBallotBitExtract,
SPVFuncImplSubgroupBallotFindLSB,
SPVFuncImplSubgroupBallotFindMSB,
SPVFuncImplSubgroupBallotBitCount,
SPVFuncImplSubgroupAllEqual,
SPVFuncImplSubgroupShuffle,
SPVFuncImplSubgroupShuffleXor,
SPVFuncImplSubgroupShuffleUp,
SPVFuncImplSubgroupShuffleDown,
SPVFuncImplQuadBroadcast,
SPVFuncImplQuadSwap,
SPVFuncImplReflectScalar,
SPVFuncImplRefractScalar,
SPVFuncImplFaceForwardScalar,
@@ -573,13 +684,11 @@ protected:
SPVFuncImplConvertYCbCrBT601,
SPVFuncImplConvertYCbCrBT2020,
SPVFuncImplDynamicImageSampler,
SPVFuncImplArrayCopyMultidimMax = 6
};
// If the underlying resource has been used for comparison then duplicate loads of that resource must be too
// Use Metal's native frame-buffer fetch API for subpass inputs.
void emit_texture_op(const Instruction &i) override;
void emit_texture_op(const Instruction &i, bool sparse) override;
void emit_binary_unord_op(uint32_t result_type, uint32_t result_id, uint32_t op0, uint32_t op1, const char *op);
void emit_instruction(const Instruction &instr) override;
void emit_glsl_op(uint32_t result_type, uint32_t result_id, uint32_t op, const uint32_t *args,
@@ -590,7 +699,7 @@ protected:
void emit_function_prototype(SPIRFunction &func, const Bitset &return_flags) 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_subgroup_op(const Instruction &i) override;
std::string to_texture_op(const Instruction &i, bool *forward,
std::string to_texture_op(const Instruction &i, bool sparse, bool *forward,
SmallVector<uint32_t> &inherited_expressions) override;
void emit_fixup() override;
std::string to_struct_member(const SPIRType &type, uint32_t member_type_id, uint32_t index,
@@ -610,17 +719,12 @@ protected:
std::string variable_decl(const SPIRType &type, const std::string &name, uint32_t id = 0) override;
std::string image_type_glsl(const SPIRType &type, uint32_t id = 0) override;
std::string sampler_type(const SPIRType &type);
std::string sampler_type(const SPIRType &type, uint32_t id);
std::string builtin_to_glsl(spv::BuiltIn builtin, spv::StorageClass storage) override;
std::string to_func_call_arg(const SPIRFunction::Parameter &arg, uint32_t id) override;
std::string to_name(uint32_t id, bool allow_alias = true) const override;
std::string to_function_name(VariableID img, const SPIRType &imgtype, bool is_fetch, bool is_gather, bool is_proj,
bool has_array_offsets, bool has_offset, bool has_grad, bool has_dref, uint32_t lod,
uint32_t minlod) override;
std::string to_function_args(VariableID img, const SPIRType &imgtype, bool is_fetch, bool is_gather, bool is_proj,
uint32_t coord, uint32_t coord_components, uint32_t dref, uint32_t grad_x,
uint32_t grad_y, uint32_t lod, uint32_t coffset, uint32_t offset, uint32_t bias,
uint32_t comp, uint32_t sample, uint32_t minlod, bool *p_forward) override;
std::string to_function_name(const TextureFunctionNameArguments &args) override;
std::string to_function_args(const TextureFunctionArguments &args, bool *p_forward) override;
std::string to_initializer_expression(const SPIRVariable &var) override;
std::string to_zero_initialized_expression(uint32_t type_id) override;
@@ -639,6 +743,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();
@@ -689,9 +799,9 @@ protected:
void fix_up_interface_member_indices(spv::StorageClass storage, uint32_t ib_type_id);
void mark_location_as_used_by_shader(uint32_t location, spv::StorageClass storage);
void mark_location_as_used_by_shader(uint32_t location, const SPIRType &type, spv::StorageClass storage);
uint32_t ensure_correct_builtin_type(uint32_t type_id, spv::BuiltIn builtin);
uint32_t ensure_correct_attribute_type(uint32_t type_id, uint32_t location, uint32_t num_components = 0);
uint32_t ensure_correct_input_type(uint32_t type_id, uint32_t location, uint32_t num_components = 0);
void emit_custom_templates();
void emit_custom_functions();
@@ -699,6 +809,7 @@ protected:
void emit_specialization_constants_and_structs();
void emit_interface_block(uint32_t ib_var_id);
bool maybe_emit_array_assignment(uint32_t id_lhs, uint32_t id_rhs);
uint32_t get_resource_array_size(uint32_t id) const;
void fix_up_shader_inputs_outputs();
@@ -713,6 +824,8 @@ protected:
std::string to_sampler_expression(uint32_t id);
std::string to_swizzle_expression(uint32_t id);
std::string to_buffer_size_expression(uint32_t id);
bool is_sample_rate() const;
bool is_direct_input_builtin(spv::BuiltIn builtin);
std::string builtin_qualifier(spv::BuiltIn builtin);
std::string builtin_type_decl(spv::BuiltIn builtin, uint32_t id = 0);
std::string built_in_func_arg(spv::BuiltIn builtin, bool prefix_comma);
@@ -720,7 +833,11 @@ protected:
std::string argument_decl(const SPIRFunction::Parameter &arg);
std::string round_fp_tex_coords(std::string tex_coords, bool coord_is_fp);
uint32_t get_metal_resource_index(SPIRVariable &var, SPIRType::BaseType basetype, uint32_t plane = 0);
uint32_t get_ordered_member_location(uint32_t type_id, uint32_t index, uint32_t *comp = nullptr);
uint32_t get_member_location(uint32_t type_id, uint32_t index, uint32_t *comp = nullptr) const;
uint32_t get_or_allocate_builtin_input_member_location(spv::BuiltIn builtin,
uint32_t type_id, uint32_t index, uint32_t *comp = nullptr);
uint32_t get_physical_tess_level_array_size(spv::BuiltIn builtin) const;
// MSL packing rules. These compute the effective packing rules as observed by the MSL compiler in the MSL output.
// These values can change depending on various extended decorations which control packing rules.
@@ -735,7 +852,13 @@ protected:
uint32_t get_declared_struct_member_matrix_stride_msl(const SPIRType &struct_type, uint32_t index) const;
uint32_t get_declared_struct_member_alignment_msl(const SPIRType &struct_type, uint32_t index) const;
uint32_t get_declared_input_size_msl(const SPIRType &struct_type, uint32_t index) const;
uint32_t get_declared_input_array_stride_msl(const SPIRType &struct_type, uint32_t index) const;
uint32_t get_declared_input_matrix_stride_msl(const SPIRType &struct_type, uint32_t index) const;
uint32_t get_declared_input_alignment_msl(const SPIRType &struct_type, uint32_t index) const;
const SPIRType &get_physical_member_type(const SPIRType &struct_type, uint32_t index) const;
SPIRType get_presumed_input_type(const SPIRType &struct_type, uint32_t index) const;
uint32_t get_declared_struct_size_msl(const SPIRType &struct_type, bool ignore_alignment = false,
bool ignore_padding = false) const;
@@ -754,6 +877,8 @@ protected:
SPIRType &get_patch_stage_in_struct_type();
SPIRType &get_patch_stage_out_struct_type();
std::string get_tess_factor_struct_name();
SPIRType &get_uint_type();
uint32_t get_uint_type_id();
void emit_atomic_func_op(uint32_t result_type, uint32_t result_id, const char *op, uint32_t mem_order_1,
uint32_t mem_order_2, bool has_mem_order_2, uint32_t op0, uint32_t op1 = 0,
bool op1_is_pointer = false, bool op1_is_literal = false, uint32_t op2 = 0);
@@ -768,6 +893,7 @@ protected:
void emit_entry_point_declarations() override;
uint32_t builtin_frag_coord_id = 0;
uint32_t builtin_sample_id_id = 0;
uint32_t builtin_sample_mask_id = 0;
uint32_t builtin_vertex_idx_id = 0;
uint32_t builtin_base_vertex_id = 0;
uint32_t builtin_instance_idx_id = 0;
@@ -779,17 +905,26 @@ protected:
uint32_t builtin_subgroup_invocation_id_id = 0;
uint32_t builtin_subgroup_size_id = 0;
uint32_t builtin_dispatch_base_id = 0;
uint32_t builtin_stage_input_size_id = 0;
uint32_t builtin_local_invocation_index_id = 0;
uint32_t builtin_workgroup_size_id = 0;
uint32_t swizzle_buffer_id = 0;
uint32_t buffer_size_buffer_id = 0;
uint32_t view_mask_buffer_id = 0;
uint32_t dynamic_offsets_buffer_id = 0;
uint32_t uint_type_id = 0;
void bitcast_to_builtin_store(uint32_t target_id, std::string &expr, const SPIRType &expr_type) override;
void bitcast_from_builtin_load(uint32_t source_id, std::string &expr, const SPIRType &expr_type) override;
bool does_shader_write_sample_mask = false;
void cast_to_builtin_store(uint32_t target_id, std::string &expr, const SPIRType &expr_type) override;
void cast_from_builtin_load(uint32_t source_id, std::string &expr, const SPIRType &expr_type) override;
void emit_store_statement(uint32_t lhs_expression, uint32_t rhs_expression) override;
void analyze_sampled_image_usage();
void prepare_access_chain_for_scalar_access(std::string &expr, const SPIRType &type, spv::StorageClass storage,
bool &is_packed) override;
void fix_up_interpolant_access_chain(const uint32_t *ops, uint32_t length);
bool emit_tessellation_access_chain(const uint32_t *ops, uint32_t length);
bool emit_tessellation_io_load(uint32_t result_type, uint32_t id, uint32_t ptr);
bool is_out_of_bounds_tessellation_level(uint32_t id_lhs);
@@ -802,15 +937,18 @@ protected:
Options msl_options;
std::set<SPVFuncImpl> spv_function_implementations;
std::unordered_map<uint32_t, MSLVertexAttr> vtx_attrs_by_location;
std::unordered_map<uint32_t, MSLVertexAttr> vtx_attrs_by_builtin;
std::unordered_set<uint32_t> vtx_attrs_in_use;
// Must be ordered to ensure declarations are in a specific order.
std::map<uint32_t, MSLShaderInput> inputs_by_location;
std::unordered_map<uint32_t, MSLShaderInput> inputs_by_builtin;
std::unordered_set<uint32_t> location_inputs_in_use;
std::unordered_map<uint32_t, uint32_t> fragment_output_components;
std::unordered_map<uint32_t, uint32_t> builtin_to_automatic_input_location;
std::set<std::string> pragma_lines;
std::set<std::string> typedef_lines;
SmallVector<uint32_t> vars_needing_early_declaration;
std::unordered_map<StageSetBinding, std::pair<MSLResourceBinding, bool>, InternalHasher> resource_bindings;
uint32_t type_to_location_count(const SPIRType &type) const;
uint32_t next_metal_resource_index_buffer = 0;
uint32_t next_metal_resource_index_texture = 0;
@@ -847,6 +985,8 @@ protected:
bool used_swizzle_buffer = false;
bool added_builtin_tess_level = false;
bool needs_subgroup_invocation_id = false;
bool needs_subgroup_size = false;
bool needs_sample_id = false;
std::string qual_pos_var_name;
std::string stage_in_var_name = "in";
std::string stage_out_var_name = "out";
@@ -857,9 +997,11 @@ protected:
std::string buffer_size_name_suffix = "BufferSize";
std::string plane_name_suffix = "Plane";
std::string input_wg_var_name = "gl_in";
std::string input_buffer_var_name = "spvIn";
std::string output_buffer_var_name = "spvOut";
std::string patch_output_buffer_var_name = "spvPatchOut";
std::string tess_factor_buffer_var_name = "spvTessLevel";
std::string index_buffer_var_name = "spvIndices";
spv::Op previous_instruction_opcode = spv::OpNop;
// Must be ordered since declaration is in a specific order.
@@ -870,6 +1012,7 @@ protected:
std::unordered_set<uint32_t> buffers_requiring_array_length;
SmallVector<uint32_t> buffer_arrays;
std::unordered_set<uint32_t> atomic_image_vars; // Emulate texture2D atomic operations
std::unordered_set<uint32_t> pull_model_inputs;
// Must be ordered since array is in a specific order.
std::map<SetBindingPair, std::pair<uint32_t, uint32_t>> buffers_requiring_dynamic_offset;
@@ -886,7 +1029,9 @@ protected:
bool descriptor_set_is_argument_buffer(uint32_t desc_set) const;
uint32_t get_target_components_for_fragment_location(uint32_t location) const;
uint32_t build_extended_vector_type(uint32_t type_id, uint32_t components);
uint32_t build_extended_vector_type(uint32_t type_id, uint32_t components,
SPIRType::BaseType basetype = SPIRType::Unknown);
uint32_t build_msl_interpolant_type(uint32_t type_id, bool is_noperspective);
bool suppress_missing_prototypes = false;
@@ -895,6 +1040,9 @@ protected:
void activate_argument_buffer_resources();
bool type_is_msl_framebuffer_fetch(const SPIRType &type) const;
bool type_is_pointer(const SPIRType &type) const;
bool type_is_pointer_to_pointer(const SPIRType &type) const;
bool is_supported_argument_buffer_type(const SPIRType &type) const;
// OpcodeHandler that handles several MSL preprocessing operations.
struct OpCodePreprocessor : OpcodeHandler
@@ -915,6 +1063,8 @@ protected:
bool uses_atomics = false;
bool uses_resource_write = false;
bool needs_subgroup_invocation_id = false;
bool needs_subgroup_size = false;
bool needs_sample_id = false;
};
// OpcodeHandler that scans for uses of sampled images
+35 -5
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2018-2020 Arm Limited
* Copyright 2018-2021 Arm Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,6 +14,13 @@
* limitations under the License.
*/
/*
* At your option, you may choose to accept this material under either:
* 1. The Apache License, Version 2.0, found at <http://www.apache.org/licenses/LICENSE-2.0>, or
* 2. The MIT License, found at <http://opensource.org/licenses/MIT>.
* SPDX-License-Identifier: Apache-2.0 OR MIT.
*/
#include "spirv_parser.hpp"
#include <assert.h>
@@ -133,6 +140,8 @@ void Parser::parse()
SPIRV_CROSS_THROW("Function was not terminated.");
if (current_block)
SPIRV_CROSS_THROW("Block was not terminated.");
if (ir.default_entry_point == 0)
SPIRV_CROSS_THROW("There is no entry point in the SPIR-V module.");
}
const uint32_t *Parser::stream(const Instruction &instr) const
@@ -623,10 +632,15 @@ void Parser::parse(const Instruction &instruction)
{
uint32_t id = ops[0];
auto &base = get<SPIRType>(ops[2]);
// Very rarely, we might receive a FunctionPrototype here.
// We won't be able to compile it, but we shouldn't crash when parsing.
// We should be able to reflect.
auto *base = maybe_get<SPIRType>(ops[2]);
auto &ptrbase = set<SPIRType>(id);
ptrbase = base;
if (base)
ptrbase = *base;
ptrbase.pointer = true;
ptrbase.pointer_depth++;
ptrbase.storage = static_cast<StorageClass>(ops[1]);
@@ -634,7 +648,7 @@ void Parser::parse(const Instruction &instruction)
if (ptrbase.storage == StorageClassAtomicCounter)
ptrbase.basetype = SPIRType::AtomicCounter;
if (base.forward_pointer)
if (base && base->forward_pointer)
forward_pointer_fixups.push_back({ id, ops[2] });
ptrbase.parent_type = ops[2];
@@ -715,7 +729,7 @@ void Parser::parse(const Instruction &instruction)
break;
}
case OpTypeRayQueryProvisionalKHR:
case OpTypeRayQueryKHR:
{
uint32_t id = ops[0];
auto &type = set<SPIRType>(id);
@@ -980,6 +994,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)
+8 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2018-2020 Arm Limited
* Copyright 2018-2021 Arm Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,6 +14,13 @@
* limitations under the License.
*/
/*
* At your option, you may choose to accept this material under either:
* 1. The Apache License, Version 2.0, found at <http://www.apache.org/licenses/LICENSE-2.0>, or
* 2. The MIT License, found at <http://opensource.org/licenses/MIT>.
* SPDX-License-Identifier: Apache-2.0 OR MIT.
*/
#ifndef SPIRV_CROSS_PARSER_HPP
#define SPIRV_CROSS_PARSER_HPP
+11 -8
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2018-2020 Bradley Austin Davis
* Copyright 2018-2021 Bradley Austin Davis
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,6 +14,13 @@
* limitations under the License.
*/
/*
* At your option, you may choose to accept this material under either:
* 1. The Apache License, Version 2.0, found at <http://www.apache.org/licenses/LICENSE-2.0>, or
* 2. The MIT License, found at <http://opensource.org/licenses/MIT>.
* SPDX-License-Identifier: Apache-2.0 OR MIT.
*/
#include "spirv_reflect.hpp"
#include "spirv_glsl.hpp"
#include <iomanip>
@@ -267,7 +274,6 @@ string CompilerReflection::compile()
json_stream = std::make_shared<simple_json::Stream>();
json_stream->set_current_locale_radix_character(current_locale_radix_character);
json_stream->begin_json_object();
fixup_type_alias();
reorder_type_alias();
emit_entry_points();
emit_types();
@@ -305,8 +311,8 @@ void CompilerReflection::emit_types()
else if (type_is_reference(type))
{
if (!naturally_emit_type(this->get<SPIRType>(type.parent_type)) &&
find(physical_pointee_types.begin(), physical_pointee_types.end(),
type.parent_type) == physical_pointee_types.end())
find(physical_pointee_types.begin(), physical_pointee_types.end(), type.parent_type) ==
physical_pointee_types.end())
{
physical_pointee_types.push_back(type.parent_type);
}
@@ -327,9 +333,6 @@ void CompilerReflection::emit_type(uint32_t type_id, bool &emitted_open_tag)
auto &type = get<SPIRType>(type_id);
auto name = type_to_glsl(type);
if (type.type_alias != TypeID(0))
return;
if (!emitted_open_tag)
{
json_stream->emit_json_key_object("types");
@@ -651,7 +654,7 @@ void CompilerReflection::emit_specialization_constants()
return;
json_stream->emit_json_key_array("specialization_constants");
for (const auto spec_const : specialization_constants)
for (const auto &spec_const : specialization_constants)
{
auto &c = get<SPIRConstant>(spec_const.id);
auto type = get<SPIRType>(c.constant_type);
+8 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2018-2020 Bradley Austin Davis
* Copyright 2018-2021 Bradley Austin Davis
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,6 +14,13 @@
* limitations under the License.
*/
/*
* At your option, you may choose to accept this material under either:
* 1. The Apache License, Version 2.0, found at <http://www.apache.org/licenses/LICENSE-2.0>, or
* 2. The MIT License, found at <http://opensource.org/licenses/MIT>.
* SPDX-License-Identifier: Apache-2.0 OR MIT.
*/
#ifndef SPIRV_CROSS_REFLECT_HPP
#define SPIRV_CROSS_REFLECT_HPP