Skip to content

Commit

Permalink
Validate CBuffer size to max of 65536 bytes (microsoft#3507)
Browse files Browse the repository at this point in the history
  • Loading branch information
tex3d authored Mar 3, 2021
1 parent a7770e6 commit 19360a8
Show file tree
Hide file tree
Showing 10 changed files with 92 additions and 0 deletions.
1 change: 1 addition & 0 deletions docs/DXIL.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
1 change: 1 addition & 0 deletions include/dxc/HLSL/DxilValidation.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
7 changes: 7 additions & 0 deletions lib/HLSL/DxilValidation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.";
Expand Down Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
@@ -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];
}
Original file line number Diff line number Diff line change
@@ -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];
}
Original file line number Diff line number Diff line change
@@ -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);
}
Original file line number Diff line number Diff line change
@@ -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);
}
Original file line number Diff line number Diff line change
@@ -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 change: 1 addition & 0 deletions utils/hct/hctdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -2624,6 +2624,7 @@ def build_valrules(self):
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.")
Expand Down

0 comments on commit 19360a8

Please sign in to comment.