瀏覽代碼

1. Clean more validation TODOs.
2. Support array of SV_Target.

Xiang Li 8 年之前
父節點
當前提交
245a771a85

+ 4 - 10
docs/DXIL.rst

@@ -2151,8 +2151,6 @@ INSTR.ERR_LOOP_CONDITION_OUT_OF_BOUNDS    TODO - cannot unroll loop with an out-
 INSTR.ERR_NON_LITERAL_RESOURCE            TODO - Resources being indexed cannot come from conditional expressions, they must come from literal expressions.
 INSTR.ERR_NON_LITERAL_STREAM              TODO - stream parameter must come from a literal expression
 INSTR.ERR_RESOURCE_UNINITIALIZED          TODO - Resource being indexed is uninitialized.
-INSTR.ERR_TEXTURE_OFFSET                  TODO - texture access must have literal offset and multisample index
-INSTR.ERR_TEXTURE_TYPE                    TODO - return type of texture too large. Cannot exceed 4 components
 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.FAILTORESLOVETGSMPOINTER            TGSM pointers must originate from an unambiguous TGSM global variable.
 INSTR.HANDLENOTFROMCREATEHANDLE           Resource handle should returned by createHandle
@@ -2200,6 +2198,7 @@ INSTR.SAMPLERMODEFORLOD                   lod instruction requires sampler decla
 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.TEXTURELOD                          TODO - Level-of-detail is only defined for Texture1D, Texture2D, Texture3D and TextureCube
+INSTR.TEXTUREOFFSET                       offset texture instructions must take offset which can resolve to integer literal in the range -8 to 7
 INSTR.TEXTUREOPARGS                       TODO - Instructions that depend on texture type must match operands
 INSTR.TYPECAST                            TODO - Type cast must be valid
 INSTR.UNDEFRESULTFORGETDIMENSION          GetDimensions used undef dimension %0 on %1
@@ -2232,6 +2231,7 @@ META.STRUCTBUFALIGNMENTOUTOFBOUND         StructuredBuffer stride out of bounds
 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                                 TODO - All metadata must be used
 META.VALIDSAMPLERMODE                     Invalid sampler mode on sampler
 META.VALUERANGE                           Metadata value must be within range
@@ -2246,7 +2246,6 @@ SM.CSNORETURN                             Compute shaders can't return values, o
 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.ERR_BIND_RESOURCE_RANGE_OVERFLOW       TODO - ERR_BIND_RESOURCE_RANGE_OVERFLOW
-SM.ERR_DUPLICATE_CBUFFER_BANK             TODO - ERR_DUPLICATE_CBUFFER_BANK
 SM.ERR_MAX_CBUFFER_EXCEEDED               TODO - The maximum number of constant buffer slots is exceeded for a library (slot index=%u, max slots=%u)
 SM.ERR_MAX_CONST_EXCEEDED                 TODO - ERR_MAX_CONST_EXCEEDED
 SM.ERR_MAX_SAMPLER_EXCEEDED               TODO - The maximum number of sampler slots is exceeded for a library (slot index=%u, max slots=%u)
@@ -2254,27 +2253,23 @@ SM.ERR_MAX_TEXTURE_EXCEEDED               TODO - The maximum number of texture s
 SM.ERR_UNABLE_TO_BIND_RESOURCE            TODO - ERR_UNABLE_TO_BIND_RESOURCE
 SM.ERR_UNABLE_TO_BIND_UNBOUNDED_RESOURCE  TODO - ERR_UNABLE_TO_BIND_UNBOUNDED_RESOURCE
 SM.GSINSTANCECOUNTRANGE                   GS instance count must be [1..%0].  %1 specified
-SM.GSOUTPUTLIMIT                          TODO - A geometry shader can output a maximum of 1024 32-bit values (including the size of the input data and the size of the data created by the shader)
 SM.GSOUTPUTVERTEXCOUNTRANGE               GS output vertex count must be [0..%0].  %1 specified
-SM.GSTOTALOUTPUTVERTEXDATARANGE           TODO: 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.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 [1..%0].  %1 specified
 SM.HULLPASSTHRUCONTROLPOINTCOUNTMATCH     For pass thru hull shader, input control point count must match output control point count
-SM.ICBLIMIT                               TODO - Constant buffers must contain at least one element, but no more than 4096 values
-SM.IDXTMPLIMIT                            TODO - Indexable temporaries must containt at least one element, but no more than 4096 values
 SM.INSIDETESSFACTORSIZEMATCHDOMAIN        InsideTessFactor size mismatch the domain.
 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.LIVELIMIT                              TODO - The total number of temporary and indexable-temporary registers (32-bit four-component values) must be less than or equal to 4096
 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                          TODO - Pixel shader output registers are not indexable.
+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
@@ -2283,7 +2278,6 @@ SM.OUTPUTCONTROLPOINTSTOTALSCALARS        Total number of scalars across all HS
 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.PSINPUTINT                             TODO - Pixel shader input values must use the same interpolation mode
 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.RESLIMIT                               TODO - Resource limit exceeded for target shader model
 SM.RESOURCERANGEOVERLAP                   Resource ranges must not overlap

+ 4 - 10
include/dxc/HLSL/DxilValidation.h

