DxilValidation.h 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // //
  3. // DxilValidation.h //
  4. // Copyright (C) Microsoft Corporation. All rights reserved. //
  5. // This file is distributed under the University of Illinois Open Source //
  6. // License. See LICENSE.TXT for details. //
  7. // //
  8. // This file provides support for validating DXIL shaders. //
  9. // //
  10. ///////////////////////////////////////////////////////////////////////////////
  11. #pragma once
  12. #include <memory>
  13. #include "dxc/Support/Global.h"
  14. #include "dxc/HLSL/DxilConstants.h"
  15. namespace llvm {
  16. class Module;
  17. class LLVMContext;
  18. class raw_ostream;
  19. class DiagnosticPrinter;
  20. class DiagnosticInfo;
  21. }
  22. namespace hlsl {
  23. /* <py::lines('VALRULE-ENUM')>hctdb_instrhelp.get_valrule_enum()</py>*/
  24. // VALRULE-ENUM:BEGIN
  25. // Known validation rules
  26. enum class ValidationRule : unsigned {
  27. // Bitcode
  28. BitcodeValid, // TODO - Module must be bitcode-valid
  29. // Container
  30. ContainerPartInvalid, // DXIL Container must not contain unknown parts
  31. ContainerPartMatches, // DXIL Container Parts must match Module
  32. ContainerPartMissing, // DXIL Container requires certain parts, corresponding to module
  33. ContainerPartRepeated, // DXIL Container must have only one of each part type
  34. ContainerRootSignatureIncompatible, // Root Signature in DXIL Container must be compatible with shader
  35. // Declaration
  36. DeclDxilFnExtern, // External function must be a DXIL function
  37. DeclDxilNsReserved, // The DXIL reserved prefixes must only be used by built-in functions and types
  38. DeclFnAttribute, // Functions should only contain known function attributes
  39. DeclFnFlattenParam, // Function parameters must not use struct types
  40. DeclFnIsCalled, // Functions can only be used by call instructions
  41. DeclNotUsedExternal, // External declaration should not be used
  42. DeclUsedExternalFunction, // External function must be used
  43. DeclUsedInternal, // Internal declaration must be used
  44. // Instruction
  45. InstrAllowed, // Instructions must be of an allowed type
  46. InstrAttributeAtVertexNoInterpolation, // Attribute %0 must have nointerpolation mode in order to use GetAttributeAtVertex function.
  47. InstrBarrierModeForNonCS, // sync in a non-Compute Shader must only sync UAV (sync_uglobal)
  48. InstrBarrierModeNoMemory, // sync must include some form of memory barrier - _u (UAV) and/or _g (Thread Group Shared Memory). Only _t (thread group sync) is optional.
  49. InstrBarrierModeUselessUGroup, // sync can't specify both _ugroup and _uglobal. If both are needed, just specify _uglobal.
  50. InstrBufferUpdateCounterOnUAV, // BufferUpdateCounter valid only on UAV
  51. InstrCBufferClassForCBufferHandle, // Expect Cbuffer for CBufferLoad handle
  52. InstrCBufferOutOfBound, // Cbuffer access out of bound
  53. InstrCallOload, // Call to DXIL intrinsic must match overload signature
  54. InstrCannotPullPosition, // pull-model evaluation of position disallowed
  55. InstrCheckAccessFullyMapped, // CheckAccessFullyMapped should only used on resource status
  56. InstrCoordinateCountForRawTypedBuf, // raw/typed buffer don't need 2 coordinates
  57. InstrCoordinateCountForStructBuf, // structured buffer require 2 coordinates
  58. InstrCreateHandleImmRangeID, // Local resource must map to global resource.
  59. InstrDxilStructUser, // Dxil struct types should only used by ExtractValue
  60. InstrDxilStructUserOutOfBound, // Index out of bound when extract value from dxil struct types
  61. InstrEvalInterpolationMode, // Interpolation mode on %0 used with eval_* instruction must be linear, linear_centroid, linear_noperspective, linear_noperspective_centroid, linear_sample or linear_noperspective_sample
  62. InstrExtractValue, // ExtractValue should only be used on dxil struct types and cmpxchg
  63. InstrFailToResloveTGSMPointer, // TGSM pointers must originate from an unambiguous TGSM global variable.
  64. InstrHandleNotFromCreateHandle, // Resource handle should returned by createHandle
  65. InstrImmBiasForSampleB, // bias amount for sample_b must be in the range [%0,%1], but %2 was specified as an immediate
  66. InstrInBoundsAccess, // Access to out-of-bounds memory is disallowed
  67. InstrMinPrecisionNotPrecise, // Instructions marked precise may not refer to minprecision values
  68. InstrMinPrecisonBitCast, // Bitcast on minprecison types is not allowed
  69. InstrMipLevelForGetDimension, // Use mip level on buffer when GetDimensions
  70. InstrMipOnUAVLoad, // uav load don't support mipLevel/sampleIndex
  71. InstrNoGenericPtrAddrSpaceCast, // Address space cast between pointer types must have one part to be generic address space
  72. InstrNoIDivByZero, // No signed integer division by zero
  73. InstrNoIndefiniteAcos, // No indefinite arccosine
  74. InstrNoIndefiniteAsin, // No indefinite arcsine
  75. InstrNoIndefiniteDsxy, // No indefinite derivative calculation
  76. InstrNoIndefiniteLog, // No indefinite logarithm
  77. InstrNoReadingUninitialized, // Instructions should not read uninitialized value
  78. InstrNoUDivByZero, // No unsigned integer division by zero
  79. InstrOffsetOnUAVLoad, // uav load don't support offset
  80. InstrOload, // DXIL intrinsic overload must be valid
  81. InstrOnlyOneAllocConsume, // RWStructuredBuffers may increment or decrement their counters, but not both.
  82. InstrOpCodeReserved, // Instructions must not reference reserved opcodes
  83. InstrOpConst, // DXIL intrinsic requires an immediate constant operand
  84. InstrOpConstRange, // Constant values must be in-range for operation
  85. InstrOperandRange, // DXIL intrinsic operand must be within defined range
  86. InstrPtrBitCast, // Pointer type bitcast must be have same size
  87. InstrResourceClassForLoad, // load can only run on UAV/SRV resource
  88. InstrResourceClassForSamplerGather, // sample, lod and gather should on srv resource.
  89. InstrResourceClassForUAVStore, // store should on uav resource.
  90. InstrResourceCoordinateMiss, // coord uninitialized
  91. InstrResourceCoordinateTooMany, // out of bound coord must be undef
  92. InstrResourceKindForBufferLoadStore, // buffer load/store only works on Raw/Typed/StructuredBuffer
  93. InstrResourceKindForCalcLOD, // lod requires resource declared as texture1D/2D/3D/Cube/CubeArray/1DArray/2DArray
  94. InstrResourceKindForGather, // gather requires resource declared as texture/2D/Cube/2DArray/CubeArray
  95. InstrResourceKindForGetDim, // Invalid resource kind on GetDimensions
  96. InstrResourceKindForSample, // sample/_l/_d requires resource declared as texture1D/2D/3D/Cube/1DArray/2DArray/CubeArray
  97. InstrResourceKindForSampleC, // samplec requires resource declared as texture1D/2D/Cube/1DArray/2DArray/CubeArray
  98. InstrResourceKindForTextureLoad, // texture load only works on Texture1D/1DArray/2D/2DArray/3D/MS2D/MS2DArray
  99. InstrResourceKindForTextureStore, // texture store only works on Texture1D/1DArray/2D/2DArray/3D
  100. InstrResourceOffsetMiss, // offset uninitialized
  101. InstrResourceOffsetTooMany, // out of bound offset must be undef
  102. InstrSampleCompType, // sample_* instructions require resource to be declared to return UNORM, SNORM or FLOAT.
  103. InstrSampleIndexForLoad2DMS, // load on Texture2DMS/2DMSArray require sampleIndex
  104. InstrSamplerModeForLOD, // lod instruction requires sampler declared in default mode
  105. InstrSamplerModeForSample, // sample/_l/_d/_cl_s/gather instruction requires sampler declared in default mode
  106. InstrSamplerModeForSampleC, // sample_c_*/gather_c instructions require sampler declared in comparison mode
  107. InstrStatus, // Resource status should only used by CheckAccessFullyMapped
  108. InstrStructBitCast, // Bitcast on struct types is not allowed
  109. InstrTGSMRaceCond, // Race condition writing to shared memory detected, consider making this write conditional
  110. InstrTextureOffset, // offset texture instructions must take offset which can resolve to integer literal in the range -8 to 7
  111. InstrUndefResultForGetDimension, // GetDimensions used undef dimension %0 on %1
  112. InstrWriteMaskForTypedUAVStore, // store on typed uav must write to all four components of the UAV
  113. InstrWriteMaskMatchValueForUAVStore, // uav store write mask must match store value mask, write mask is %0 and store value mask is %1
  114. // Metadata
  115. MetaBarycentricsFloat3, // only 'float3' type is allowed for SV_Barycentrics.
  116. MetaBarycentricsInterpolation, // SV_Barycentrics cannot be used with 'nointerpolation' type
  117. MetaBarycentricsTwoPerspectives, // There can only be up to two input attributes of SV_Barycentrics with different perspective interpolation mode.
  118. MetaBranchFlatten, // Can't use branch and flatten attributes together
  119. MetaClipCullMaxComponents, // Combined elements of SV_ClipDistance and SV_CullDistance must fit in 8 components
  120. MetaClipCullMaxRows, // Combined elements of SV_ClipDistance and SV_CullDistance must fit in two rows.
  121. MetaControlFlowHintNotOnControlFlow, // Control flow hint only works on control flow inst
  122. MetaDenseResIDs, // Resource identifiers must be zero-based and dense
  123. MetaDuplicateSysValue, // System value may only appear once in signature
  124. MetaEntryFunction, // entrypoint not found
  125. MetaFlagsUsage, // Flags must match usage
  126. MetaForceCaseOnSwitch, // Attribute forcecase only works for switch
  127. MetaFunctionAnnotation, // Cannot find function annotation for %0
  128. MetaGlcNotOnAppendConsume, // globallycoherent cannot be used with append/consume buffers
  129. MetaIntegerInterpMode, // Interpolation mode on integer must be Constant
  130. MetaInterpModeInOneRow, // Interpolation mode must be identical for all elements packed into the same row.
  131. MetaInterpModeValid, // Interpolation mode must be valid
  132. MetaInvalidControlFlowHint, // Invalid control flow hint
  133. MetaKnown, // Named metadata should be known
  134. MetaMaxTessFactor, // Hull Shader MaxTessFactor must be [%0..%1]. %2 specified
  135. MetaNoSemanticOverlap, // Semantics must not overlap
  136. MetaRequired, // TODO - Required metadata missing
  137. MetaSemaKindMatchesName, // Semantic name must match system value, when defined.
  138. MetaSemaKindValid, // Semantic kind must be valid
  139. MetaSemanticCompType, // %0 must be %1
  140. MetaSemanticIndexMax, // System value semantics have a maximum valid semantic index
  141. MetaSemanticLen, // Semantic length must be at least 1 and at most 64
  142. MetaSemanticShouldBeAllocated, // Semantic should have a valid packing location
  143. MetaSemanticShouldNotBeAllocated, // Semantic should have a packing location of -1
  144. MetaSignatureCompType, // signature %0 specifies unrecognized or invalid component type
  145. MetaSignatureDataWidth, // Data width must be identical for all elements packed into the same row.
  146. MetaSignatureIllegalComponentOrder, // Component ordering for packed elements must be: arbitrary < system value < system generated value
  147. MetaSignatureIndexConflict, // Only elements with compatible indexing rules may be packed together
  148. MetaSignatureOutOfRange, // Signature elements must fit within maximum signature size
  149. MetaSignatureOverlap, // Signature elements may not overlap in packing location.
  150. MetaStructBufAlignment, // StructuredBuffer stride not aligned
  151. MetaStructBufAlignmentOutOfBound, // StructuredBuffer stride out of bounds
  152. MetaSystemValueRows, // System value may only have 1 row
  153. MetaTarget, // Target triple must be 'dxil-ms-dx'
  154. MetaTessellatorOutputPrimitive, // Invalid Tessellator Output Primitive specified. Must be point, line, triangleCW or triangleCCW.
  155. MetaTessellatorPartition, // Invalid Tessellator Partitioning specified. Must be integer, pow2, fractional_odd or fractional_even.
  156. MetaTextureType, // elements of typed buffers and textures must fit in four 32-bit quantities
  157. MetaUsed, // All metadata must be used by dxil
  158. MetaValidSamplerMode, // Invalid sampler mode on sampler
  159. MetaValueRange, // Metadata value must be within range
  160. MetaWellFormed, // TODO - Metadata must be well-formed in operand count and types
  161. // Program flow
  162. FlowDeadLoop, // Loop must have break
  163. FlowFunctionCall, // Function with parameter is not permitted
  164. FlowNoRecusion, // Recursion is not permitted
  165. FlowReducible, // Execution flow must be reducible
  166. // Shader model
  167. SmAppendAndConsumeOnSameUAV, // BufferUpdateCounter inc and dec on a given UAV (%d) cannot both be in the same shader for shader model less than 5.1.
  168. SmCBufferElementOverflow, // CBuffer elements must not overflow
  169. SmCBufferOffsetOverlap, // CBuffer offsets must not overlap
  170. SmCBufferTemplateTypeMustBeStruct, // D3D12 constant/texture buffer template element can only be a struct
  171. SmCSNoReturn, // Compute shaders can't return values, outputs must be written in writable resources (UAVs).
  172. SmCompletePosition, // Not all elements of SV_Position were written
  173. SmCounterOnlyOnStructBuf, // BufferUpdateCounter valid only on structured buffers
  174. SmDSInputControlPointCountRange, // DS input control point count must be [0..%0]. %1 specified
  175. SmDomainLocationIdxOOB, // DomainLocation component index out of bounds for the domain.
  176. SmDxilVersion, // Target shader model requires specific Dxil Version
  177. SmGSInstanceCountRange, // GS instance count must be [1..%0]. %1 specified
  178. SmGSOutputVertexCountRange, // GS output vertex count must be [0..%0]. %1 specified
  179. SmGSTotalOutputVertexDataRange, // Declared output vertex count (%0) multiplied by the total number of declared scalar components of output data (%1) equals %2. This value cannot be greater than %3
  180. SmGSValidInputPrimitive, // GS input primitive unrecognized
  181. SmGSValidOutputPrimitiveTopology, // GS output primitive topology unrecognized
  182. SmHSInputControlPointCountRange, // HS input control point count must be [0..%0]. %1 specified
  183. SmHullPassThruControlPointCountMatch, // For pass thru hull shader, input control point count must match output control point count
  184. SmInsideTessFactorSizeMatchDomain, // InsideTessFactor rows, columns (%0, %1) invalid for domain %2. Expected %3 rows and 1 column.
  185. SmInvalidResourceCompType, // Invalid resource return type
  186. SmInvalidResourceKind, // Invalid resources kind
  187. SmInvalidTextureKindOnUAV, // Texture2DMS[Array] or TextureCube[Array] resources are not supported with UAVs
  188. SmIsoLineOutputPrimitiveMismatch, // Hull Shader declared with IsoLine Domain must specify output primitive point or line. Triangle_cw or triangle_ccw output are not compatible with the IsoLine Domain.
  189. SmMaxTGSMSize, // Total Thread Group Shared Memory storage is %0, exceeded %1
  190. SmMaxTheadGroup, // Declared Thread Group Count %0 (X*Y*Z) is beyond the valid maximum of %1
  191. SmMultiStreamMustBePoint, // When multiple GS output streams are used they must be pointlists
  192. SmName, // Target shader model name must be known
  193. SmNoInterpMode, // Interpolation mode must be undefined for VS input/PS output/patch constant.
  194. SmNoPSOutputIdx, // Pixel shader output registers are not indexable.
  195. SmOpcode, // Opcode must be defined in target shader model
  196. SmOpcodeInInvalidFunction, // Invalid DXIL opcode usage like StorePatchConstant in patch constant function
  197. SmOperand, // Operand must be defined in target shader model
  198. SmOutputControlPointCountRange, // output control point count must be [0..%0]. %1 specified
  199. SmOutputControlPointsTotalScalars, // Total number of scalars across all HS output control points must not exceed
  200. SmPSConsistentInterp, // Interpolation mode for PS input position must be linear_noperspective_centroid or linear_noperspective_sample when outputting oDepthGE or oDepthLE and not running at sample frequency (which is forced by inputting SV_SampleIndex or declaring an input linear_sample or linear_noperspective_sample)
  201. SmPSCoverageAndInnerCoverage, // InnerCoverage and Coverage are mutually exclusive.
  202. SmPSMultipleDepthSemantic, // Pixel Shader only allows one type of depth semantic to be declared
  203. SmPSOutputSemantic, // Pixel Shader allows output semantics to be SV_Target, SV_Depth, SV_DepthGreaterEqual, SV_DepthLessEqual, SV_Coverage or SV_StencilRef, %0 found
  204. SmPSTargetCol0, // SV_Target packed location must start at column 0
  205. SmPSTargetIndexMatchesRow, // SV_Target semantic index must match packed row location
  206. SmPatchConstantOnlyForHSDS, // patch constant signature only valid in HS and DS
  207. SmROVOnlyInPS, // RasterizerOrdered objects are only allowed in 5.0+ pixel shaders
  208. SmResourceRangeOverlap, // Resource ranges must not overlap
  209. SmSampleCountOnlyOn2DMS, // Only Texture2DMS/2DMSArray could has sample count
  210. SmSemantic, // Semantic must be defined in target shader model
  211. SmStreamIndexRange, // Stream index (%0) must between 0 and %1
  212. SmTessFactorForDomain, // Required TessFactor for domain not found declared anywhere in Patch Constant data
  213. SmTessFactorSizeMatchDomain, // TessFactor rows, columns (%0, %1) invalid for domain %2. Expected %3 rows and 1 column.
  214. SmThreadGroupChannelRange, // Declared Thread Group %0 size %1 outside valid range [%2..%3]
  215. SmTriOutputPrimitiveMismatch, // Hull Shader declared with Tri Domain must specify output primitive point, triangle_cw or triangle_ccw. Line output is not compatible with the Tri domain
  216. SmUndefinedOutput, // Not all elements of output %0 were written
  217. SmValidDomain, // Invalid Tessellator Domain specified. Must be isoline, tri or quad
  218. SmViewIDNeedsSlot, // ViewID requires compatible space in pixel shader input signature
  219. SmZeroHSInputControlPointWithInput, // When HS input control point count is 0, no input signature should exist
  220. // Type system
  221. TypesDefined, // Type must be defined based on DXIL primitives
  222. TypesI8, // I8 can only used as immediate value for intrinsic
  223. TypesIntWidth, // Int type must be of valid width
  224. TypesNoMultiDim, // Only one dimension allowed for array type
  225. TypesNoVector, // Vector types must not be present
  226. // Uniform analysis
  227. UniNoWaveSensitiveGradient, // Gradient operations are not affected by wave-sensitive data or control flow.
  228. };
  229. // VALRULE-ENUM:END
  230. const char *GetValidationRuleText(ValidationRule value);
  231. void GetValidationVersion(_Out_ unsigned *pMajor, _Out_ unsigned *pMinor);
  232. HRESULT ValidateDxilModule(_In_ llvm::Module *pModule,
  233. _In_opt_ llvm::Module *pDebugModule);
  234. // DXIL Container Verification Functions (return false on failure)
  235. bool VerifySignatureMatches(_In_ llvm::Module *pModule,
  236. hlsl::DXIL::SignatureKind SigKind,
  237. _In_reads_bytes_(SigSize) const void *pSigData,
  238. _In_ uint32_t SigSize);
  239. // PSV = data for Pipeline State Validation
  240. bool VerifyPSVMatches(_In_ llvm::Module *pModule,
  241. _In_reads_bytes_(PSVSize) const void *pPSVData,
  242. _In_ uint32_t PSVSize);
  243. bool VerifyFeatureInfoMatches(_In_ llvm::Module *pModule,
  244. _In_reads_bytes_(FeatureInfoSize) const void *pFeatureInfoData,
  245. _In_ uint32_t FeatureInfoSize);
  246. // Validate the container parts, assuming supplied module is valid, loaded from the container provided
  247. struct DxilContainerHeader;
  248. HRESULT ValidateDxilContainerParts(_In_ llvm::Module *pModule,
  249. _In_opt_ llvm::Module *pDebugModule,
  250. _In_reads_bytes_(ContainerSize) const DxilContainerHeader *pContainer,
  251. _In_ uint32_t ContainerSize);
  252. // Loads module, validating load, but not module.
  253. HRESULT ValidateLoadModule(_In_reads_bytes_(ILLength) const char *pIL,
  254. _In_ uint32_t ILLength,
  255. _In_ std::unique_ptr<llvm::Module> &pModule,
  256. _In_ llvm::LLVMContext &Ctx,
  257. _In_ llvm::raw_ostream &DiagStream,
  258. _In_ unsigned bLazyLoad);
  259. // Loads module from container, validating load, but not module.
  260. HRESULT ValidateLoadModuleFromContainer(
  261. _In_reads_bytes_(ContainerSize) const void *pContainer,
  262. _In_ uint32_t ContainerSize, _In_ std::unique_ptr<llvm::Module> &pModule,
  263. _In_ std::unique_ptr<llvm::Module> &pDebugModule,
  264. _In_ llvm::LLVMContext &Ctx, llvm::LLVMContext &DbgCtx,
  265. _In_ llvm::raw_ostream &DiagStream);
  266. // Lazy loads module from container, validating load, but not module.
  267. HRESULT ValidateLoadModuleFromContainerLazy(
  268. _In_reads_bytes_(ContainerSize) const void *pContainer,
  269. _In_ uint32_t ContainerSize, _In_ std::unique_ptr<llvm::Module> &pModule,
  270. _In_ std::unique_ptr<llvm::Module> &pDebugModule,
  271. _In_ llvm::LLVMContext &Ctx, llvm::LLVMContext &DbgCtx,
  272. _In_ llvm::raw_ostream &DiagStream);
  273. // Load and validate Dxil module from bitcode.
  274. HRESULT ValidateDxilBitcode(_In_reads_bytes_(ILLength) const char *pIL,
  275. _In_ uint32_t ILLength,
  276. _In_ llvm::raw_ostream &DiagStream);
  277. // Full container validation, including ValidateDxilModule
  278. HRESULT ValidateDxilContainer(_In_reads_bytes_(ContainerSize) const void *pContainer,
  279. _In_ uint32_t ContainerSize,
  280. _In_ llvm::raw_ostream &DiagStream);
  281. class PrintDiagnosticContext {
  282. private:
  283. llvm::DiagnosticPrinter &m_Printer;
  284. bool m_errorsFound;
  285. bool m_warningsFound;
  286. public:
  287. PrintDiagnosticContext(llvm::DiagnosticPrinter &printer);
  288. bool HasErrors() const;
  289. bool HasWarnings() const;
  290. void Handle(const llvm::DiagnosticInfo &DI);
  291. static void PrintDiagnosticHandler(const llvm::DiagnosticInfo &DI,
  292. void *Context);
  293. };
  294. }