Browse Source

Merged PR 105: update handle validation.

update handle validation.
Xiang_Li (XBox) 7 years ago
parent
commit
94157e54ab

+ 203 - 198
docs/DXIL.rst

@@ -2894,204 +2894,209 @@ The set of validation rules that are known to hold for a DXIL program is identif
 .. <py::lines('VALRULES-RST')>hctdb_instrhelp.get_valrules_rst()</py>
 .. VALRULES-RST:BEGIN
 
-====================================== =======================================================================================================================================================================================================================================================================================================
-Rule Code                              Description
-====================================== =======================================================================================================================================================================================================================================================================================================
-BITCODE.VALID                          TODO - Module must be bitcode-valid
-CONTAINER.PARTINVALID                  DXIL Container must not contain unknown parts
-CONTAINER.PARTMATCHES                  DXIL Container Parts must match Module
-CONTAINER.PARTMISSING                  DXIL Container requires certain parts, corresponding to module
-CONTAINER.PARTREPEATED                 DXIL Container must have only one of each part type
-CONTAINER.ROOTSIGNATUREINCOMPATIBLE    Root Signature in DXIL Container must be compatible with shader
-DECL.DXILFNEXTERN                      External function must be a DXIL function
-DECL.DXILNSRESERVED                    The DXIL reserved prefixes must only be used by built-in functions and types
-DECL.FNATTRIBUTE                       Functions should only contain known function attributes
-DECL.FNFLATTENPARAM                    Function parameters must not use struct types
-DECL.FNISCALLED                        Functions can only be used by call instructions
-DECL.NOTUSEDEXTERNAL                   External declaration should not be used
-DECL.USEDEXTERNALFUNCTION              External function must be used
-DECL.USEDINTERNAL                      Internal declaration must be used
-FLOW.DEADLOOP                          Loop must have break
-FLOW.FUNCTIONCALL                      Function with parameter is not permitted
-FLOW.NORECUSION                        Recursion is not permitted
-FLOW.REDUCIBLE                         Execution flow must be reducible
-INSTR.ALLOWED                          Instructions must be of an allowed type
-INSTR.ATTRIBUTEATVERTEXNOINTERPOLATION Attribute %0 must have nointerpolation mode in order to use GetAttributeAtVertex function.
-INSTR.BARRIERMODEFORNONCS              sync in a non-Compute Shader must only sync UAV (sync_uglobal)
-INSTR.BARRIERMODENOMEMORY              sync must include some form of memory barrier - _u (UAV) and/or _g (Thread Group Shared Memory).  Only _t (thread group sync) is optional.
-INSTR.BARRIERMODEUSELESSUGROUP         sync can't specify both _ugroup and _uglobal. If both are needed, just specify _uglobal.
-INSTR.BUFFERUPDATECOUNTERONUAV         BufferUpdateCounter valid only on UAV
-INSTR.CALLOLOAD                        Call to DXIL intrinsic must match overload signature
-INSTR.CANNOTPULLPOSITION               pull-model evaluation of position disallowed
-INSTR.CBUFFERCLASSFORCBUFFERHANDLE     Expect Cbuffer for CBufferLoad handle
-INSTR.CBUFFEROUTOFBOUND                Cbuffer access out of bound
-INSTR.CHECKACCESSFULLYMAPPED           CheckAccessFullyMapped should only used on resource status
-INSTR.COORDINATECOUNTFORRAWTYPEDBUF    raw/typed buffer don't need 2 coordinates
-INSTR.COORDINATECOUNTFORSTRUCTBUF      structured buffer require 2 coordinates
-INSTR.CREATEHANDLEIMMRANGEID           Local resource must map to global resource.
-INSTR.DXILSTRUCTUSER                   Dxil struct types should only used by ExtractValue
-INSTR.DXILSTRUCTUSEROUTOFBOUND         Index out of bound when extract value from dxil struct types
-INSTR.EVALINTERPOLATIONMODE            Interpolation mode on %0 used with eval_* instruction must be linear, linear_centroid, linear_noperspective, linear_noperspective_centroid, linear_sample or linear_noperspective_sample
-INSTR.EXTRACTVALUE                     ExtractValue should only be used on dxil struct types and cmpxchg
-INSTR.FAILTORESLOVETGSMPOINTER         TGSM pointers must originate from an unambiguous TGSM global variable.
-INSTR.HANDLENOTFROMCREATEHANDLE        Resource handle should returned by createHandle
-INSTR.IMMBIASFORSAMPLEB                bias amount for sample_b must be in the range [%0,%1], but %2 was specified as an immediate
-INSTR.INBOUNDSACCESS                   Access to out-of-bounds memory is disallowed
-INSTR.MINPRECISIONNOTPRECISE           Instructions marked precise may not refer to minprecision values
-INSTR.MINPRECISONBITCAST               Bitcast on minprecison types is not allowed
-INSTR.MIPLEVELFORGETDIMENSION          Use mip level on buffer when GetDimensions
-INSTR.MIPONUAVLOAD                     uav load don't support mipLevel/sampleIndex
-INSTR.NOGENERICPTRADDRSPACECAST        Address space cast between pointer types must have one part to be generic address space
-INSTR.NOIDIVBYZERO                     No signed integer division by zero
-INSTR.NOINDEFINITEACOS                 No indefinite arccosine
-INSTR.NOINDEFINITEASIN                 No indefinite arcsine
-INSTR.NOINDEFINITEDSXY                 No indefinite derivative calculation
-INSTR.NOINDEFINITELOG                  No indefinite logarithm
-INSTR.NOREADINGUNINITIALIZED           Instructions should not read uninitialized value
-INSTR.NOUDIVBYZERO                     No unsigned integer division by zero
-INSTR.OFFSETONUAVLOAD                  uav load don't support offset
-INSTR.OLOAD                            DXIL intrinsic overload must be valid
-INSTR.ONLYONEALLOCCONSUME              RWStructuredBuffers may increment or decrement their counters, but not both.
-INSTR.OPCODERESERVED                   Instructions must not reference reserved opcodes
-INSTR.OPCONST                          DXIL intrinsic requires an immediate constant operand
-INSTR.OPCONSTRANGE                     Constant values must be in-range for operation
-INSTR.OPERANDRANGE                     DXIL intrinsic operand must be within defined range
-INSTR.PTRBITCAST                       Pointer type bitcast must be have same size
-INSTR.RESOURCECLASSFORLOAD             load can only run on UAV/SRV resource
-INSTR.RESOURCECLASSFORSAMPLERGATHER    sample, lod and gather should on srv resource.
-INSTR.RESOURCECLASSFORUAVSTORE         store should on uav resource.
-INSTR.RESOURCECOORDINATEMISS           coord uninitialized
-INSTR.RESOURCECOORDINATETOOMANY        out of bound coord must be undef
-INSTR.RESOURCEKINDFORBUFFERLOADSTORE   buffer load/store only works on Raw/Typed/StructuredBuffer
-INSTR.RESOURCEKINDFORCALCLOD           lod requires resource declared as texture1D/2D/3D/Cube/CubeArray/1DArray/2DArray
-INSTR.RESOURCEKINDFORGATHER            gather requires resource declared as texture/2D/Cube/2DArray/CubeArray
-INSTR.RESOURCEKINDFORGETDIM            Invalid resource kind on GetDimensions
-INSTR.RESOURCEKINDFORSAMPLE            sample/_l/_d requires resource declared as texture1D/2D/3D/Cube/1DArray/2DArray/CubeArray
-INSTR.RESOURCEKINDFORSAMPLEC           samplec requires resource declared as texture1D/2D/Cube/1DArray/2DArray/CubeArray
-INSTR.RESOURCEKINDFORTEXTURELOAD       texture load only works on Texture1D/1DArray/2D/2DArray/3D/MS2D/MS2DArray
-INSTR.RESOURCEKINDFORTEXTURESTORE      texture store only works on Texture1D/1DArray/2D/2DArray/3D
-INSTR.RESOURCEOFFSETMISS               offset uninitialized
-INSTR.RESOURCEOFFSETTOOMANY            out of bound offset must be undef
-INSTR.SAMPLECOMPTYPE                   sample_* instructions require resource to be declared to return UNORM, SNORM or FLOAT.
-INSTR.SAMPLEINDEXFORLOAD2DMS           load on Texture2DMS/2DMSArray require sampleIndex
-INSTR.SAMPLERMODEFORLOD                lod instruction requires sampler declared in default mode
-INSTR.SAMPLERMODEFORSAMPLE             sample/_l/_d/_cl_s/gather instruction requires sampler declared in default mode
-INSTR.SAMPLERMODEFORSAMPLEC            sample_c_*/gather_c instructions require sampler declared in comparison mode
-INSTR.SIGNATUREOPERATIONNOTINENTRY     Dxil operation for input output signature must be in entryPoints.
-INSTR.STATUS                           Resource status should only used by CheckAccessFullyMapped
-INSTR.STRUCTBITCAST                    Bitcast on struct types is not allowed
-INSTR.TEXTUREOFFSET                    offset texture instructions must take offset which can resolve to integer literal in the range -8 to 7
-INSTR.TGSMRACECOND                     Race condition writing to shared memory detected, consider making this write conditional
-INSTR.UNDEFRESULTFORGETDIMENSION       GetDimensions used undef dimension %0 on %1
-INSTR.WRITEMASKFORTYPEDUAVSTORE        store on typed uav must write to all four components of the UAV
-INSTR.WRITEMASKMATCHVALUEFORUAVSTORE   uav store write mask must match store value mask, write mask is %0 and store value mask is %1
-META.BARYCENTRICSFLOAT3                only 'float3' type is allowed for SV_Barycentrics.
-META.BARYCENTRICSINTERPOLATION         SV_Barycentrics cannot be used with 'nointerpolation' type
-META.BARYCENTRICSTWOPERSPECTIVES       There can only be up to two input attributes of SV_Barycentrics with different perspective interpolation mode.
-META.BRANCHFLATTEN                     Can't use branch and flatten attributes together
-META.CLIPCULLMAXCOMPONENTS             Combined elements of SV_ClipDistance and SV_CullDistance must fit in 8 components
-META.CLIPCULLMAXROWS                   Combined elements of SV_ClipDistance and SV_CullDistance must fit in two rows.
-META.CONTROLFLOWHINTNOTONCONTROLFLOW   Control flow hint only works on control flow inst
-META.DENSERESIDS                       Resource identifiers must be zero-based and dense
-META.DUPLICATESYSVALUE                 System value may only appear once in signature
-META.ENTRYFUNCTION                     entrypoint not found
-META.FLAGSUSAGE                        Flags must match usage
-META.FORCECASEONSWITCH                 Attribute forcecase only works for switch
-META.FUNCTIONANNOTATION                Cannot find function annotation for %0
-META.GLCNOTONAPPENDCONSUME             globallycoherent cannot be used with append/consume buffers
-META.INTEGERINTERPMODE                 Interpolation mode on integer must be Constant
-META.INTERPMODEINONEROW                Interpolation mode must be identical for all elements packed into the same row.
-META.INTERPMODEVALID                   Interpolation mode must be valid
-META.INVALIDCONTROLFLOWHINT            Invalid control flow hint
-META.KNOWN                             Named metadata should be known
-META.MAXTESSFACTOR                     Hull Shader MaxTessFactor must be [%0..%1].  %2 specified
-META.NOENTRYPROPSFORENTRY              EntryPoints must have entry properties.
-META.NOSEMANTICOVERLAP                 Semantics must not overlap
-META.REQUIRED                          TODO - Required metadata missing
-META.SEMAKINDMATCHESNAME               Semantic name must match system value, when defined.
-META.SEMAKINDVALID                     Semantic kind must be valid
-META.SEMANTICCOMPTYPE                  %0 must be %1
-META.SEMANTICINDEXMAX                  System value semantics have a maximum valid semantic index
-META.SEMANTICLEN                       Semantic length must be at least 1 and at most 64
-META.SEMANTICSHOULDBEALLOCATED         Semantic should have a valid packing location
-META.SEMANTICSHOULDNOTBEALLOCATED      Semantic should have a packing location of -1
-META.SIGNATURECOMPTYPE                 signature %0 specifies unrecognized or invalid component type
-META.SIGNATUREDATAWIDTH                Data width must be identical for all elements packed into the same row.
-META.SIGNATUREILLEGALCOMPONENTORDER    Component ordering for packed elements must be: arbitrary < system value < system generated value
-META.SIGNATUREINDEXCONFLICT            Only elements with compatible indexing rules may be packed together
-META.SIGNATUREOUTOFRANGE               Signature elements must fit within maximum signature size
-META.SIGNATUREOVERLAP                  Signature elements may not overlap in packing location.
-META.STRUCTBUFALIGNMENT                StructuredBuffer stride not aligned
-META.STRUCTBUFALIGNMENTOUTOFBOUND      StructuredBuffer stride out of bounds
-META.SYSTEMVALUEROWS                   System value may only have 1 row
-META.TARGET                            Target triple must be 'dxil-ms-dx'
-META.TESSELLATOROUTPUTPRIMITIVE        Invalid Tessellator Output Primitive specified. Must be point, line, triangleCW or triangleCCW.
-META.TESSELLATORPARTITION              Invalid Tessellator Partitioning specified. Must be integer, pow2, fractional_odd or fractional_even.
-META.TEXTURETYPE                       elements of typed buffers and textures must fit in four 32-bit quantities
-META.USED                              All metadata must be used by dxil
-META.VALIDSAMPLERMODE                  Invalid sampler mode on sampler
-META.VALUERANGE                        Metadata value must be within range
-META.WELLFORMED                        TODO - Metadata must be well-formed in operand count and types
-SM.APPENDANDCONSUMEONSAMEUAV           BufferUpdateCounter inc and dec on a given UAV (%d) cannot both be in the same shader for shader model less than 5.1.
-SM.CBUFFERELEMENTOVERFLOW              CBuffer elements must not overflow
-SM.CBUFFEROFFSETOVERLAP                CBuffer offsets must not overlap
-SM.CBUFFERTEMPLATETYPEMUSTBESTRUCT     D3D12 constant/texture buffer template element can only be a struct
-SM.COMPLETEPOSITION                    Not all elements of SV_Position were written
-SM.COUNTERONLYONSTRUCTBUF              BufferUpdateCounter valid only on structured buffers
-SM.CSNORETURN                          Compute shaders can't return values, outputs must be written in writable resources (UAVs).
-SM.DOMAINLOCATIONIDXOOB                DomainLocation component index out of bounds for the domain.
-SM.DSINPUTCONTROLPOINTCOUNTRANGE       DS input control point count must be [0..%0].  %1 specified
-SM.DXILVERSION                         Target shader model requires specific Dxil Version
-SM.GSINSTANCECOUNTRANGE                GS instance count must be [1..%0].  %1 specified
-SM.GSOUTPUTVERTEXCOUNTRANGE            GS output vertex count must be [0..%0].  %1 specified
-SM.GSTOTALOUTPUTVERTEXDATARANGE        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
-SM.GSVALIDINPUTPRIMITIVE               GS input primitive unrecognized
-SM.GSVALIDOUTPUTPRIMITIVETOPOLOGY      GS output primitive topology unrecognized
-SM.HSINPUTCONTROLPOINTCOUNTRANGE       HS input control point count must be [0..%0].  %1 specified
-SM.HULLPASSTHRUCONTROLPOINTCOUNTMATCH  For pass thru hull shader, input control point count must match output control point count
-SM.INSIDETESSFACTORSIZEMATCHDOMAIN     InsideTessFactor rows, columns (%0, %1) invalid for domain %2.  Expected %3 rows and 1 column.
-SM.INVALIDRESOURCECOMPTYPE             Invalid resource return type
-SM.INVALIDRESOURCEKIND                 Invalid resources kind
-SM.INVALIDTEXTUREKINDONUAV             Texture2DMS[Array] or TextureCube[Array] resources are not supported with UAVs
-SM.ISOLINEOUTPUTPRIMITIVEMISMATCH      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.
-SM.MAXTGSMSIZE                         Total Thread Group Shared Memory storage is %0, exceeded %1
-SM.MAXTHEADGROUP                       Declared Thread Group Count %0 (X*Y*Z) is beyond the valid maximum of %1
-SM.MULTISTREAMMUSTBEPOINT              When multiple GS output streams are used they must be pointlists
-SM.NAME                                Target shader model name must be known
-SM.NOINTERPMODE                        Interpolation mode must be undefined for VS input/PS output/patch constant.
-SM.NOPSOUTPUTIDX                       Pixel shader output registers are not indexable.
-SM.OPCODE                              Opcode must be defined in target shader model
-SM.OPCODEININVALIDFUNCTION             Invalid DXIL opcode usage like StorePatchConstant in patch constant function
-SM.OPERAND                             Operand must be defined in target shader model
-SM.OUTPUTCONTROLPOINTCOUNTRANGE        output control point count must be [0..%0].  %1 specified
-SM.OUTPUTCONTROLPOINTSTOTALSCALARS     Total number of scalars across all HS output control points must not exceed
-SM.PATCHCONSTANTONLYFORHSDS            patch constant signature only valid in HS and DS
-SM.PSCONSISTENTINTERP                  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)
-SM.PSCOVERAGEANDINNERCOVERAGE          InnerCoverage and Coverage are mutually exclusive.
-SM.PSMULTIPLEDEPTHSEMANTIC             Pixel Shader only allows one type of depth semantic to be declared
-SM.PSOUTPUTSEMANTIC                    Pixel Shader allows output semantics to be SV_Target, SV_Depth, SV_DepthGreaterEqual, SV_DepthLessEqual, SV_Coverage or SV_StencilRef, %0 found
-SM.PSTARGETCOL0                        SV_Target packed location must start at column 0
-SM.PSTARGETINDEXMATCHESROW             SV_Target semantic index must match packed row location
-SM.RESOURCERANGEOVERLAP                Resource ranges must not overlap
-SM.ROVONLYINPS                         RasterizerOrdered objects are only allowed in 5.0+ pixel shaders
-SM.SAMPLECOUNTONLYON2DMS               Only Texture2DMS/2DMSArray could has sample count
-SM.SEMANTIC                            Semantic must be defined in target shader model
-SM.STREAMINDEXRANGE                    Stream index (%0) must between 0 and %1
-SM.TESSFACTORFORDOMAIN                 Required TessFactor for domain not found declared anywhere in Patch Constant data
-SM.TESSFACTORSIZEMATCHDOMAIN           TessFactor rows, columns (%0, %1) invalid for domain %2.  Expected %3 rows and 1 column.
-SM.THREADGROUPCHANNELRANGE             Declared Thread Group %0 size %1 outside valid range [%2..%3]
-SM.TRIOUTPUTPRIMITIVEMISMATCH          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
-SM.UNDEFINEDOUTPUT                     Not all elements of output %0 were written
-SM.VALIDDOMAIN                         Invalid Tessellator Domain specified. Must be isoline, tri or quad
-SM.VIEWIDNEEDSSLOT                     ViewID requires compatible space in pixel shader input signature
-SM.ZEROHSINPUTCONTROLPOINTWITHINPUT    When HS input control point count is 0, no input signature should exist
-TYPES.DEFINED                          Type must be defined based on DXIL primitives
-TYPES.I8                               I8 can only used as immediate value for intrinsic
-TYPES.INTWIDTH                         Int type must be of valid width
-TYPES.NOMULTIDIM                       Only one dimension allowed for array type
-TYPES.NOVECTOR                         Vector types must not be present
-UNI.NOWAVESENSITIVEGRADIENT            Gradient operations are not affected by wave-sensitive data or control flow.
-====================================== =======================================================================================================================================================================================================================================================================================================
+======================================== =======================================================================================================================================================================================================================================================================================================
+Rule Code                                Description
+======================================== =======================================================================================================================================================================================================================================================================================================
+BITCODE.VALID                            TODO - Module must be bitcode-valid
+CONTAINER.PARTINVALID                    DXIL Container must not contain unknown parts
+CONTAINER.PARTMATCHES                    DXIL Container Parts must match Module
+CONTAINER.PARTMISSING                    DXIL Container requires certain parts, corresponding to module
+CONTAINER.PARTREPEATED                   DXIL Container must have only one of each part type
+CONTAINER.ROOTSIGNATUREINCOMPATIBLE      Root Signature in DXIL Container must be compatible with shader
+DECL.DXILFNEXTERN                        External function must be a DXIL function
+DECL.DXILNSRESERVED                      The DXIL reserved prefixes must only be used by built-in functions and types
+DECL.FNATTRIBUTE                         Functions should only contain known function attributes
+DECL.FNFLATTENPARAM                      Function parameters must not use struct types
+DECL.FNISCALLED                          Functions can only be used by call instructions
+DECL.NOTUSEDEXTERNAL                     External declaration should not be used
+DECL.USEDEXTERNALFUNCTION                External function must be used
+DECL.USEDINTERNAL                        Internal declaration must be used
+FLOW.DEADLOOP                            Loop must have break
+FLOW.FUNCTIONCALL                        Function with parameter is not permitted
+FLOW.NORECUSION                          Recursion is not permitted
+FLOW.REDUCIBLE                           Execution flow must be reducible
+INSTR.ALLOWED                            Instructions must be of an allowed type
+INSTR.ATTRIBUTEATVERTEXNOINTERPOLATION   Attribute %0 must have nointerpolation mode in order to use GetAttributeAtVertex function.
+INSTR.BARRIERMODEFORNONCS                sync in a non-Compute Shader must only sync UAV (sync_uglobal)
+INSTR.BARRIERMODENOMEMORY                sync must include some form of memory barrier - _u (UAV) and/or _g (Thread Group Shared Memory).  Only _t (thread group sync) is optional.
+INSTR.BARRIERMODEUSELESSUGROUP           sync can't specify both _ugroup and _uglobal. If both are needed, just specify _uglobal.
+INSTR.BUFFERUPDATECOUNTERONRESHASCOUNTER BufferUpdateCounter valid only when HasCounter is true
+INSTR.BUFFERUPDATECOUNTERONUAV           BufferUpdateCounter valid only on UAV
+INSTR.CALLOLOAD                          Call to DXIL intrinsic must match overload signature
+INSTR.CANNOTPULLPOSITION                 pull-model evaluation of position disallowed
+INSTR.CBUFFERCLASSFORCBUFFERHANDLE       Expect Cbuffer for CBufferLoad handle
+INSTR.CBUFFEROUTOFBOUND                  Cbuffer access out of bound
+INSTR.CHECKACCESSFULLYMAPPED             CheckAccessFullyMapped should only used on resource status
+INSTR.COORDINATECOUNTFORRAWTYPEDBUF      raw/typed buffer don't need 2 coordinates
+INSTR.COORDINATECOUNTFORSTRUCTBUF        structured buffer require 2 coordinates
+INSTR.CREATEHANDLEIMMRANGEID             Local resource must map to global resource.
+INSTR.DXILSTRUCTUSER                     Dxil struct types should only used by ExtractValue
+INSTR.DXILSTRUCTUSEROUTOFBOUND           Index out of bound when extract value from dxil struct types
+INSTR.EVALINTERPOLATIONMODE              Interpolation mode on %0 used with eval_* instruction must be linear, linear_centroid, linear_noperspective, linear_noperspective_centroid, linear_sample or linear_noperspective_sample
+INSTR.EXTRACTVALUE                       ExtractValue should only be used on dxil struct types and cmpxchg
+INSTR.FAILTORESLOVETGSMPOINTER           TGSM pointers must originate from an unambiguous TGSM global variable.
+INSTR.HANDLENOTFROMCREATEHANDLE          Resource handle should returned by createHandle
+INSTR.IMMBIASFORSAMPLEB                  bias amount for sample_b must be in the range [%0,%1], but %2 was specified as an immediate
+INSTR.INBOUNDSACCESS                     Access to out-of-bounds memory is disallowed
+INSTR.MINPRECISIONNOTPRECISE             Instructions marked precise may not refer to minprecision values
+INSTR.MINPRECISONBITCAST                 Bitcast on minprecison types is not allowed
+INSTR.MIPLEVELFORGETDIMENSION            Use mip level on buffer when GetDimensions
+INSTR.MIPONUAVLOAD                       uav load don't support mipLevel/sampleIndex
+INSTR.NOGENERICPTRADDRSPACECAST          Address space cast between pointer types must have one part to be generic address space
+INSTR.NOIDIVBYZERO                       No signed integer division by zero
+INSTR.NOINDEFINITEACOS                   No indefinite arccosine
+INSTR.NOINDEFINITEASIN                   No indefinite arcsine
+INSTR.NOINDEFINITEDSXY                   No indefinite derivative calculation
+INSTR.NOINDEFINITELOG                    No indefinite logarithm
+INSTR.NOREADINGUNINITIALIZED             Instructions should not read uninitialized value
+INSTR.NOUDIVBYZERO                       No unsigned integer division by zero
+INSTR.OFFSETONUAVLOAD                    uav load don't support offset
+INSTR.OLOAD                              DXIL intrinsic overload must be valid
+INSTR.ONLYONEALLOCCONSUME                RWStructuredBuffers may increment or decrement their counters, but not both.
+INSTR.OPCODERESERVED                     Instructions must not reference reserved opcodes
+INSTR.OPCONST                            DXIL intrinsic requires an immediate constant operand
+INSTR.OPCONSTRANGE                       Constant values must be in-range for operation
+INSTR.OPERANDRANGE                       DXIL intrinsic operand must be within defined range
+INSTR.PTRBITCAST                         Pointer type bitcast must be have same size
+INSTR.RESOURCECLASSFORLOAD               load can only run on UAV/SRV resource
+INSTR.RESOURCECLASSFORSAMPLERGATHER      sample, lod and gather should on srv resource.
+INSTR.RESOURCECLASSFORUAVSTORE           store should on uav resource.
+INSTR.RESOURCECOORDINATEMISS             coord uninitialized
+INSTR.RESOURCECOORDINATETOOMANY          out of bound coord must be undef
+INSTR.RESOURCEKINDFORBUFFERLOADSTORE     buffer load/store only works on Raw/Typed/StructuredBuffer
+INSTR.RESOURCEKINDFORCALCLOD             lod requires resource declared as texture1D/2D/3D/Cube/CubeArray/1DArray/2DArray
+INSTR.RESOURCEKINDFORGATHER              gather requires resource declared as texture/2D/Cube/2DArray/CubeArray
+INSTR.RESOURCEKINDFORGETDIM              Invalid resource kind on GetDimensions
+INSTR.RESOURCEKINDFORSAMPLE              sample/_l/_d requires resource declared as texture1D/2D/3D/Cube/1DArray/2DArray/CubeArray
+INSTR.RESOURCEKINDFORSAMPLEC             samplec requires resource declared as texture1D/2D/Cube/1DArray/2DArray/CubeArray
+INSTR.RESOURCEKINDFORTEXTURELOAD         texture load only works on Texture1D/1DArray/2D/2DArray/3D/MS2D/MS2DArray
+INSTR.RESOURCEKINDFORTEXTURESTORE        texture store only works on Texture1D/1DArray/2D/2DArray/3D
+INSTR.RESOURCEKINDFORTRACERAY            TraceRay should only use RTAccelerationStructure
+INSTR.RESOURCEMAPTOSINGLEENTRY           Fail to map resource to resource table
+INSTR.RESOURCEOFFSETMISS                 offset uninitialized
+INSTR.RESOURCEOFFSETTOOMANY              out of bound offset must be undef
+INSTR.RESOURCEUSER                       Resource should only used by Load/GEP/Call
+INSTR.SAMPLECOMPTYPE                     sample_* instructions require resource to be declared to return UNORM, SNORM or FLOAT.
+INSTR.SAMPLEINDEXFORLOAD2DMS             load on Texture2DMS/2DMSArray require sampleIndex
+INSTR.SAMPLERMODEFORLOD                  lod instruction requires sampler declared in default mode
+INSTR.SAMPLERMODEFORSAMPLE               sample/_l/_d/_cl_s/gather instruction requires sampler declared in default mode
+INSTR.SAMPLERMODEFORSAMPLEC              sample_c_*/gather_c instructions require sampler declared in comparison mode
+INSTR.SIGNATUREOPERATIONNOTINENTRY       Dxil operation for input output signature must be in entryPoints.
+INSTR.STATUS                             Resource status should only used by CheckAccessFullyMapped
+INSTR.STRUCTBITCAST                      Bitcast on struct types is not allowed
+INSTR.TEXTUREOFFSET                      offset texture instructions must take offset which can resolve to integer literal in the range -8 to 7
+INSTR.TGSMRACECOND                       Race condition writing to shared memory detected, consider making this write conditional
+INSTR.UNDEFRESULTFORGETDIMENSION         GetDimensions used undef dimension %0 on %1
+INSTR.WRITEMASKFORTYPEDUAVSTORE          store on typed uav must write to all four components of the UAV
+INSTR.WRITEMASKMATCHVALUEFORUAVSTORE     uav store write mask must match store value mask, write mask is %0 and store value mask is %1
+META.BARYCENTRICSFLOAT3                  only 'float3' type is allowed for SV_Barycentrics.
+META.BARYCENTRICSINTERPOLATION           SV_Barycentrics cannot be used with 'nointerpolation' type
+META.BARYCENTRICSTWOPERSPECTIVES         There can only be up to two input attributes of SV_Barycentrics with different perspective interpolation mode.
+META.BRANCHFLATTEN                       Can't use branch and flatten attributes together
+META.CLIPCULLMAXCOMPONENTS               Combined elements of SV_ClipDistance and SV_CullDistance must fit in 8 components
+META.CLIPCULLMAXROWS                     Combined elements of SV_ClipDistance and SV_CullDistance must fit in two rows.
+META.CONTROLFLOWHINTNOTONCONTROLFLOW     Control flow hint only works on control flow inst
+META.DENSERESIDS                         Resource identifiers must be zero-based and dense
+META.DUPLICATESYSVALUE                   System value may only appear once in signature
+META.ENTRYFUNCTION                       entrypoint not found
+META.FLAGSUSAGE                          Flags must match usage
+META.FORCECASEONSWITCH                   Attribute forcecase only works for switch
+META.FUNCTIONANNOTATION                  Cannot find function annotation for %0
+META.GLCNOTONAPPENDCONSUME               globallycoherent cannot be used with append/consume buffers
+META.INTEGERINTERPMODE                   Interpolation mode on integer must be Constant
+META.INTERPMODEINONEROW                  Interpolation mode must be identical for all elements packed into the same row.
+META.INTERPMODEVALID                     Interpolation mode must be valid
+META.INVALIDCONTROLFLOWHINT              Invalid control flow hint
+META.KNOWN                               Named metadata should be known
+META.MAXTESSFACTOR                       Hull Shader MaxTessFactor must be [%0..%1].  %2 specified
+META.NOENTRYPROPSFORENTRY                EntryPoints must have entry properties.
+META.NOSEMANTICOVERLAP                   Semantics must not overlap
+META.REQUIRED                            TODO - Required metadata missing
+META.SEMAKINDMATCHESNAME                 Semantic name must match system value, when defined.
+META.SEMAKINDVALID                       Semantic kind must be valid
+META.SEMANTICCOMPTYPE                    %0 must be %1
+META.SEMANTICINDEXMAX                    System value semantics have a maximum valid semantic index
+META.SEMANTICLEN                         Semantic length must be at least 1 and at most 64
+META.SEMANTICSHOULDBEALLOCATED           Semantic should have a valid packing location
+META.SEMANTICSHOULDNOTBEALLOCATED        Semantic should have a packing location of -1
+META.SIGNATURECOMPTYPE                   signature %0 specifies unrecognized or invalid component type
+META.SIGNATUREDATAWIDTH                  Data width must be identical for all elements packed into the same row.
+META.SIGNATUREILLEGALCOMPONENTORDER      Component ordering for packed elements must be: arbitrary < system value < system generated value
+META.SIGNATUREINDEXCONFLICT              Only elements with compatible indexing rules may be packed together
+META.SIGNATUREOUTOFRANGE                 Signature elements must fit within maximum signature size
+META.SIGNATUREOVERLAP                    Signature elements may not overlap in packing location.
+META.STRUCTBUFALIGNMENT                  StructuredBuffer stride not aligned
+META.STRUCTBUFALIGNMENTOUTOFBOUND        StructuredBuffer stride out of bounds
+META.SYSTEMVALUEROWS                     System value may only have 1 row
+META.TARGET                              Target triple must be 'dxil-ms-dx'
+META.TESSELLATOROUTPUTPRIMITIVE          Invalid Tessellator Output Primitive specified. Must be point, line, triangleCW or triangleCCW.
+META.TESSELLATORPARTITION                Invalid Tessellator Partitioning specified. Must be integer, pow2, fractional_odd or fractional_even.
+META.TEXTURETYPE                         elements of typed buffers and textures must fit in four 32-bit quantities
+META.USED                                All metadata must be used by dxil
+META.VALIDSAMPLERMODE                    Invalid sampler mode on sampler
+META.VALUERANGE                          Metadata value must be within range
+META.WELLFORMED                          TODO - Metadata must be well-formed in operand count and types
+SM.64BITRAWBUFFERLOADSTORE               i64/f64 rawBufferLoad/Store overloads are allowed after SM 6.3
+SM.APPENDANDCONSUMEONSAMEUAV             BufferUpdateCounter inc and dec on a given UAV (%d) cannot both be in the same shader for shader model less than 5.1.
+SM.CBUFFERELEMENTOVERFLOW                CBuffer elements must not overflow
+SM.CBUFFEROFFSETOVERLAP                  CBuffer offsets must not overlap
+SM.CBUFFERTEMPLATETYPEMUSTBESTRUCT       D3D12 constant/texture buffer template element can only be a struct
+SM.COMPLETEPOSITION                      Not all elements of SV_Position were written
+SM.COUNTERONLYONSTRUCTBUF                BufferUpdateCounter valid only on structured buffers
+SM.CSNORETURN                            Compute shaders can't return values, outputs must be written in writable resources (UAVs).
+SM.DOMAINLOCATIONIDXOOB                  DomainLocation component index out of bounds for the domain.
+SM.DSINPUTCONTROLPOINTCOUNTRANGE         DS input control point count must be [0..%0].  %1 specified
+SM.DXILVERSION                           Target shader model requires specific Dxil Version
+SM.GSINSTANCECOUNTRANGE                  GS instance count must be [1..%0].  %1 specified
+SM.GSOUTPUTVERTEXCOUNTRANGE              GS output vertex count must be [0..%0].  %1 specified
+SM.GSTOTALOUTPUTVERTEXDATARANGE          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
+SM.GSVALIDINPUTPRIMITIVE                 GS input primitive unrecognized
+SM.GSVALIDOUTPUTPRIMITIVETOPOLOGY        GS output primitive topology unrecognized
+SM.HSINPUTCONTROLPOINTCOUNTRANGE         HS input control point count must be [0..%0].  %1 specified
+SM.HULLPASSTHRUCONTROLPOINTCOUNTMATCH    For pass thru hull shader, input control point count must match output control point count
+SM.INSIDETESSFACTORSIZEMATCHDOMAIN       InsideTessFactor rows, columns (%0, %1) invalid for domain %2.  Expected %3 rows and 1 column.
+SM.INVALIDRESOURCECOMPTYPE               Invalid resource return type
+SM.INVALIDRESOURCEKIND                   Invalid resources kind
+SM.INVALIDTEXTUREKINDONUAV               Texture2DMS[Array] or TextureCube[Array] resources are not supported with UAVs
+SM.ISOLINEOUTPUTPRIMITIVEMISMATCH        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.
+SM.MAXTGSMSIZE                           Total Thread Group Shared Memory storage is %0, exceeded %1
+SM.MAXTHEADGROUP                         Declared Thread Group Count %0 (X*Y*Z) is beyond the valid maximum of %1
+SM.MULTISTREAMMUSTBEPOINT                When multiple GS output streams are used they must be pointlists
+SM.NAME                                  Target shader model name must be known
+SM.NOINTERPMODE                          Interpolation mode must be undefined for VS input/PS output/patch constant.
+SM.NOPSOUTPUTIDX                         Pixel shader output registers are not indexable.
+SM.OPCODE                                Opcode must be defined in target shader model
+SM.OPCODEININVALIDFUNCTION               Invalid DXIL opcode usage like StorePatchConstant in patch constant function
+SM.OPERAND                               Operand must be defined in target shader model
+SM.OUTPUTCONTROLPOINTCOUNTRANGE          output control point count must be [0..%0].  %1 specified
+SM.OUTPUTCONTROLPOINTSTOTALSCALARS       Total number of scalars across all HS output control points must not exceed
+SM.PATCHCONSTANTONLYFORHSDS              patch constant signature only valid in HS and DS
+SM.PSCONSISTENTINTERP                    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)
+SM.PSCOVERAGEANDINNERCOVERAGE            InnerCoverage and Coverage are mutually exclusive.
+SM.PSMULTIPLEDEPTHSEMANTIC               Pixel Shader only allows one type of depth semantic to be declared
+SM.PSOUTPUTSEMANTIC                      Pixel Shader allows output semantics to be SV_Target, SV_Depth, SV_DepthGreaterEqual, SV_DepthLessEqual, SV_Coverage or SV_StencilRef, %0 found
+SM.PSTARGETCOL0                          SV_Target packed location must start at column 0
+SM.PSTARGETINDEXMATCHESROW               SV_Target semantic index must match packed row location
+SM.RESOURCERANGEOVERLAP                  Resource ranges must not overlap
+SM.ROVONLYINPS                           RasterizerOrdered objects are only allowed in 5.0+ pixel shaders
+SM.SAMPLECOUNTONLYON2DMS                 Only Texture2DMS/2DMSArray could has sample count
+SM.SEMANTIC                              Semantic must be defined in target shader model
+SM.STREAMINDEXRANGE                      Stream index (%0) must between 0 and %1
+SM.TESSFACTORFORDOMAIN                   Required TessFactor for domain not found declared anywhere in Patch Constant data
+SM.TESSFACTORSIZEMATCHDOMAIN             TessFactor rows, columns (%0, %1) invalid for domain %2.  Expected %3 rows and 1 column.
+SM.THREADGROUPCHANNELRANGE               Declared Thread Group %0 size %1 outside valid range [%2..%3]
+SM.TRIOUTPUTPRIMITIVEMISMATCH            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
+SM.UNDEFINEDOUTPUT                       Not all elements of output %0 were written
+SM.VALIDDOMAIN                           Invalid Tessellator Domain specified. Must be isoline, tri or quad
+SM.VIEWIDNEEDSSLOT                       ViewID requires compatible space in pixel shader input signature
+SM.ZEROHSINPUTCONTROLPOINTWITHINPUT      When HS input control point count is 0, no input signature should exist
+TYPES.DEFINED                            Type must be defined based on DXIL primitives
+TYPES.I8                                 I8 can only used as immediate value for intrinsic
+TYPES.INTWIDTH                           Int type must be of valid width
+TYPES.NOMULTIDIM                         Only one dimension allowed for array type
+TYPES.NOVECTOR                           Vector types must not be present
+UNI.NOWAVESENSITIVEGRADIENT              Gradient operations are not affected by wave-sensitive data or control flow.
+======================================== =======================================================================================================================================================================================================================================================================================================
 
 .. VALRULES-RST:END
 

