浏览代码

Validate CBuffer size to max of 65536 bytes (#3507)

Tex Riddell 4 年之前
父节点
当前提交
19360a8fa6

+ 1 - 0
docs/DXIL.rst

@@ -3126,6 +3126,7 @@ SM.APPENDANDCONSUMEONSAMEUAV              BufferUpdateCounter inc and dec on a g
 SM.CBUFFERARRAYOFFSETALIGNMENT            CBuffer array offset must be aligned to 16-bytes
 SM.CBUFFERELEMENTOVERFLOW                 CBuffer elements must not overflow
 SM.CBUFFEROFFSETOVERLAP                   CBuffer offsets must not overlap
+SM.CBUFFERSIZE                            CBuffer size must not exceed 65536 bytes
 SM.CBUFFERTEMPLATETYPEMUSTBESTRUCT        D3D12 constant/texture buffer template element can only be a struct.
 SM.COMPLETEPOSITION                       Not all elements of SV_Position were written.
 SM.CONSTANTINTERPMODE                     Interpolation mode must be constant for MS primitive output.

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

@@ -202,6 +202,7 @@ enum class ValidationRule : unsigned {
   SmCBufferArrayOffsetAlignment, // CBuffer array offset must be aligned to 16-bytes
   SmCBufferElementOverflow, // CBuffer elements must not overflow
   SmCBufferOffsetOverlap, // CBuffer offsets must not overlap
+  SmCBufferSize, // CBuffer size must not exceed 65536 bytes
   SmCBufferTemplateTypeMustBeStruct, // D3D12 constant/texture buffer template element can only be a struct.
   SmCSNoSignatures, // Compute shaders must not have shader signatures.
   SmCompletePosition, // Not all elements of SV_Position were written.

+ 7 - 0
lib/HLSL/DxilValidation.cpp

@@ -261,6 +261,7 @@ const char *hlsl::GetValidationRuleText(ValidationRule value) {
     case hlsl::ValidationRule::SmCSNoSignatures: return "Compute shaders must not have shader signatures.";
     case hlsl::ValidationRule::SmCBufferTemplateTypeMustBeStruct: return "D3D12 constant/texture buffer template element can only be a struct.";
     case hlsl::ValidationRule::SmResourceRangeOverlap: return "Resource %0 with base %1 size %2 overlap with other resource with base %3 size %4 in space %5.";
+    case hlsl::ValidationRule::SmCBufferSize: return "CBuffer size is %0 bytes, exceeding maximum of 65536 bytes.";
     case hlsl::ValidationRule::SmCBufferOffsetOverlap: return "CBuffer %0 has offset overlaps at %1.";
     case hlsl::ValidationRule::SmCBufferElementOverflow: return "CBuffer %0 size insufficient for element at offset %1.";
     case hlsl::ValidationRule::SmCBufferArrayOffsetAlignment: return "CBuffer %0 has unaligned array offset at %1.";
@@ -4176,6 +4177,12 @@ static void ValidateCBuffer(DxilCBuffer &cb, ValidationContext &ValCtx) {
                              ValidationRule::SmCBufferTemplateTypeMustBeStruct);
     return;
   }
+  if (cb.GetSize() > (DXIL::kMaxCBufferSize << 4)) {
+    ValCtx.EmitResourceFormatError(&cb,
+                             ValidationRule::SmCBufferSize,
+                             {std::to_string(cb.GetSize())});
+    return;
+  }
   StructType *ST = cast<StructType>(Ty);
   DxilTypeSystem &typeSys = ValCtx.DxilMod.GetTypeSystem();
   DxilStructAnnotation *annotation = typeSys.GetStructAnnotation(ST);

+ 14 - 0
tools/clang/test/HLSLFileCheck/hlsl/objects/CbufferLegacy/cbufferSize1.hlsl

@@ -0,0 +1,14 @@
+// RUN: %dxc -E main -T ps_6_0 %s | FileCheck %s
+
+// CHECK: error: CBuffer size is 65552 bytes, exceeding maximum of 65536 bytes.
+
+cbuffer Foo1 : register(b5)
+{
+  float4 g1 : packoffset(c4096);
+  float4 g2 : packoffset(c0);
+}
+
+float4 main() : SV_TARGET
+{
+  return g2+g1;
+}

+ 13 - 0
tools/clang/test/HLSLFileCheck/hlsl/objects/CbufferLegacy/cbufferSize2.hlsl

@@ -0,0 +1,13 @@
+// RUN: %dxc -E main -T ps_6_0 %s | FileCheck %s
+
+// CHECK: call %dx.types.CBufRet.f32 @dx.op.cbufferLoadLegacy.f32(i32 59, %dx.types.Handle %{{.*}}, i32 4095)
+
+cbuffer Foo1 : register(b5)
+{
+  float arr[4096];
+}
+
+float4 main() : SV_TARGET
+{
+  return arr[4095];
+}

+ 13 - 0
tools/clang/test/HLSLFileCheck/hlsl/objects/CbufferLegacy/cbufferSize3.hlsl

@@ -0,0 +1,13 @@
+// RUN: %dxc -E main -T ps_6_0 %s | FileCheck %s
+
+// CHECK: error: CBuffer size is 65540 bytes, exceeding maximum of 65536 bytes.
+
+cbuffer Foo1 : register(b5)
+{
+  float arr[4097];
+}
+
+float4 main() : SV_TARGET
+{
+  return arr[4096];
+}

+ 14 - 0
tools/clang/test/HLSLFileCheck/hlsl/objects/CbufferLegacy/cbufferSize4.hlsl

@@ -0,0 +1,14 @@
+// RUN: %dxc -E main -T ps_6_0 %s | FileCheck %s
+
+// CHECK: call %dx.types.CBufRet.f32 @dx.op.cbufferLoadLegacy.f32(i32 59, %dx.types.Handle %{{.*}}, i32 4095)
+
+cbuffer Foo1 : register(b5)
+{
+  float arr[4096];
+  float3 after_array;
+}
+
+float4 main() : SV_TARGET
+{
+  return float4(arr[4095], after_array);
+}

+ 15 - 0
tools/clang/test/HLSLFileCheck/hlsl/objects/CbufferLegacy/cbufferSize5.hlsl

@@ -0,0 +1,15 @@
+// RUN: %dxc -E main -T ps_6_0 %s | FileCheck %s
+
+// CHECK: error: CBuffer size is 65540 bytes, exceeding maximum of 65536 bytes.
+
+cbuffer Foo1 : register(b5)
+{
+  float arr[4096];
+  float3 after_array;
+  float overflow;
+}
+
+float4 main() : SV_TARGET
+{
+  return float4(arr[4095] + overflow, after_array);
+}

+ 13 - 0
tools/clang/test/HLSLFileCheck/hlsl/objects/CbufferLegacy/cbufferSize6.hlsl

@@ -0,0 +1,13 @@
+// RUN: %dxc -E main -T ps_6_0 %s | FileCheck %s
+
+// CHECK: error: CBuffer size is 65540 bytes, exceeding maximum of 65536 bytes.
+
+cbuffer Foo1 : register(b5)
+{
+  float arr[4096] : packoffset(c1);
+}
+
+float4 main() : SV_TARGET
+{
+  return arr[4095];
+}

+ 1 - 0
utils/hct/hctdb.py

@@ -2624,6 +2624,7 @@ class db_dxil(object):
         self.add_valrule("Sm.CSNoSignatures", "Compute shaders must not have shader signatures.")
         self.add_valrule("Sm.CBufferTemplateTypeMustBeStruct", "D3D12 constant/texture buffer template element can only be a struct.")
         self.add_valrule_msg("Sm.ResourceRangeOverlap", "Resource ranges must not overlap", "Resource %0 with base %1 size %2 overlap with other resource with base %3 size %4 in space %5.")
+        self.add_valrule_msg("Sm.CBufferSize", "CBuffer size must not exceed 65536 bytes", "CBuffer size is %0 bytes, exceeding maximum of 65536 bytes.")
         self.add_valrule_msg("Sm.CBufferOffsetOverlap", "CBuffer offsets must not overlap", "CBuffer %0 has offset overlaps at %1.")
         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.CBufferArrayOffsetAlignment", "CBuffer array offset must be aligned to 16-bytes", "CBuffer %0 has unaligned array offset at %1.")