@@ -58,8 +58,6 @@ enum class ValidationRule : unsigned {
   InstrERR_NON_LITERAL_RESOURCE, // TODO - Resources being indexed cannot come from conditional expressions, they must come from literal expressions.
   InstrERR_NON_LITERAL_STREAM, // TODO - stream parameter must come from a literal expression
   InstrERR_RESOURCE_UNINITIALIZED, // TODO - Resource being indexed is uninitialized.
-  InstrERR_TEXTURE_OFFSET, // TODO - texture access must have literal offset and multisample index
-  InstrERR_TEXTURE_TYPE, // TODO - return type of texture too large. Cannot exceed 4 components
   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
   InstrFailToResloveTGSMPointer, // TGSM pointers must originate from an unambiguous TGSM global variable.
   InstrHandleNotFromCreateHandle, // Resource handle should returned by createHandle
@@ -107,6 +105,7 @@ enum class ValidationRule : unsigned {
   InstrSamplerModeForSample, // sample/_l/_d/_cl_s/gather instruction requires sampler declared in default mode
   InstrSamplerModeForSampleC, // sample_c_*/gather_c instructions require sampler declared in comparison mode
   InstrTextureLod, // TODO - Level-of-detail is only defined for Texture1D, Texture2D, Texture3D and TextureCube
+  InstrTextureOffset, // offset texture instructions must take offset which can resolve to integer literal in the range -8 to 7
   InstrTextureOpArgs, // TODO - Instructions that depend on texture type must match operands
   InstrTypeCast, // TODO - Type cast must be valid
   InstrUndefResultForGetDimension, // GetDimensions used undef dimension %0 on %1
@@ -141,6 +140,7 @@ enum class ValidationRule : unsigned {
   MetaTarget, // Target triple must be 'dxil-ms-dx'
   MetaTessellatorOutputPrimitive, // Invalid Tessellator Output Primitive specified. Must be point, line, triangleCW or triangleCCW.
   MetaTessellatorPartition, // Invalid Tessellator Partitioning specified. Must be integer, pow2, fractional_odd or fractional_even.
+  MetaTextureType, // elements of typed buffers and textures must fit in four 32-bit quantities
   MetaUsed, // TODO - All metadata must be used
   MetaValidSamplerMode, // Invalid sampler mode on sampler 
   MetaValueRange, // Metadata value must be within range
@@ -164,7 +164,6 @@ enum class ValidationRule : unsigned {
   SmDSInputControlPointCountRange, // DS input control point count must be [0..%0].  %1 specified
   SmDomainLocationIdxOOB, // DomainLocation component index out of bounds for the domain.
   SmERR_BIND_RESOURCE_RANGE_OVERFLOW, // TODO - ERR_BIND_RESOURCE_RANGE_OVERFLOW
-  SmERR_DUPLICATE_CBUFFER_BANK, // TODO - ERR_DUPLICATE_CBUFFER_BANK
   SmERR_MAX_CBUFFER_EXCEEDED, // TODO - The maximum number of constant buffer slots is exceeded for a library (slot index=%u, max slots=%u)
   SmERR_MAX_CONST_EXCEEDED, // TODO - ERR_MAX_CONST_EXCEEDED
   SmERR_MAX_SAMPLER_EXCEEDED, // TODO - The maximum number of sampler slots is exceeded for a library (slot index=%u, max slots=%u)
@@ -172,27 +171,23 @@ enum class ValidationRule : unsigned {
   SmERR_UNABLE_TO_BIND_RESOURCE, // TODO - ERR_UNABLE_TO_BIND_RESOURCE
   SmERR_UNABLE_TO_BIND_UNBOUNDED_RESOURCE, // TODO - ERR_UNABLE_TO_BIND_UNBOUNDED_RESOURCE
   SmGSInstanceCountRange, // GS instance count must be [1..%0].  %1 specified
-  SmGSOutputLimit, // TODO - A geometry shader can output a maximum of 1024 32-bit values (including the size of the input data and the size of the data created by the shader)
   SmGSOutputVertexCountRange, // GS output vertex count must be [0..%0].  %1 specified
-  SmGSTotalOutputVertexDataRange, // TODO: 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
+  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
   SmGSValidInputPrimitive, // GS input primitive unrecognized
   SmGSValidOutputPrimitiveTopology, // GS output primitive topology unrecognized
   SmHSInputControlPointCountRange, // HS input control point count must be [1..%0].  %1 specified
   SmHullPassThruControlPointCountMatch, // For pass thru hull shader, input control point count must match output control point count
-  SmICBLimit, // TODO - Constant buffers must contain at least one element, but no more than 4096 values
-  SmIdxTmpLimit, // TODO - Indexable temporaries must containt at least one element, but no more than 4096 values
   SmInsideTessFactorSizeMatchDomain, // InsideTessFactor size mismatch the domain.
   SmInvalidResourceCompType, // Invalid resource return type
   SmInvalidResourceKind, // Invalid resources kind
   SmInvalidTextureKindOnUAV, // Texture2DMS[Array] or TextureCube[Array] resources are not supported with UAVs
   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.
-  SmLiveLimit, // TODO - The total number of temporary and indexable-temporary registers (32-bit four-component values) must be less than or equal to 4096
   SmMaxTGSMSize, // Total Thread Group Shared Memory storage is %0, exceeded %1
   SmMaxTheadGroup, // Declared Thread Group Count %0 (X*Y*Z) is beyond the valid maximum of %1
   SmMultiStreamMustBePoint, // When multiple GS output streams are used they must be pointlists
   SmName, // Target shader model name must be known
   SmNoInterpMode, // Interpolation mode must be undefined for VS input/PS output/patch constant.
-  SmNoPSOutputIdx, // TODO - Pixel shader output registers are not indexable.
+  SmNoPSOutputIdx, // Pixel shader output registers are not indexable.
   SmOpcode, // Opcode must be defined in target shader model
   SmOpcodeInInvalidFunction, // Invalid DXIL opcode usage like StorePatchConstant in patch constant function
   SmOperand, // Operand must be defined in target shader model
@@ -200,7 +195,6 @@ enum class ValidationRule : unsigned {
   SmOutputControlPointsTotalScalars, // Total number of scalars across all HS output control points must not exceed 
   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)
   SmPSCoverageAndInnerCoverage, // InnerCoverage and Coverage are mutually exclusive.
-  SmPSInputInt, // TODO - Pixel shader input values must use the same interpolation mode
   SmPSOutputSemantic, // Pixel Shader allows output semantics to be SV_Target, SV_Depth, SV_DepthGreaterEqual, SV_DepthLessEqual, SV_Coverage or SV_StencilRef, %0 found
   SmPatchConstantOnlyForHSDS, // patch constant signature only valid in HS and DS
   SmROVOnlyInPS, // RasterizerOrdered objects are only allowed in 5.0+ pixel shaders

+ 1 - 1
lib/HLSL/DxilResource.cpp

@@ -42,7 +42,7 @@ Type *DxilResource::GetRetType() const {
   Constant *GV = GetGlobalSymbol();
   Type *Ty = GV->getType()->getPointerElementType();
   // For resource array, use element type.
-  if (Ty->isArrayTy())
+  while (Ty->isArrayTy())
     Ty = Ty->getArrayElementType();
   // Get the struct buffer type like this %class.StructuredBuffer = type {
   // %struct.mat }.

+ 38 - 13
lib/HLSL/DxilValidation.cpp

@@ -80,6 +80,7 @@ const char *hlsl::GetValidationRuleText(ValidationRule value) {
     case hlsl::ValidationRule::MetaInvalidControlFlowHint: return "Invalid control flow hint";
     case hlsl::ValidationRule::MetaBranchFlatten: return "Can't use branch and flatten attributes together";
     case hlsl::ValidationRule::MetaForceCaseOnSwitch: return "Attribute forcecase only works for switch";
+    case hlsl::ValidationRule::MetaTextureType: return "elements of typed buffers and textures must fit in four 32-bit quantities";
     case hlsl::ValidationRule::InstrOload: return "DXIL intrinsic overload must be valid";
     case hlsl::ValidationRule::InstrCallOload: return "Call to DXIL intrinsic '%0' does not match an allowed overload signature";
     case hlsl::ValidationRule::InstrResID: return "TODO - DXIL instruction must refer to valid resource IDs";
@@ -106,8 +107,7 @@ const char *hlsl::GetValidationRuleText(ValidationRule value) {
     case hlsl::ValidationRule::InstrERR_ALIAS_ARRAY_INDEX_OUT_OF_BOUNDS: return "TODO - ERR_ALIAS_ARRAY_INDEX_OUT_OF_BOUNDS";
     case hlsl::ValidationRule::InstrMinPrecisionNotPrecise: return "Instructions marked precise may not refer to minprecision values";
     case hlsl::ValidationRule::InstrOnlyOneAllocConsume: return "RWStructuredBuffers may increment or decrement their counters, but not both.";
-    case hlsl::ValidationRule::InstrERR_TEXTURE_TYPE: return "TODO - return type of texture too large. Cannot exceed 4 components";
-    case hlsl::ValidationRule::InstrERR_TEXTURE_OFFSET: return "TODO - texture access must have literal offset and multisample index";
+    case hlsl::ValidationRule::InstrTextureOffset: return "offset texture instructions must take offset which can resolve to integer literal in the range -8 to 7";
     case hlsl::ValidationRule::InstrWAR_GRADIENT_IN_VARYING_FLOW: return "TODO - gradient instruction used in a loop with varying iteration; partial derivatives may have undefined value";
     case hlsl::ValidationRule::InstrDeterminateDerivative: return "gradient operation uses a value that may not be defined for all pixels (in UAV loads can not participate in gradient operations)";
     case hlsl::ValidationRule::InstrERR_NON_LITERAL_RESOURCE: return "TODO - Resources being indexed cannot come from conditional expressions, they must come from literal expressions.";
@@ -165,14 +165,9 @@ const char *hlsl::GetValidationRuleText(ValidationRule value) {
     case hlsl::ValidationRule::SmOperand: return "Operand must be defined in target shader model";
     case hlsl::ValidationRule::SmSemantic: return "Semantic '%0' is invalid as %1 %2";
     case hlsl::ValidationRule::SmResLimit: return "TODO - Resource limit exceeded for target shader model";
-    case hlsl::ValidationRule::SmICBLimit: return "TODO - Constant buffers must contain at least one element, but no more than 4096 values";
-    case hlsl::ValidationRule::SmIdxTmpLimit: return "TODO - Indexable temporaries must containt at least one element, but no more than 4096 values";
-    case hlsl::ValidationRule::SmLiveLimit: return "TODO - The total number of temporary and indexable-temporary registers (32-bit four-component values) must be less than or equal to 4096";
-    case hlsl::ValidationRule::SmPSInputInt: return "TODO - Pixel shader input values must use the same interpolation mode";
     case hlsl::ValidationRule::SmNoInterpMode: return "Interpolation mode for '%0' is set but should be undefined";
-    case hlsl::ValidationRule::SmNoPSOutputIdx: return "TODO - Pixel shader output registers are not indexable.";
+    case hlsl::ValidationRule::SmNoPSOutputIdx: return "Pixel shader output registers are not indexable.";
     case hlsl::ValidationRule::SmPSConsistentInterp: return "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)";
-    case hlsl::ValidationRule::SmGSOutputLimit: return "TODO - A geometry shader can output a maximum of 1024 32-bit values (including the size of the input data and the size of the data created by the shader)";
     case hlsl::ValidationRule::SmThreadGroupChannelRange: return "Declared Thread Group %0 size %1 outside valid range [%2..%3]";
     case hlsl::ValidationRule::SmMaxTheadGroup: return "Declared Thread Group Count %0 (X*Y*Z) is beyond the valid maximum of %1";
     case hlsl::ValidationRule::SmMaxTGSMSize: return "Total Thread Group Shared Memory storage is %0, exceeded %1";
@@ -203,7 +198,7 @@ const char *hlsl::GetValidationRuleText(ValidationRule value) {
     case hlsl::ValidationRule::SmInvalidResourceCompType: return "Invalid resource return type";
     case hlsl::ValidationRule::SmSampleCountOnlyOn2DMS: return "Only Texture2DMS/2DMSArray could has sample count";
     case hlsl::ValidationRule::SmCounterOnlyOnStructBuf: return "BufferUpdateCounter valid only on structured buffers";
-    case hlsl::ValidationRule::SmGSTotalOutputVertexDataRange: return "TODO: 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";
+    case hlsl::ValidationRule::SmGSTotalOutputVertexDataRange: return "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";
     case hlsl::ValidationRule::SmMultiStreamMustBePoint: return "Multiple GS output streams are used but '%0' is not pointlist";
     case hlsl::ValidationRule::SmCompletePosition: return "Not all elements of SV_Position were written";
     case hlsl::ValidationRule::SmUndefinedOutput: return "Not all elements of output %0 were written";
@@ -213,7 +208,6 @@ const char *hlsl::GetValidationRuleText(ValidationRule value) {
     case hlsl::ValidationRule::SmERR_MAX_SAMPLER_EXCEEDED: return "TODO - The maximum number of sampler slots is exceeded for a library (slot index=%u, max slots=%u)";
     case hlsl::ValidationRule::SmERR_MAX_TEXTURE_EXCEEDED: return "TODO - The maximum number of texture slots is exceeded for a library (slot index=%u, max slots=%u)";
     case hlsl::ValidationRule::SmERR_MAX_CBUFFER_EXCEEDED: return "TODO - The maximum number of constant buffer slots is exceeded for a library (slot index=%u, max slots=%u)";
-    case hlsl::ValidationRule::SmERR_DUPLICATE_CBUFFER_BANK: return "TODO - ERR_DUPLICATE_CBUFFER_BANK";
     case hlsl::ValidationRule::SmERR_UNABLE_TO_BIND_RESOURCE: return "TODO - ERR_UNABLE_TO_BIND_RESOURCE";
     case hlsl::ValidationRule::SmERR_UNABLE_TO_BIND_UNBOUNDED_RESOURCE: return "TODO - ERR_UNABLE_TO_BIND_UNBOUNDED_RESOURCE";
     case hlsl::ValidationRule::SmERR_BIND_RESOURCE_RANGE_OVERFLOW: return "TODO - ERR_BIND_RESOURCE_RANGE_OVERFLOW";
@@ -806,10 +800,28 @@ static void ValidateResourceOffset(CallInst *CI, DXIL::ResourceKind resKind,
   unsigned numOffsets = DxilResource::GetNumOffsets(resKind);
   bool hasOffset = !isa<UndefValue>(offsets[0]);
 
+  auto validateOffset = [&](Value *offset) {
+    if (ConstantInt *cOffset = dyn_cast<ConstantInt>(offset)) {
+      int offset = cOffset->getValue().getSExtValue();
+      if (offset > 7 || offset < -8) {
+        ValCtx.EmitInstrError(CI, ValidationRule::InstrTextureOffset);
+      }
+    } else {
+      ValCtx.EmitInstrError(CI, ValidationRule::InstrTextureOffset);
+    }
+  };
+
+  if (hasOffset) {
+    validateOffset(offsets[0]);
+  }
+
   for (unsigned i = 1; i < kMaxNumOffsets; i++) {
     if (i < numOffsets) {
-      if (hasOffset && isa<UndefValue>(offsets[i])) {
-        ValCtx.EmitInstrError(CI, ValidationRule::InstrResourceOffsetMiss);
+      if (hasOffset) {
+        if (isa<UndefValue>(offsets[i]))
+          ValCtx.EmitInstrError(CI, ValidationRule::InstrResourceOffsetMiss);
+        else
+          validateOffset(offsets[i]);
       }
     } else {
       if (!isa<UndefValue>(offsets[i])) {
@@ -2423,6 +2435,14 @@ static void ValidateResource(hlsl::DxilResource &res,
            std::to_string(stride).c_str()});
     }
   }
+
+  if (res.IsAnyTexture() || res.IsTypedBuffer()) {
+    Type *RetTy = res.GetRetType();
+    unsigned size = ValCtx.DxilMod.GetModule()->getDataLayout().getTypeAllocSize(RetTy);
+    if (size > 4*4) {
+      ValCtx.EmitResourceError(&res, ValidationRule::MetaTextureType);
+    }
+  }
 }
 
 static void
@@ -2879,6 +2899,7 @@ static void ValidateSignature(ValidationContext &ValCtx, const DxilSignature &S,
   SpacesAllocator<unsigned, DxilSignatureElement> allocator;
 
   bool IsGS = ValCtx.DxilMod.GetShaderModel()->IsGS();
+  bool IsPS = ValCtx.DxilMod.GetShaderModel()->IsPS();
 
   unordered_map<Semantic::Kind, unsigned> semanticUsageMap[4];
   semanticUsageMap[0][Semantic::Kind::ClipDistance] = 0;
@@ -2899,7 +2920,6 @@ static void ValidateSignature(ValidationContext &ValCtx, const DxilSignature &S,
 
   for (auto &E : S.GetElements()) {
     ValidateSignatureElement(*E, ValCtx);
-
     // Overlap check.
     unsigned streamId = E->GetOutputStream();
     if (streamId >= DXIL::kNumOutputStreams) {
@@ -2924,6 +2944,11 @@ static void ValidateSignature(ValidationContext &ValCtx, const DxilSignature &S,
     if (isOutput && E->GetSemantic()->GetKind() == DXIL::SemanticKind::Position) {
       ValCtx.hasOutputPosition[E->GetOutputStream()] = true;
     }
+    if (isOutput && IsPS) {
+      if (E->GetRows() > 1) {
+        ValCtx.EmitError(ValidationRule::SmNoPSOutputIdx);
+      }
+    }
   }
 
   if (semanticUsageMap[0].count(Semantic::Kind::InnerCoverage) > 0 &&

+ 96 - 13
lib/Transforms/Scalar/ScalarReplAggregatesHLSL.cpp

@@ -3805,7 +3805,7 @@ void SROA_Parameter_HLSL::allocateSemanticIndex(
 void SROA_Parameter_HLSL::flattenArgument(
     Function *F, Value *Arg, DxilParameterAnnotation &paramAnnotation,
     std::vector<Value *> &FlatParamList,
-    std::vector<DxilParameterAnnotation> &FlatRetAnnotationList, IRBuilder<> &Builder,
+    std::vector<DxilParameterAnnotation> &FlatAnnotationList, IRBuilder<> &Builder,
     DbgDeclareInst *DDI) {
   std::deque<Value *> WorkList;
   WorkList.push_back(Arg);
@@ -3822,7 +3822,7 @@ void SROA_Parameter_HLSL::flattenArgument(
   }
   Type *opcodeTy = Type::getInt32Ty(F->getContext());
 
-  unsigned startArgIndex = FlatRetAnnotationList.size();
+  unsigned startArgIndex = FlatAnnotationList.size();
 
   // Map from value to annotation.
   std::unordered_map<Value *, DxilFieldAnnotation> annotationMap;
@@ -3831,6 +3831,9 @@ void SROA_Parameter_HLSL::flattenArgument(
   DxilTypeSystem &dxilTypeSys = m_pHLModule->GetTypeSystem();
 
   const std::string &semantic = paramAnnotation.GetSemanticString();
+  bool bSemOverride = !semantic.empty();
+
+  bool bForParam = F == Builder.GetInsertPoint()->getParent()->getParent();
 
   // Map from semantic string to type.
   llvm::StringMap<Type *> semanticTypeMap;
@@ -3916,18 +3919,93 @@ void SROA_Parameter_HLSL::flattenArgument(
       if (Instruction *I = dyn_cast<Instruction>(V))
         deadAllocas.emplace_back(I);
     } else {
-      if (!semantic.empty()) {
+      if (bSemOverride) {
         if (!annotation.GetSemanticString().empty()) {
           // TODO: warning for override the semantic in EltAnnotation.
         }
         // Just save parent semantic here, allocate later.
         annotation.SetSemanticString(semantic);
       }
+
+      // Flatten array of SV_Target.
+      StringRef semanticStr = annotation.GetSemanticString();
+      if (semanticStr.upper().find("SV_TARGET") == 0 &&
+          V->getType()->getPointerElementType()->isArrayTy()) {
+        Type *Ty = cast<ArrayType>(V->getType()->getPointerElementType());
+        StringRef targetStr;
+        unsigned  targetIndex;
+        Semantic::DecomposeNameAndIndex(semanticStr, &targetStr, &targetIndex);
+        // Replace target parameter with local target.
+        AllocaInst *localTarget = Builder.CreateAlloca(Ty);
+        V->replaceAllUsesWith(localTarget);
+        unsigned arraySize = 1;
+        std::vector<unsigned> arraySizeList;
+        while (Ty->isArrayTy()) {
+          unsigned size = Ty->getArrayNumElements();
+          arraySizeList.emplace_back(size);
+          arraySize *= size;
+          Ty = Ty->getArrayElementType();
+        }
+
+        unsigned arrayLevel = arraySizeList.size();
+        std::vector<unsigned> arrayIdxList(arrayLevel, 0);
+
+        // Create flattened target.
+        DxilFieldAnnotation EltAnnotation = annotation;
+        for (unsigned i=0;i<arraySize;i++) {
+          Value *Elt = Builder.CreateAlloca(Ty);
+          EltAnnotation.SetSemanticString(targetStr.str()+std::to_string(targetIndex+i));
+
+          // Add semantic type.
+          semanticTypeMap[EltAnnotation.GetSemanticString()] = Ty;
+
+          annotationMap[Elt] = EltAnnotation;
+          WorkList.push_front(Elt);
+          // Copy local target to flattened target.
+          std::vector<Value*> idxList(arrayLevel+1);
+          idxList[0] = Builder.getInt32(0);
+          for (unsigned idx=0;idx<arrayLevel; idx++) {
+            idxList[idx+1] = Builder.getInt32(arrayIdxList[idx]);
+          }
+
+          if (bForParam) {
+            // If Argument, copy before each return.
+            for (auto &BB : F->getBasicBlockList()) {
+              TerminatorInst *TI = BB.getTerminator();
+              if (isa<ReturnInst>(TI)) {
+                IRBuilder<> RetBuilder(TI);
+                Value *Ptr = RetBuilder.CreateGEP(localTarget, idxList);
+                Value *V = RetBuilder.CreateLoad(Ptr);
+                RetBuilder.CreateStore(V, Elt);
+              }
+            }
+          } else {
+            // Else, copy with Builder.
+            Value *Ptr = Builder.CreateGEP(localTarget, idxList);
+            Value *V = Builder.CreateLoad(Ptr);
+            Builder.CreateStore(V, Elt);
+          }
+
+          // Update arrayIdxList.
+          for (unsigned idx=arrayLevel;idx>0;idx--) {
+            arrayIdxList[idx-1]++;
+            if (arrayIdxList[idx-1] < arraySizeList[idx-1])
+              break;
+            arrayIdxList[idx-1] = 0;
+          }
+        }
+        // Don't override flattened SV_Target.
+        if (V == Arg) {
+          bSemOverride = false;
+        }
+        continue;
+      }
+
       // Cannot SROA, save it to final parameter list.
       FlatParamList.emplace_back(V);
       // Create ParamAnnotation for V.
-      FlatRetAnnotationList.emplace_back(DxilParameterAnnotation());
-      DxilParameterAnnotation &flatParamAnnotation = FlatRetAnnotationList.back();
+      FlatAnnotationList.emplace_back(DxilParameterAnnotation());
+      DxilParameterAnnotation &flatParamAnnotation = FlatAnnotationList.back();
 
       flatParamAnnotation.SetParamInputQual(paramAnnotation.GetParamInputQual());
             
@@ -4032,19 +4110,20 @@ void SROA_Parameter_HLSL::flattenArgument(
   for (Instruction *I : deadAllocas)
     I->eraseFromParent();
 
-  unsigned endArgIndex = FlatRetAnnotationList.size();
-  if (startArgIndex < endArgIndex) {
+  unsigned endArgIndex = FlatAnnotationList.size();
+  if (bForParam && startArgIndex < endArgIndex) {
     DxilParamInputQual inputQual = paramAnnotation.GetParamInputQual();
     if (inputQual == DxilParamInputQual::OutStream0 ||
         inputQual == DxilParamInputQual::OutStream1 ||
         inputQual == DxilParamInputQual::OutStream2 ||
         inputQual == DxilParamInputQual::OutStream3)
       startArgIndex++;
+
     DxilParameterAnnotation &flatParamAnnotation =
-        FlatRetAnnotationList[startArgIndex];
+        FlatAnnotationList[startArgIndex];
     const std::string &semantic = flatParamAnnotation.GetSemanticString();
     if (!semantic.empty())
-      allocateSemanticIndex(FlatRetAnnotationList, startArgIndex,
+      allocateSemanticIndex(FlatAnnotationList, startArgIndex,
                             semanticTypeMap);
   }
 
@@ -4352,7 +4431,8 @@ void SROA_Parameter_HLSL::createFlattenedFunction(Function *F) {
   std::vector<DxilParameterAnnotation> FlatRetAnnotationList;
   // Split and change to out parameter.
   if (!retType->isVoidTy()) {
-    IRBuilder<> Builder(F->getEntryBlock().getFirstInsertionPt());
+    Instruction *InsertPt = F->getEntryBlock().getFirstInsertionPt();
+    IRBuilder<> Builder(InsertPt);
     Value *retValAddr = Builder.CreateAlloca(retType);
     // Create DbgDecl for the ret value.
     if (DISubprogram *funcDI = getDISubprogram(F)) {
@@ -4370,10 +4450,13 @@ void SROA_Parameter_HLSL::createFlattenedFunction(Function *F) {
     for (BasicBlock &BB : F->getBasicBlockList()) {
       if (ReturnInst *RI = dyn_cast<ReturnInst>(BB.getTerminator())) {
         // Create store for return.
-        IRBuilder<> Builder(RI);
-        Builder.CreateStore(RI->getReturnValue(), retValAddr);
+        IRBuilder<> RetBuilder(RI);
+        RetBuilder.CreateStore(RI->getReturnValue(), retValAddr);
         // Clone the return.
-        Builder.CreateRet(RI->getReturnValue());
+        ReturnInst *NewRet = RetBuilder.CreateRet(RI->getReturnValue());
+        if (RI == InsertPt) {
+          Builder.SetInsertPoint(NewRet);
+        }
         RI->eraseFromParent();
       }
     }

+ 17 - 0
tools/clang/test/CodeGenHLSL/targetArray.hlsl

@@ -0,0 +1,17 @@
+// RUN: %dxc -E main -T ps_5_0 %s | FileCheck %s
+
+// CHECK: @main
+
+uint i;
+float4 main(int4 a : A, out float4 o[2] : SV_TARGET, out float4 o2[2][2] : SV_TARGET2) : SV_TARGET7
+{
+  o[0] = a+2;
+  o[1] = a+3;
+  o[i] = a+10;
+  o2[0][0] = a+5;
+  o2[0][1] = a+6;
+  o2[1][0] = a+7;
+  o2[1][1] = a+8;
+  o2[i][i] = a + 12;
+  return a + 16;
+}

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

@@ -68,6 +68,19 @@ public:
   TEST_METHOD(StructBufGlobalCoherentAndCounter)
   TEST_METHOD(StructBufLoadCoordinates)
   TEST_METHOD(StructBufStoreCoordinates)
+  TEST_METHOD(TypedBufRetType)
+  TEST_METHOD(VsInputSemantic)
+  TEST_METHOD(VsOutputSemantic)
+  TEST_METHOD(HsInputSemantic)
+  TEST_METHOD(HsOutputSemantic)
+  TEST_METHOD(PatchConstSemantic)
+  TEST_METHOD(DsInputSemantic)
+  TEST_METHOD(DsOutputSemantic)
+  TEST_METHOD(GsInputSemantic)
+  TEST_METHOD(GsOutputSemantic)
+  TEST_METHOD(PsInputSemantic)
+  TEST_METHOD(PsOutputSemantic)
+  TEST_METHOD(ArrayOfSVTarget)
 
   TEST_METHOD(WhenInstrDisallowedThenFail);
   TEST_METHOD(WhenDepthNotFloatThenFail);
@@ -665,6 +678,110 @@ TEST_F(ValidationTest, StructBufStoreCoordinates) {
       "structured buffer require 2 coordinates");
 }
 
+TEST_F(ValidationTest, TypedBufRetType) {
+    RewriteAssemblyCheckMsg(
+      L"..\\CodeGenHLSL\\sample5.hlsl", "ps_5_0",
+      "%class.Texture2D = type { <4 x float>",
+      "%class.Texture2D = type { <4 x double>",
+      "elements of typed buffers and textures must fit in four 32-bit quantities");
+}
+
+TEST_F(ValidationTest, VsInputSemantic) {
+    RewriteAssemblyCheckMsg(
+      L"..\\CodeGenHLSL\\clip_planes.hlsl", "vs_5_0",
+      "!\"POSITION\", i8 9, i8 0",
+      "!\"SV_Target\", i8 9, i8 16",
+      "Semantic 'SV_Target' is invalid as vs Input");
+}
+
+TEST_F(ValidationTest, VsOutputSemantic) {
+    RewriteAssemblyCheckMsg(
+      L"..\\CodeGenHLSL\\clip_planes.hlsl", "vs_5_0",
+      "!\"NORMAL\", i8 9, i8 0",
+      "!\"SV_Target\", i8 9, i8 16",
+      "Semantic 'SV_Target' is invalid as vs Output");
+}
+
+TEST_F(ValidationTest, HsInputSemantic) {
+    RewriteAssemblyCheckMsg(
+      L"..\\CodeGenHLSL\\SimpleHs1.hlsl", "hs_5_0",
+      "!\"TEXCOORD\", i8 9, i8 0",
+      "!\"VertexID\", i8 4, i8 1",
+      "Semantic 'VertexID' is invalid as hs Input");
+}
+
+TEST_F(ValidationTest, HsOutputSemantic) {
+    RewriteAssemblyCheckMsg(
+      L"..\\CodeGenHLSL\\SimpleHs1.hlsl", "hs_5_0",
+      "!\"TEXCOORD\", i8 9, i8 0",
+      "!\"VertexID\", i8 4, i8 1",
+      "Semantic 'VertexID' is invalid as hs Output");
+}
+
+TEST_F(ValidationTest, PatchConstSemantic) {
+    RewriteAssemblyCheckMsg(
+      L"..\\CodeGenHLSL\\SimpleHs1.hlsl", "hs_5_0",
+      "!\"SV_TessFactor\", i8 9, i8 25",
+      "!\"VertexID\", i8 4, i8 1",
+      "Semantic 'VertexID' is invalid as hs PatchConstant");
+}
+
+TEST_F(ValidationTest, DsInputSemantic) {
+    RewriteAssemblyCheckMsg(
+      L"..\\CodeGenHLSL\\SimpleDs1.hlsl", "ds_5_0",
+      "!\"TEXCOORD\", i8 9, i8 0",
+      "!\"VertexID\", i8 4, i8 1",
+      "Semantic 'VertexID' is invalid as ds Input");
+}
+
+TEST_F(ValidationTest, DsOutputSemantic) {
+    RewriteAssemblyCheckMsg(
+      L"..\\CodeGenHLSL\\SimpleDs1.hlsl", "ds_5_0",
+      "!\"TEXCOORD\", i8 9, i8 0",
+      "!\"VertexID\", i8 4, i8 1",
+      "Semantic 'VertexID' is invalid as ds Output");
+}
+
+TEST_F(ValidationTest, GsInputSemantic) {
+    RewriteAssemblyCheckMsg(
+      L"..\\CodeGenHLSL\\SimpleGs1.hlsl", "gs_5_0",
+      "!\"POSSIZE\", i8 9, i8 0",
+      "!\"VertexID\", i8 4, i8 1",
+      "Semantic 'VertexID' is invalid as gs Input");
+}
+
+TEST_F(ValidationTest, GsOutputSemantic) {
+    RewriteAssemblyCheckMsg(
+      L"..\\CodeGenHLSL\\SimpleGs1.hlsl", "gs_5_0",
+      "!\"TEXCOORD\", i8 9, i8 0",
+      "!\"VertexID\", i8 4, i8 1",
+      "Semantic 'VertexID' is invalid as gs Output");
+}
+
+TEST_F(ValidationTest, PsInputSemantic) {
+    RewriteAssemblyCheckMsg(
+      L"..\\CodeGenHLSL\\abs2.hlsl", "ps_5_0",
+      "!\"A\", i8 4, i8 0",
+      "!\"VertexID\", i8 4, i8 1",
+      "Semantic 'VertexID' is invalid as ps Input");
+}
+
+TEST_F(ValidationTest, PsOutputSemantic) {
+    RewriteAssemblyCheckMsg(
+      L"..\\CodeGenHLSL\\abs2.hlsl", "ps_5_0",
+      "!\"SV_Target\", i8 9, i8 16",
+      "!\"VertexID\", i8 4, i8 1",
+      "Semantic 'VertexID' is invalid as ps Output");
+}
+
+TEST_F(ValidationTest, ArrayOfSVTarget) {
+    RewriteAssemblyCheckMsg(
+      L"..\\CodeGenHLSL\\targetArray.hlsl", "ps_5_0",
+      "i32 6, !\"SV_Target\", i8 9, i8 16, !36, i8 0, i32 1",
+      "i32 6, !\"SV_Target\", i8 9, i8 16, !36, i8 0, i32 2",
+      "Pixel shader output registers are not indexable.");
+}
+
 TEST_F(ValidationTest, WhenWaveAffectsGradientThenFail) {
   TestCheck(L"val-wave-failures-ps.hlsl");
 }

+ 4 - 10
utils/hct/hctdb.py

@@ -1402,6 +1402,7 @@ class db_dxil(object):
         self.add_valrule("Meta.InvalidControlFlowHint", "Invalid control flow hint")
         self.add_valrule("Meta.BranchFlatten", "Can't use branch and flatten attributes together")
         self.add_valrule("Meta.ForceCaseOnSwitch", "Attribute forcecase only works for switch")
+        self.add_valrule("Meta.TextureType", "elements of typed buffers and textures must fit in four 32-bit quantities")
 
         self.add_valrule("Instr.Oload", "DXIL intrinsic overload must be valid")
         self.add_valrule_msg("Instr.CallOload", "Call to DXIL intrinsic must match overload signature", "Call to DXIL intrinsic '%0' does not match an allowed overload signature")
@@ -1437,8 +1438,7 @@ class db_dxil(object):
         self.add_valrule("Instr.OnlyOneAllocConsume", "RWStructuredBuffers may increment or decrement their counters, but not both.")
 
         # CCompiler
-        self.add_valrule("Instr.ERR_TEXTURE_TYPE", "TODO - return type of texture too large. Cannot exceed 4 components")
-        self.add_valrule("Instr.ERR_TEXTURE_OFFSET", "TODO - texture access must have literal offset and multisample index")
+        self.add_valrule("Instr.TextureOffset", "offset texture instructions must take offset which can resolve to integer literal in the range -8 to 7")
         # D3D12
         self.add_valrule("Instr.WAR_GRADIENT_IN_VARYING_FLOW", "TODO - gradient instruction used in a loop with varying iteration; partial derivatives may have undefined value")
         self.add_valrule("Instr.DeterminateDerivative", "gradient operation uses a value that may not be defined for all pixels (in UAV loads can not participate in gradient operations)")
@@ -1507,14 +1507,9 @@ class db_dxil(object):
         self.add_valrule("Sm.Operand", "Operand must be defined in target shader model")
         self.add_valrule_msg("Sm.Semantic", "Semantic must be defined in target shader model", "Semantic '%0' is invalid as %1 %2")
         self.add_valrule("Sm.ResLimit", "TODO - Resource limit exceeded for target shader model")
-        self.add_valrule("Sm.ICBLimit", "TODO - Constant buffers must contain at least one element, but no more than 4096 values")
-        self.add_valrule("Sm.IdxTmpLimit", "TODO - Indexable temporaries must containt at least one element, but no more than 4096 values")
-        self.add_valrule("Sm.LiveLimit", "TODO - The total number of temporary and indexable-temporary registers (32-bit four-component values) must be less than or equal to 4096")
-        self.add_valrule("Sm.PSInputInt", "TODO - Pixel shader input values must use the same interpolation mode") # TODO restrict to PS
         self.add_valrule_msg("Sm.NoInterpMode", "Interpolation mode must be undefined for VS input/PS output/patch constant.", "Interpolation mode for '%0' is set but should be undefined")
-        self.add_valrule("Sm.NoPSOutputIdx", "TODO - Pixel shader output registers are not indexable.")# TODO restrict to PS
+        self.add_valrule("Sm.NoPSOutputIdx", "Pixel shader output registers are not indexable.")# TODO restrict to PS
         self.add_valrule("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)")
-        self.add_valrule("Sm.GSOutputLimit", "TODO - A geometry shader can output a maximum of 1024 32-bit values (including the size of the input data and the size of the data created by the shader)")
         self.add_valrule("Sm.ThreadGroupChannelRange", "Declared Thread Group %0 size %1 outside valid range [%2..%3]")
         self.add_valrule("Sm.MaxTheadGroup", "Declared Thread Group Count %0 (X*Y*Z) is beyond the valid maximum of %1")
         self.add_valrule("Sm.MaxTGSMSize", "Total Thread Group Shared Memory storage is %0, exceeded %1")
@@ -1545,7 +1540,7 @@ class db_dxil(object):
         self.add_valrule("Sm.InvalidResourceCompType","Invalid resource return type")
         self.add_valrule("Sm.SampleCountOnlyOn2DMS","Only Texture2DMS/2DMSArray could has sample count")
         self.add_valrule("Sm.CounterOnlyOnStructBuf", "BufferUpdateCounter valid only on structured buffers")
-        self.add_valrule("Sm.GSTotalOutputVertexDataRange", "TODO: 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")
+        self.add_valrule("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")
         self.add_valrule_msg("Sm.MultiStreamMustBePoint", "When multiple GS output streams are used they must be pointlists", "Multiple GS output streams are used but '%0' is not pointlist")
         self.add_valrule("Sm.CompletePosition", "Not all elements of SV_Position were written")
         self.add_valrule("Sm.UndefinedOutput", "Not all elements of output %0 were written")
@@ -1555,7 +1550,6 @@ class db_dxil(object):
         self.add_valrule("Sm.ERR_MAX_SAMPLER_EXCEEDED", "TODO - The maximum number of sampler slots is exceeded for a library (slot index=%u, max slots=%u)")
         self.add_valrule("Sm.ERR_MAX_TEXTURE_EXCEEDED", "TODO - The maximum number of texture slots is exceeded for a library (slot index=%u, max slots=%u)")
         self.add_valrule("Sm.ERR_MAX_CBUFFER_EXCEEDED", "TODO - The maximum number of constant buffer slots is exceeded for a library (slot index=%u, max slots=%u)")
-        self.add_valrule("Sm.ERR_DUPLICATE_CBUFFER_BANK", "TODO - ERR_DUPLICATE_CBUFFER_BANK")
         self.add_valrule("Sm.ERR_UNABLE_TO_BIND_RESOURCE", "TODO - ERR_UNABLE_TO_BIND_RESOURCE")
         self.add_valrule("Sm.ERR_UNABLE_TO_BIND_UNBOUNDED_RESOURCE", "TODO - ERR_UNABLE_TO_BIND_UNBOUNDED_RESOURCE")
         self.add_valrule("Sm.ERR_BIND_RESOURCE_RANGE_OVERFLOW", "TODO - ERR_BIND_RESOURCE_RANGE_OVERFLOW")