+ 5 - 0
include/dxc/HLSL/DxilValidation.h

@@ -56,6 +56,7 @@ enum class ValidationRule : unsigned {
   InstrBarrierModeForNonCS, // sync in a non-Compute Shader must only sync UAV (sync_uglobal)
   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. 
   InstrBarrierModeUselessUGroup, // sync can't specify both _ugroup and _uglobal. If both are needed, just specify _uglobal.
+  InstrBufferUpdateCounterOnResHasCounter, // BufferUpdateCounter valid only when HasCounter is true
   InstrBufferUpdateCounterOnUAV, // BufferUpdateCounter valid only on UAV
   InstrCBufferClassForCBufferHandle, // Expect Cbuffer for CBufferLoad handle
   InstrCBufferOutOfBound, // Cbuffer access out of bound
@@ -106,8 +107,11 @@ enum class ValidationRule : unsigned {
   InstrResourceKindForSampleC, // samplec requires resource declared as texture1D/2D/Cube/1DArray/2DArray/CubeArray
   InstrResourceKindForTextureLoad, // texture load only works on Texture1D/1DArray/2D/2DArray/3D/MS2D/MS2DArray
   InstrResourceKindForTextureStore, // texture store only works on Texture1D/1DArray/2D/2DArray/3D
+  InstrResourceKindForTraceRay, // TraceRay should only use RTAccelerationStructure
+  InstrResourceMapToSingleEntry, // Fail to map resource to resource table
   InstrResourceOffsetMiss, // offset uninitialized
   InstrResourceOffsetTooMany, // out of bound offset must be undef
+  InstrResourceUser, // Resource should only used by Load/GEP/Call
   InstrSampleCompType, // sample_* instructions require resource to be declared to return UNORM, SNORM or FLOAT.
   InstrSampleIndexForLoad2DMS, // load on Texture2DMS/2DMSArray require sampleIndex
   InstrSamplerModeForLOD, // lod instruction requires sampler declared in default mode
@@ -178,6 +182,7 @@ enum class ValidationRule : unsigned {
   FlowReducible, // Execution flow must be reducible
 
   // Shader model
+  Sm64bitRawBufferLoadStore, // i64/f64 rawBufferLoad/Store overloads are allowed after SM 6.3
   SmAppendAndConsumeOnSameUAV, // BufferUpdateCounter inc and dec on a given UAV (%d) cannot both be in the same shader for shader model less than 5.1.
   SmCBufferElementOverflow, // CBuffer elements must not overflow
   SmCBufferOffsetOverlap, // CBuffer offsets must not overlap

+ 307 - 505
lib/HLSL/DxilValidation.cpp

@@ -164,6 +164,9 @@ const char *hlsl::GetValidationRuleText(ValidationRule value) {
     case hlsl::ValidationRule::InstrResourceClassForSamplerGather: return "sample, lod and gather should on srv resource.";
     case hlsl::ValidationRule::InstrResourceClassForUAVStore: return "store should on uav resource.";
     case hlsl::ValidationRule::InstrResourceClassForLoad: return "load can only run on UAV/SRV resource";
+    case hlsl::ValidationRule::InstrResourceMapToSingleEntry: return "Fail to map resource to resource table";
+    case hlsl::ValidationRule::InstrResourceUser: return "Resource should only used by Load/GEP/Call";
+    case hlsl::ValidationRule::InstrResourceKindForTraceRay: return "TraceRay should only use RTAccelerationStructure";
     case hlsl::ValidationRule::InstrOffsetOnUAVLoad: return "uav load don't support offset";
     case hlsl::ValidationRule::InstrMipOnUAVLoad: return "uav load don't support mipLevel/sampleIndex";
     case hlsl::ValidationRule::InstrSampleIndexForLoad2DMS: return "load on Texture2DMS/2DMSArray require sampleIndex";
@@ -174,6 +177,7 @@ const char *hlsl::GetValidationRuleText(ValidationRule value) {
     case hlsl::ValidationRule::InstrDxilStructUserOutOfBound: return "Index out of bound when extract value from dxil struct types";
     case hlsl::ValidationRule::InstrHandleNotFromCreateHandle: return "Resource handle should returned by createHandle";
     case hlsl::ValidationRule::InstrBufferUpdateCounterOnUAV: return "BufferUpdateCounter valid only on UAV";
+    case hlsl::ValidationRule::InstrBufferUpdateCounterOnResHasCounter: return "BufferUpdateCounter valid only when HasCounter is true";
     case hlsl::ValidationRule::InstrCBufferOutOfBound: return "Cbuffer access out of bound";
     case hlsl::ValidationRule::InstrCBufferClassForCBufferHandle: return "Expect Cbuffer for CBufferLoad handle";
     case hlsl::ValidationRule::InstrFailToResloveTGSMPointer: return "TGSM pointers must originate from an unambiguous TGSM global variable.";
@@ -240,6 +244,7 @@ const char *hlsl::GetValidationRuleText(ValidationRule value) {
     case hlsl::ValidationRule::SmCBufferElementOverflow: return "CBuffer %0 size insufficient for element at offset %1";
     case hlsl::ValidationRule::SmOpcodeInInvalidFunction: return "opcode '%0' should only be used in '%1'";
     case hlsl::ValidationRule::SmViewIDNeedsSlot: return "Pixel shader input signature lacks available space for ViewID";
+    case hlsl::ValidationRule::Sm64bitRawBufferLoadStore: return "i64/f64 rawBufferLoad/Store overloads are allowed after SM 6.3";
     case hlsl::ValidationRule::UniNoWaveSensitiveGradient: return "Gradient operations are not affected by wave-sensitive data or control flow.";
     case hlsl::ValidationRule::FlowReducible: return "Execution flow must be reducible";
     case hlsl::ValidationRule::FlowNoRecusion: return "Recursion is not permitted";
@@ -366,8 +371,7 @@ struct ValidationContext {
   std::unordered_set<Function *> patchConstFuncCallSet;
   std::unordered_map<unsigned, bool> UavCounterIncMap;
   // TODO: save resource map for each createHandle/createHandleForLib.
-  std::unordered_map<Type *, DxilResourceBase *> ResTypeMap;
-  std::unordered_map<MDNode *, std::unique_ptr<DxilResourceBase>> ResInParam;
+  std::unordered_map<Value *, DxilResourceBase *> ResMap;
   std::unordered_map<Function *, std::vector<Function*>> PatchConstantFuncMap;
   std::unordered_map<Function *, std::unique_ptr<EntryStatus>> entryStatusMap;
   bool isLibProfile;
@@ -400,19 +404,7 @@ struct ValidationContext {
     }
 
     isLibProfile = dxilModule.GetShaderModel()->IsLib();
-    if (isLibProfile) {
-      auto collectResTy = [&](auto &ResTab) {
-        for (auto &Res : ResTab) {
-          Type *Ty = Res->GetGlobalSymbol()->getType()->getPointerElementType();
-          Ty = dxilutil::GetArrayEltTy(Ty);
-          ResTypeMap[Ty] = Res.get();
-        }
-      };
-      collectResTy(DxilMod.GetCBuffers());
-      collectResTy(DxilMod.GetUAVs());
-      collectResTy(DxilMod.GetSRVs());
-      collectResTy(DxilMod.GetSamplers());
-    }
+    BuildResMap();
     // Collect patch constant map.
     if (isLibProfile) {
       for (Function &F : dxilModule.GetModule()->functions()) {
@@ -439,74 +431,147 @@ struct ValidationContext {
     }
   }
 
-  bool HasEntryStatus(Function *F) {
-    return entryStatusMap.find(F) != entryStatusMap.end();
+  void PropagateResMap(Value *V, DxilResourceBase *Res) {
+    auto it = ResMap.find(V);
+    if (it != ResMap.end()) {
+      if (it->second != Res) {
+        EmitError(ValidationRule::InstrResourceMapToSingleEntry);
+      }
+    } else {
+      ResMap[V] = Res;
+      for (User *U : V->users()) {
+        if (GEPOperator *GEP = dyn_cast<GEPOperator>(U)) {
+          PropagateResMap(U, Res);
+        } else if (CallInst *CI = dyn_cast<CallInst>(U)) {
+          // Stop propagate on function call.
+          DxilInst_CreateHandleForLib hdl(CI);
+          if (hdl) {
+            ResMap[CI] = Res;
+          }
+        } else if (LoadInst *LI = dyn_cast<LoadInst>(U)) {
+          PropagateResMap(U, Res);
+        } else {
+          EmitError(ValidationRule::InstrResourceUser);
+        }
+      }
+    }
   }
 
-  EntryStatus &GetEntryStatus(Function *F) { return *entryStatusMap[F]; }
+  void BuildResMap() {
+    hlsl::OP *hlslOP = DxilMod.GetOP();
 
-  DxilResourceBase *GetResFromTy(Type *Ty) {
-    auto it = ResTypeMap.find(Ty);
-    if (it == ResTypeMap.end())
-      return nullptr;
-    else
-      return it->second;
-  }
-
-  DxilResourceBase *GetResourceFromMetadata(MDNode *Node) {
-    auto it = ResInParam.find(Node);
-    if (it != ResInParam.end())
-      return it->second.get();
-    DxilResourceBase Res(DxilResource::Class::Invalid);
-    DxilMod.LoadDxilResourceBaseFromMDNode(Node, Res);
-
-    std::unique_ptr<DxilResourceBase> ResBasePtr = nullptr;
-    switch (Res.GetClass()) {
-    case DXIL::ResourceClass::CBuffer: {
-      std::unique_ptr<DxilCBuffer> ResPtr = llvm::make_unique<DxilCBuffer>();
-      // TODO: set more field.
-      ResPtr->SetKind(Res.GetKind());
-      ResBasePtr = std::unique_ptr<DxilResourceBase>(ResPtr.release());
-    } break;
-    case DXIL::ResourceClass::Sampler: {
-      DxilSampler Res;
-      DxilMod.LoadDxilSamplerFromMDNode(Node, Res);
-      std::unique_ptr<DxilSampler> ResPtr = llvm::make_unique<DxilSampler>();
-      // TODO: set more field.
-      ResPtr->SetKind(Res.GetKind());
-      ResPtr->SetSamplerKind(Res.GetSamplerKind());
-      ResBasePtr = std::unique_ptr<DxilResourceBase>(ResPtr.release());
-    } break;
-    case DXIL::ResourceClass::SRV: {
-      DxilResource Res;
-      DxilMod.LoadDxilResourceFromMDNode(Node, Res);
-      std::unique_ptr<DxilResource> ResPtr = llvm::make_unique<DxilResource>();
-      // TODO: set more field.
-      ResPtr->SetKind(Res.GetKind());
-      ResPtr->SetRW(false);
-      ResBasePtr = std::unique_ptr<DxilResourceBase>(ResPtr.release());
-    } break;
-    case DXIL::ResourceClass::UAV: {
-      DxilResource Res;
-      DxilMod.LoadDxilResourceFromMDNode(Node, Res);
-      std::unique_ptr<DxilResource> ResPtr = llvm::make_unique<DxilResource>();
-      // TODO: set more field.
-      ResPtr->SetKind(Res.GetKind());
-      ResPtr->SetRW(true);
-      ResPtr->SetHasCounter(Res.HasCounter());
-      ResBasePtr = std::unique_ptr<DxilResourceBase>(ResPtr.release());
-    } break;
-    default:
-      return nullptr;
+    if (isLibProfile) {
+      std::unordered_set<Value *> ResSet;
+      // Start from all global variable in resTab.
+      auto collectRes = [&](auto &ResTab) {
+        for (auto &Res : ResTab) {
+          PropagateResMap(Res->GetGlobalSymbol(), Res.get());
+        }
+      };
+
+      collectRes(DxilMod.GetCBuffers());
+      collectRes(DxilMod.GetUAVs());
+      collectRes(DxilMod.GetSRVs());
+      collectRes(DxilMod.GetSamplers());
+    } else {
+      // Scan all createHandle.
+      for (auto &it : hlslOP->GetOpFuncList(DXIL::OpCode::CreateHandle)) {
+        Function *F = it.second;
+        if (!F)
+          continue;
+        for (User *U : F->users()) {
+          CallInst *CI = cast<CallInst>(U);
+          DxilInst_CreateHandle hdl(CI);
+          // Validate Class/RangeID/Index.
+          Value *resClass = hdl.get_resourceClass();
+          if (!isa<ConstantInt>(resClass)) {
+            EmitInstrError(CI, ValidationRule::InstrOpConstRange);
+            continue;
+          }
+          Value *rangeIndex = hdl.get_rangeId();
+          if (!isa<ConstantInt>(rangeIndex)) {
+            EmitInstrError(CI, ValidationRule::InstrOpConstRange);
+            continue;
+          }
+
+          DxilResourceBase *Res = nullptr;
+          unsigned rangeId = hdl.get_rangeId_val();
+          switch (
+              static_cast<DXIL::ResourceClass>(hdl.get_resourceClass_val())) {
+          default:
+            EmitInstrError(CI, ValidationRule::InstrOpConstRange);
+            continue;
+            break;
+          case DXIL::ResourceClass::CBuffer:
+            if (DxilMod.GetCBuffers().size() > rangeId) {
+              Res = &DxilMod.GetCBuffer(rangeId);
+            } else {
+              // Emit Error.
+              EmitInstrError(CI, ValidationRule::InstrOpConstRange);
+              continue;
+            }
+            break;
+          case DXIL::ResourceClass::Sampler:
+            if (DxilMod.GetSamplers().size() > rangeId) {
+              Res = &DxilMod.GetSampler(rangeId);
+            } else {
+              // Emit Error.
+              EmitInstrError(CI, ValidationRule::InstrOpConstRange);
+              continue;
+            }
+            break;
+          case DXIL::ResourceClass::SRV:
+            if (DxilMod.GetSRVs().size() > rangeId) {
+              Res = &DxilMod.GetSRV(rangeId);
+            } else {
+              // Emit Error.
+              EmitInstrError(CI, ValidationRule::InstrOpConstRange);
+              continue;
+            }
+            break;
+          case DXIL::ResourceClass::UAV:
+            if (DxilMod.GetUAVs().size() > rangeId) {
+              Res = &DxilMod.GetUAV(rangeId);
+            } else {
+              // Emit Error.
+              EmitInstrError(CI, ValidationRule::InstrOpConstRange);
+              continue;
+            }
+            break;
+          }
+
+          ConstantInt *cIndex = dyn_cast<ConstantInt>(hdl.get_index());
+          if (!Res->GetGlobalSymbol()
+                   ->getType()
+                   ->getPointerElementType()
+                   ->isArrayTy()) {
+            if (!cIndex) {
+              // index must be 0 for none array resource.
+              EmitInstrError(CI, ValidationRule::InstrOpConstRange);
+              continue;
+            }
+          }
+          if (cIndex) {
+            unsigned index = cIndex->getLimitedValue();
+            if (index < Res->GetLowerBound() || index > Res->GetUpperBound()) {
+              // index out of range.
+              EmitInstrError(CI, ValidationRule::InstrOpConstRange);
+              continue;
+            }
+          }
+
+          ResMap[CI] = Res;
+        }
+      }
     }
+  }
 
-    DxilResourceBase *Ptr = ResBasePtr.get();
-    ResInParam[Node] = std::move(ResBasePtr);
-    return Ptr;
+  bool HasEntryStatus(Function *F) {
+    return entryStatusMap.find(F) != entryStatusMap.end();
   }
 
-  DxilResourceBase *GetResourceFromResPtr(Value *resVal,
-                                          std::deque<unsigned> &offsets);
+  EntryStatus &GetEntryStatus(Function *F) { return *entryStatusMap[F]; }
+
   DxilResourceBase *GetResourceFromVal(Value *resVal);
 
   // Provide direct access to the raw_ostream in DiagPrinter.
@@ -832,129 +897,26 @@ ValidateSignatureAccess(Instruction *I, DxilSignature &sig, Value *sigID,
   return &SE;
 }
 
-static CallInst *GetHandleFromValue(Value *V, DenseSet<Value *> &Checked);
-static CallInst *GetHandleFromPhi(PHINode *Phi, DenseSet<Value *> &Checked) {
-  // TODO: validate all incoming values for phi is same kind and class.
-  for (Value *V : Phi->incoming_values()) {
-    if (CallInst *CI = GetHandleFromValue(V, Checked))
-      return CI;
-  }
-  return nullptr;
-}
-static CallInst *GetHandleFromSelect(SelectInst *Sel, DenseSet<Value *> &Checked) {
-  // TODO: validate all incoming values for select is same kind and class.
-  for (Value *V = Sel->getTrueValue(), *F = Sel->getFalseValue(); V != F; V = F) {
-    if (CallInst *CI = GetHandleFromValue(V, Checked))
-      return CI;
-  }
-  return nullptr;
-}
-static CallInst *GetHandleFromValue(Value *V, DenseSet<Value *> &Checked) {
-  if (!Checked.count(V)) {
-    Checked.insert(V);
-    if (CallInst *CI = dyn_cast<CallInst>(V)) {
-      return CI;
-    }
-    else if (PHINode *P = dyn_cast<PHINode>(V)) {
-      if (CallInst *CI = GetHandleFromPhi(P, Checked)) {
-        return CI;
-      }
-    }
-    else if (SelectInst *S = dyn_cast<SelectInst>(V)) {
-      if (CallInst *CI = GetHandleFromSelect(S, Checked)) {
-        return CI;
-      }
-    }
-  }
-  return nullptr;
-}
-
 static DXIL::SamplerKind GetSamplerKind(Value *samplerHandle,
                                         ValidationContext &ValCtx) {
   if (!isa<CallInst>(samplerHandle)) {
-    DenseSet<Value *> Checked;
-    if (CallInst *CI = GetHandleFromValue(samplerHandle, Checked)) {
-      samplerHandle = CI;
-    } else {
-      ValCtx.EmitError(ValidationRule::InstrHandleNotFromCreateHandle);
-      return DXIL::SamplerKind::Invalid;
-    }
+    ValCtx.EmitError(ValidationRule::InstrHandleNotFromCreateHandle);
+    return DXIL::SamplerKind::Invalid;
   }
 
-  DxilInst_CreateHandle createHandle(cast<CallInst>(samplerHandle));
-  if (!createHandle) {
-    auto EmitError = [&]() -> DXIL::SamplerKind {
+  DxilResourceBase *Res = ValCtx.GetResourceFromVal(samplerHandle);
+  if (!Res) {
       ValCtx.EmitInstrError(cast<CallInst>(samplerHandle),
-                            ValidationRule::InstrHandleNotFromCreateHandle);
+          ValidationRule::InstrHandleNotFromCreateHandle);
       return DXIL::SamplerKind::Invalid;
-    };
-    if (!ValCtx.isLibProfile) {
-      return EmitError();
-    }
-
-    DxilInst_CreateHandleForLib createHandleFromRes(
-        cast<CallInst>(samplerHandle));
-    if (!createHandleFromRes) {
-      return EmitError();
-    }
-
-    DxilResourceBase *Res =
-        ValCtx.GetResFromTy(createHandleFromRes.get_Resource()->getType());
-    if (!Res) {
-      Res = ValCtx.GetResourceFromVal(createHandleFromRes.get_Resource());
-      if (!Res)
-        return EmitError();
-    }
-    if (Res->GetClass() == DXIL::ResourceClass::Sampler) {
-      DxilSampler *S = (DxilSampler *)(Res);
-      return S->GetSamplerKind();
-    } else {
-      return EmitError();
-    }
   }
 
-  Value *resClass = createHandle.get_resourceClass();
-  if (!isa<ConstantInt>(resClass)) {
-    return DXIL::SamplerKind::Invalid;
-  }
-
-  if (createHandle.get_resourceClass_val() != static_cast<unsigned>(DXIL::ResourceClass::Sampler)) {
+  if (Res->GetClass() != DXIL::ResourceClass::Sampler) {
     // must be sampler.
     return DXIL::SamplerKind::Invalid;
   }
 
-  Value *rangeIndex = createHandle.get_rangeId();
-  if (!isa<ConstantInt>(rangeIndex)) {
-    // must be constant
-    return DXIL::SamplerKind::Invalid;
-  }
-  unsigned samplerIndex = cast<ConstantInt>(rangeIndex)->getLimitedValue();
-  auto &samplers = ValCtx.DxilMod.GetSamplers();
-  if (samplerIndex >= samplers.size()) {
-    return DXIL::SamplerKind::Invalid;
-  }
-
-  DxilSampler *sampler = samplers[samplerIndex].get();
-
-  Value *index = createHandle.get_index();
-  ConstantInt *cIndex = dyn_cast<ConstantInt>(index);
-
-  if (!sampler->GetGlobalSymbol()->getType()->getPointerElementType()->isArrayTy()) {
-    if (!cIndex) {
-      // index must be 0 for none array resource.
-      return DXIL::SamplerKind::Invalid;
-    }
-  }
-
-  if (cIndex) {
-    unsigned index = cIndex->getLimitedValue();
-    if (index < sampler->GetLowerBound() || index > sampler->GetUpperBound()) {
-      // index out of range.
-      return DXIL::SamplerKind::Invalid;
-    }
-  }
-
-  return sampler->GetSamplerKind();
+  return ((DxilSampler*)Res)->GetSamplerKind();
 }
 
 static DXIL::ResourceKind GetResourceKindAndCompTy(Value *handle, DXIL::ComponentType &CompTy, DXIL::ResourceClass &ResClass,
@@ -963,56 +925,19 @@ static DXIL::ResourceKind GetResourceKindAndCompTy(Value *handle, DXIL::Componen
   CompTy = DXIL::ComponentType::Invalid;
   ResClass = DXIL::ResourceClass::Invalid;
   if (!isa<CallInst>(handle)) {
-    DenseSet<Value *> Checked;
-    if (CallInst *CI = GetHandleFromValue(handle, Checked)) {
-      handle = CI;
-    } else {
-      ValCtx.EmitError(ValidationRule::InstrHandleNotFromCreateHandle);
-      return DXIL::ResourceKind::Invalid;
-    }
+    ValCtx.EmitError(ValidationRule::InstrHandleNotFromCreateHandle);
+    return DXIL::ResourceKind::Invalid;
   }
   // TODO: validate ROV is used only in PS.
 
-  DxilInst_CreateHandle createHandle(cast<CallInst>(handle));
-  if (!createHandle) {
-    auto EmitError = [&]() -> DXIL::ResourceKind {
-      ValCtx.EmitInstrError(cast<CallInst>(handle),
-                            ValidationRule::InstrHandleNotFromCreateHandle);
-      return DXIL::ResourceKind::Invalid;
-    };
-    if (!ValCtx.isLibProfile) {
-      return EmitError();
-    }
-    DxilInst_CreateHandleForLib createHandleFromRes(
-        cast<CallInst>(handle));
-    if (!createHandleFromRes) {
-      return EmitError();
-    }
-    DxilResourceBase *res =
-        ValCtx.GetResFromTy(createHandleFromRes.get_Resource()->getType());
-    if (!res) {
-      res = ValCtx.GetResourceFromVal(createHandleFromRes.get_Resource());
-      if (!res)
-        return EmitError();
-    }
-    // TODO: resIndex for Uav Counter.
-    if (res->GetClass() == DXIL::ResourceClass::UAV ||
-        res->GetClass() == DXIL::ResourceClass::SRV) {
-      DxilResource *Res = (DxilResource*)(res);
-      CompTy = Res->GetCompType().GetKind();
-    } else {
-      return EmitError();
-    }
-    ResClass = res->GetClass();
-    return res->GetKind();
-  }
-
-  Value *resourceClass = createHandle.get_resourceClass();
-  if (!isa<ConstantInt>(resourceClass)) {
+  DxilResourceBase *Res = ValCtx.GetResourceFromVal(handle);
+  if (!Res) {
+    ValCtx.EmitInstrError(cast<CallInst>(handle),
+                          ValidationRule::InstrHandleNotFromCreateHandle);
     return DXIL::ResourceKind::Invalid;
   }
 
-  ResClass = static_cast<DXIL::ResourceClass>(createHandle.get_resourceClass_val());
+  ResClass = Res->GetClass();
 
   switch (ResClass) {
   case DXIL::ResourceClass::SRV:
@@ -1027,53 +952,11 @@ static DXIL::ResourceKind GetResourceKindAndCompTy(Value *handle, DXIL::Componen
     return DXIL::ResourceKind::Invalid;
   }
 
-  Value *rangeIndex = createHandle.get_rangeId();
-  if (!isa<ConstantInt>(rangeIndex)) {
-    ValCtx.EmitInstrError(cast<CallInst>(handle),
-                          ValidationRule::InstrCreateHandleImmRangeID);
-    // must be constant
-    return DXIL::ResourceKind::Invalid;
-  }
-  resIndex = cast<ConstantInt>(rangeIndex)->getLimitedValue();
-
-  DxilResource *res = nullptr;
-  if (ResClass == DXIL::ResourceClass::UAV) {
-    auto &resources = ValCtx.DxilMod.GetUAVs();
-    if (resIndex >= resources.size()) {
-      return DXIL::ResourceKind::Invalid;
-    }
-    res = resources[resIndex].get();
-  } else {
-    if (ResClass != DXIL::ResourceClass::SRV) {
-      return DXIL::ResourceKind::Invalid;
-    }
-    auto &resources = ValCtx.DxilMod.GetSRVs();
-    if (resIndex >= resources.size()) {
-      return DXIL::ResourceKind::Invalid;
-    }
-    res = resources[resIndex].get();
-  }
-
-  CompTy = res->GetCompType().GetKind();
+  resIndex = Res->GetID();
 
-  Value *index = createHandle.get_index();
-  ConstantInt *cIndex = dyn_cast<ConstantInt>(index);
+  CompTy = ((DxilResource*)Res)->GetCompType().GetKind();
 
-  if (!res->GetGlobalSymbol()->getType()->getPointerElementType()->isArrayTy()) {
-    if (!cIndex) {
-      // index must be 0 for none array resource.
-      return DXIL::ResourceKind::Invalid;
-    }
-  }
-  if (cIndex) {
-    unsigned index = cIndex->getLimitedValue();
-    if (index < res->GetLowerBound() || index > res->GetUpperBound()) {
-      // index out of range.
-      return DXIL::ResourceKind::Invalid;
-    }
-  }
-
-  return res->GetKind();
+  return Res->GetKind();
 }
 
 DxilFieldAnnotation *GetFieldAnnotation(Type *Ty,
@@ -1105,168 +988,29 @@ DxilFieldAnnotation *GetFieldAnnotation(Type *Ty,
   return nullptr;
 }
 
-DxilResourceBase *
-ValidationContext::GetResourceFromResPtr(Value *resPtr,
-                                         std::deque<unsigned> &offsets) {
-  if (GlobalVariable *GV = dyn_cast<GlobalVariable>(resPtr)) {
-    auto FindRes = [&](auto &ResTab) -> DxilResourceBase * {
-      for (auto &UAV : ResTab) {
-        if (UAV->GetGlobalSymbol() == GV) {
-          return UAV.get();
-        }
-      }
-      return nullptr;
-    };
-    DxilResourceBase *Res = FindRes(DxilMod.GetUAVs());
-    if (Res)
-      return Res;
-    Res = FindRes(DxilMod.GetSRVs());
-    if (Res)
-      return Res;
-    Res = FindRes(DxilMod.GetCBuffers());
-    if (Res)
-      return Res;
-    return FindRes(DxilMod.GetSamplers());
-  } else if (Argument *Arg = dyn_cast<Argument>(resPtr)) {
-    Function *F = Arg->getParent();
-    auto &typeSys = DxilMod.GetTypeSystem();
-    if (auto *FunctionAnnot = typeSys.GetFunctionAnnotation(F)) {
-      FunctionType *FT = F->getFunctionType();
-      auto &ParamAnnot = FunctionAnnot->GetParameterAnnotation(Arg->getArgNo());
-      if (offsets.size() == 1) {
-        MDNode *Node = ParamAnnot.GetResourceAttribute();
-        if (!Node)
-          return nullptr;
-        return GetResourceFromMetadata(Node);
-      } else {
-        Type *Ty = FT->getParamType(Arg->getArgNo());
-        if (!isa<PointerType>(Ty))
-          return nullptr;
-        Ty = Ty->getPointerElementType();
-        if (!isa<StructType>(Ty))
-          return nullptr;
-        if (DxilFieldAnnotation *fieldAnnot =
-                GetFieldAnnotation(Ty, typeSys, offsets)) {
-          MDNode *Node = fieldAnnot->GetResourceAttribute();
-          if (!Node)
-            return nullptr;
-          return GetResourceFromMetadata(Node);
-        } else {
-          return nullptr;
-        }
-      }
-    } else {
-      return nullptr;
-    }
-  } else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(resPtr)) {
-    auto it = GEP->idx_begin();
-    auto end = GEP->idx_end();
-    // Skip first 0.
-    it++;
-    for (; it != end; it++) {
-      if (ConstantInt *idx = dyn_cast<ConstantInt>(*it)) {
-        offsets.emplace_back(idx->getLimitedValue());
-      } else {
-        offsets.emplace_back(0);
-      }
-    }
-    return GetResourceFromResPtr(GEP->getPointerOperand(), offsets);
-  } else if (AllocaInst *AI = dyn_cast<AllocaInst>(resPtr)) {
-    Type *Ty = AI->getAllocatedType();
-    auto &typeSys = DxilMod.GetTypeSystem();
-    while (isa<ArrayType>(Ty)) {
-      Ty = Ty->getArrayElementType();
-      offsets.pop_front();
-    }
-    if (offsets.size() == 1) {
-      // Try to find info from function call.
-      // Assume alloca of resource must be used by a function call.
-      for (User *U : AI->users()) {
-        if (CallInst *CI = dyn_cast<CallInst>(U)) {
-          for (unsigned i = 0; i < CI->getNumArgOperands(); i++) {
-            if (CI->getArgOperand(i) == AI) {
-              Function *F = CI->getCalledFunction();
-              if (auto *FunctionAnnot = typeSys.GetFunctionAnnotation(F)) {
-                auto &ParamAnnot = FunctionAnnot->GetParameterAnnotation(i);
-                if (offsets.size() == 1) {
-                  MDNode *Node = ParamAnnot.GetResourceAttribute();
-                  if (!Node)
-                    return nullptr;
-                  return GetResourceFromMetadata(Node);
-                }
-              }
-              break;
-            }
-          }
-        }
-      }
-      return nullptr;
-    } else if (DxilFieldAnnotation *fieldAnnot =
-                   GetFieldAnnotation(Ty, typeSys, offsets)) {
-      MDNode *Node = fieldAnnot->GetResourceAttribute();
-      if (!Node)
-        return nullptr;
-      return GetResourceFromMetadata(Node);
-    } else {
-      return nullptr;
-    }
-
-  } else {
-    return nullptr;
-  }
-}
 
 DxilResourceBase *ValidationContext::GetResourceFromVal(Value *resVal) {
-  if (LoadInst *LI = dyn_cast<LoadInst>(resVal)) {
-    // Add the first 0 for pointer.
-    std::deque<unsigned> offsets(1, 0);
-    DxilResourceBase *Res = GetResourceFromResPtr(LI->getPointerOperand(), offsets);
-    if (Res)
-      ResTypeMap[LI->getType()] = Res;
-    return Res;
-  } else {
+  auto it = ResMap.find(resVal);
+  if (it != ResMap.end())
+    return it->second;
+  else
     return nullptr;
-  }
 }
 
 static DxilResource *GetResource(Value *handle, ValidationContext &ValCtx) {
   if (!isa<CallInst>(handle)) {
-    DenseSet<Value *> Checked;
-    if (CallInst *CI = GetHandleFromValue(handle, Checked)) {
-      handle = CI;
-    } else {
-      ValCtx.EmitError(ValidationRule::InstrHandleNotFromCreateHandle);
-      return nullptr;
-    }
-  }
-
-  DxilInst_CreateHandle createHandle(cast<CallInst>(handle));
-  if (!createHandle) {
-    auto EmitError = [&]() -> DXIL::ResourceKind {
-      ValCtx.EmitInstrError(cast<CallInst>(handle),
-                            ValidationRule::InstrHandleNotFromCreateHandle);
-      return DXIL::ResourceKind::Invalid;
-    };
-    if (!ValCtx.isLibProfile) {
-      EmitError();
-      return nullptr;
-    }
-    DxilInst_CreateHandleForLib createHandleFromRes(cast<CallInst>(handle));
-    if (!createHandleFromRes) {
-      EmitError();
-      return nullptr;
-    }
-    Value *resVal = createHandleFromRes.get_Resource();
-    return (DxilResource*)ValCtx.GetResourceFromVal(resVal);
+    ValCtx.EmitError(ValidationRule::InstrHandleNotFromCreateHandle);
+    return nullptr;
   }
 
-  Value *resourceClass = createHandle.get_resourceClass();
-  if (!isa<ConstantInt>(resourceClass)) {
+  DxilResourceBase *Res = ValCtx.GetResourceFromVal(handle);
+  if (!Res) {
+    ValCtx.EmitInstrError(cast<CallInst>(handle),
+                          ValidationRule::InstrHandleNotFromCreateHandle);
     return nullptr;
   }
 
-  DXIL::ResourceClass ResClass =
-      static_cast<DXIL::ResourceClass>(createHandle.get_resourceClass_val());
+  DXIL::ResourceClass ResClass = Res->GetClass();
 
   switch (ResClass) {
   case DXIL::ResourceClass::SRV:
@@ -1281,33 +1025,7 @@ static DxilResource *GetResource(Value *handle, ValidationContext &ValCtx) {
     return nullptr;
   }
 
-  Value *rangeIndex = createHandle.get_rangeId();
-  if (!isa<ConstantInt>(rangeIndex)) {
-    ValCtx.EmitInstrError(cast<CallInst>(handle),
-                          ValidationRule::InstrCreateHandleImmRangeID);
-    // must be constant
-    return nullptr;
-  }
-  unsigned resIndex = cast<ConstantInt>(rangeIndex)->getLimitedValue();
-
-  DxilResource *res = nullptr;
-  if (ResClass == DXIL::ResourceClass::UAV) {
-    auto &resources = ValCtx.DxilMod.GetUAVs();
-    if (resIndex >= resources.size()) {
-      return nullptr;
-    }
-    res = resources[resIndex].get();
-  } else {
-    if (ResClass != DXIL::ResourceClass::SRV) {
-      return nullptr;
-    }
-    auto &resources = ValCtx.DxilMod.GetSRVs();
-    if (resIndex >= resources.size()) {
-      return nullptr;
-    }
-    res = resources[resIndex].get();
-  }
-  return res;
+  return (DxilResource *)Res;
 }
 
 struct ResRetUsage {
@@ -1560,68 +1278,24 @@ static unsigned StoreValueToMask(ArrayRef<Value *> vals) {
 
 static int GetCBufSize(Value *cbHandle, ValidationContext &ValCtx) {
   if (!isa<CallInst>(cbHandle)) {
-    DenseSet<Value *> Checked;
-    if (CallInst *CI = GetHandleFromValue(cbHandle, Checked)) {
-      cbHandle = CI;
-    } else {
-      ValCtx.EmitError(ValidationRule::InstrHandleNotFromCreateHandle);
-      return -1;
-    }
-  }
-  DxilInst_CreateHandle createHandle(cast<CallInst>(cbHandle));
-  if (!createHandle) {
-    auto EmitError = [&]() -> int {
-      ValCtx.EmitInstrError(cast<CallInst>(cbHandle),
-                            ValidationRule::InstrHandleNotFromCreateHandle);
-      return -1;
-    };
-    if (!ValCtx.isLibProfile) {
-      return EmitError();
-    }
-    DxilInst_CreateHandleForLib createHandleFromRes(
-        cast<CallInst>(cbHandle));
-    if (!createHandleFromRes) {
-      return EmitError();
-    }
-
-    DxilResourceBase *Res =
-        ValCtx.GetResFromTy(createHandleFromRes.get_Resource()->getType());
-    if (!Res) {
-      Res = ValCtx.GetResourceFromVal(createHandleFromRes.get_Resource());
-      if (!Res)
-        return EmitError();
-    }
-    if (Res->GetClass() == DXIL::ResourceClass::CBuffer) {
-      DxilCBuffer *CB = (DxilCBuffer *)(Res);
-      return CB->GetSize();
-    } else {
-      return EmitError();
-    }
-  }
-
-  Value *resourceClass = createHandle.get_resourceClass();
-  if (!isa<ConstantInt>(resourceClass)) {
-    ValCtx.EmitInstrError(cast<CallInst>(cbHandle),
-                          ValidationRule::InstrOpConstRange);
+    ValCtx.EmitError(ValidationRule::InstrHandleNotFromCreateHandle);
     return -1;
   }
 
-  if (static_cast<DXIL::ResourceClass>(createHandle.get_resourceClass_val()) !=
-      DXIL::ResourceClass::CBuffer) {
-    ValCtx.EmitInstrError(cast<CallInst>(cbHandle), ValidationRule::InstrCBufferClassForCBufferHandle);
+  DxilResourceBase *Res = ValCtx.GetResourceFromVal(cbHandle);
+  if (!Res) {
+    ValCtx.EmitInstrError(cast<CallInst>(cbHandle),
+                          ValidationRule::InstrHandleNotFromCreateHandle);
     return -1;
   }
 
-  Value *rangeIndex = createHandle.get_rangeId();
-  if (!isa<ConstantInt>(rangeIndex)) {
+  if (Res->GetClass() != DXIL::ResourceClass::CBuffer) {
     ValCtx.EmitInstrError(cast<CallInst>(cbHandle),
-                          ValidationRule::InstrOpConstRange);
+                          ValidationRule::InstrCBufferClassForCBufferHandle);
     return -1;
   }
 
-  DxilCBuffer &CB = ValCtx.DxilMod.GetCBuffer(
-      cast<ConstantInt>(rangeIndex)->getLimitedValue());
-  return CB.GetSize();
+  return ((DxilCBuffer *)Res)->GetSize();
 }
 
 static unsigned GetNumVertices(DXIL::InputPrimitive inputPrimitive) {
@@ -2407,6 +2081,133 @@ static void ValidateResourceDxilOp(CallInst *CI, DXIL::OpCode opcode,
       }
     }
   } break;
+  case DXIL::OpCode::RawBufferLoad: {
+    hlsl::OP *hlslOP = ValCtx.DxilMod.GetOP();
+    if (!ValCtx.DxilMod.GetShaderModel()->IsSM63Plus()) {
+      Type *Ty = hlslOP->GetOverloadType(DXIL::OpCode::RawBufferLoad,
+                                         CI->getCalledFunction());
+      if (ValCtx.DL.getTypeAllocSizeInBits(Ty) > 32) {
+        ValCtx.EmitInstrError(CI, ValidationRule::Sm64bitRawBufferLoadStore);
+      }
+    }
+    DxilInst_RawBufferLoad bufLd(CI);
+    DXIL::ComponentType compTy;
+    DXIL::ResourceClass resClass;
+    unsigned resIndex;
+    DXIL::ResourceKind resKind = GetResourceKindAndCompTy(
+        bufLd.get_srv(), compTy, resClass, resIndex, ValCtx);
+
+    if (resClass != DXIL::ResourceClass::SRV &&
+        resClass != DXIL::ResourceClass::UAV) {
+      ValCtx.EmitInstrError(CI, ValidationRule::InstrResourceClassForLoad);
+    }
+
+    Value *offset = bufLd.get_elementOffset();
+    Value *align = bufLd.get_alignment();
+    unsigned alignSize = 0;
+    if (!isa<ConstantInt>(align)) {
+      ValCtx.EmitInstrError(CI,
+                            ValidationRule::InstrCoordinateCountForRawTypedBuf);
+    } else {
+      alignSize = bufLd.get_alignment_val();
+    }
+    switch (resKind) {
+    case DXIL::ResourceKind::RawBuffer:
+      if (!isa<UndefValue>(offset)) {
+        ValCtx.EmitInstrError(
+            CI, ValidationRule::InstrCoordinateCountForRawTypedBuf);
+      }
+      break;
+    case DXIL::ResourceKind::StructuredBuffer:
+      if (isa<UndefValue>(offset)) {
+        ValCtx.EmitInstrError(CI,
+                              ValidationRule::InstrCoordinateCountForStructBuf);
+      }
+      break;
+    default:
+      ValCtx.EmitInstrError(
+          CI, ValidationRule::InstrResourceKindForBufferLoadStore);
+      break;
+    }
+  } break;
+  case DXIL::OpCode::RawBufferStore: {
+    hlsl::OP *hlslOP = ValCtx.DxilMod.GetOP();
+    if (!ValCtx.DxilMod.GetShaderModel()->IsSM63Plus()) {
+      Type *Ty = hlslOP->GetOverloadType(DXIL::OpCode::RawBufferStore,
+                                         CI->getCalledFunction());
+      if (ValCtx.DL.getTypeAllocSizeInBits(Ty) > 32) {
+        ValCtx.EmitInstrError(CI, ValidationRule::Sm64bitRawBufferLoadStore);
+      }
+    }
+    DxilInst_RawBufferStore bufSt(CI);
+    DXIL::ComponentType compTy;
+    DXIL::ResourceClass resClass;
+    unsigned resIndex;
+    DXIL::ResourceKind resKind = GetResourceKindAndCompTy(
+        bufSt.get_uav(), compTy, resClass, resIndex, ValCtx);
+
+    if (resClass != DXIL::ResourceClass::UAV) {
+      ValCtx.EmitInstrError(CI, ValidationRule::InstrResourceClassForUAVStore);
+    }
+
+    ConstantInt *mask = dyn_cast<ConstantInt>(bufSt.get_mask());
+    if (!mask) {
+      // Mask for buffer store should be immediate.
+      ValCtx.EmitInstrFormatError(CI, ValidationRule::InstrOpConst,
+                                  {"Mask", "BufferStore"});
+      return;
+    }
+    unsigned uMask = mask->getLimitedValue();
+    unsigned stValMask =
+        StoreValueToMask({bufSt.get_value0(), bufSt.get_value1(),
+                          bufSt.get_value2(), bufSt.get_value3()});
+
+    if (stValMask != uMask) {
+      ValCtx.EmitInstrFormatError(
+          CI, ValidationRule::InstrWriteMaskMatchValueForUAVStore,
+          {std::to_string(uMask), std::to_string(stValMask)});
+    }
+
+    Value *offset = bufSt.get_elementOffset();
+    Value *align = bufSt.get_alignment();
+    unsigned alignSize = 0;
+    if (!isa<ConstantInt>(align)) {
+      ValCtx.EmitInstrError(CI,
+                            ValidationRule::InstrCoordinateCountForRawTypedBuf);
+    } else {
+      alignSize = bufSt.get_alignment_val();
+    }
+    switch (resKind) {
+    case DXIL::ResourceKind::RawBuffer:
+      if (!isa<UndefValue>(offset)) {
+        ValCtx.EmitInstrError(
+            CI, ValidationRule::InstrCoordinateCountForRawTypedBuf);
+      }
+      break;
+    case DXIL::ResourceKind::StructuredBuffer:
+      if (isa<UndefValue>(offset)) {
+        ValCtx.EmitInstrError(CI,
+                              ValidationRule::InstrCoordinateCountForStructBuf);
+      }
+      break;
+    default:
+      ValCtx.EmitInstrError(
+          CI, ValidationRule::InstrResourceKindForBufferLoadStore);
+      break;
+    }
+  } break;
+  case DXIL::OpCode::TraceRay: {
+    DxilInst_TraceRay traceRay(CI);
+    Value *hdl = traceRay.get_AccelerationStructure();
+    DxilResourceBase *Res = ValCtx.GetResourceFromVal(hdl);
+    if (!Res) {
+      ValCtx.EmitInstrError(CI, ValidationRule::InstrResourceKindForTraceRay);
+      return;
+    }
+    if (Res->GetKind() != DXIL::ResourceKind::RTAccelerationStructure) {
+      ValCtx.EmitInstrError(CI, ValidationRule::InstrResourceKindForTraceRay);
+    }
+  } break;
   default:
     break;
   }
@@ -2486,7 +2287,8 @@ static void ValidateDxilOperationCallInProfile(CallInst *CI,
     }
 
     if (!res->HasCounter()) {
-      // TODO: Must has counter to run UpdateCounter.
+      ValCtx.EmitInstrError(
+          CI, ValidationRule::InstrBufferUpdateCounterOnResHasCounter);
     }
 
     Value *inc = updateCounter.get_inc();

+ 12 - 0
tools/clang/unittests/HLSL/ValidationTest.cpp

@@ -324,6 +324,7 @@ public:
   TEST_METHOD(UndefValueFail);
   TEST_METHOD(UpdateCounterFail);
   TEST_METHOD(LocalResCopy);
+  TEST_METHOD(ResCounter);
 
   TEST_METHOD(WhenSmUnknownThenFail);
   TEST_METHOD(WhenSmLegacyThenFail);
@@ -3211,6 +3212,17 @@ TEST_F(ValidationTest, Float32DenormModeAttribute) {
     true);
 }
 
+TEST_F(ValidationTest, ResCounter) {
+    if (m_ver.SkipDxilVersion(1, 3)) return;
+    RewriteAssemblyCheckMsg(
+        "RWStructuredBuffer<float4> buf; float GetCounter() {return buf.IncrementCounter();}",
+        "lib_6_3",
+        { "!\"buf\", i32 0, i32 -1, i32 1, i32 12, i1 false, i1 true, i1 false, !" },
+        { "!\"buf\", i32 0, i32 -1, i32 1, i32 12, i1 false, i1 false, i1 false, !" },
+        "BufferUpdateCounter valid only when HasCounter is true",
+        true);
+}
+
 TEST_F(ValidationTest, FunctionAttributes) {
   if (m_ver.SkipDxilVersion(1, 2)) return;
   std::vector<LPCWSTR> pArguments = { L"-denorm", L"ftz" };

+ 5 - 0
utils/hct/hctdb.py

@@ -1908,6 +1908,9 @@ class db_dxil(object):
         self.add_valrule("Instr.ResourceClassForSamplerGather", "sample, lod and gather should on srv resource.")
         self.add_valrule("Instr.ResourceClassForUAVStore", "store should on uav resource.")
         self.add_valrule("Instr.ResourceClassForLoad", "load can only run on UAV/SRV resource")
+        self.add_valrule("Instr.ResourceMapToSingleEntry", "Fail to map resource to resource table")
+        self.add_valrule("Instr.ResourceUser", "Resource should only used by Load/GEP/Call")
+        self.add_valrule("Instr.ResourceKindForTraceRay", "TraceRay should only use RTAccelerationStructure")
         self.add_valrule("Instr.OffsetOnUAVLoad", "uav load don't support offset")
         self.add_valrule("Instr.MipOnUAVLoad", "uav load don't support mipLevel/sampleIndex")
         self.add_valrule("Instr.SampleIndexForLoad2DMS", "load on Texture2DMS/2DMSArray require sampleIndex")
@@ -1918,6 +1921,7 @@ class db_dxil(object):
         self.add_valrule("Instr.DxilStructUserOutOfBound", "Index out of bound when extract value from dxil struct types")
         self.add_valrule("Instr.HandleNotFromCreateHandle", "Resource handle should returned by createHandle")
         self.add_valrule("Instr.BufferUpdateCounterOnUAV", "BufferUpdateCounter valid only on UAV")
+        self.add_valrule("Instr.BufferUpdateCounterOnResHasCounter", "BufferUpdateCounter valid only when HasCounter is true")
         self.add_valrule("Instr.CBufferOutOfBound", "Cbuffer access out of bound")
         self.add_valrule("Instr.CBufferClassForCBufferHandle", "Expect Cbuffer for CBufferLoad handle")
         self.add_valrule("Instr.FailToResloveTGSMPointer", "TGSM pointers must originate from an unambiguous TGSM global variable.")
@@ -1993,6 +1997,7 @@ class db_dxil(object):
         self.add_valrule_msg("Sm.CBufferElementOverflow", "CBuffer elements must not overflow", "CBuffer %0 size insufficient for element at offset %1")
         self.add_valrule_msg("Sm.OpcodeInInvalidFunction", "Invalid DXIL opcode usage like StorePatchConstant in patch constant function", "opcode '%0' should only be used in '%1'")
         self.add_valrule_msg("Sm.ViewIDNeedsSlot", "ViewID requires compatible space in pixel shader input signature", "Pixel shader input signature lacks available space for ViewID")
+        self.add_valrule("Sm.64bitRawBufferLoadStore", "i64/f64 rawBufferLoad/Store overloads are allowed after SM 6.3")
 
         # fxc relaxed check of gradient check.
         #self.add_valrule("Uni.NoUniInDiv", "TODO - No instruction requiring uniform execution can be present in divergent block")