New cbuffer tests: D3D11, D3D12 packedoffset; D3D12 cbuffer array

cbuffer packed_consts : register(b2)
{
  float col1z : packoffset(c1.z); // 4+2
  float col2w : packoffset(c2.w); // 8+3
};

struct ArrayStruct
{
  float4 a;
};

ConstantBuffer<ArrayStruct> array_consts[2] : register(b3);
This commit is contained in:
Jake Turner
2025-09-18 15:19:54 +01:00
parent b47e703c06
commit e16a714aba
6 changed files with 169 additions and 26 deletions
+13 -1
View File
@@ -286,9 +286,15 @@ cbuffer consts : register(b0)
float4 test; // {536, 537, 538, 539}
};
cbuffer packed_consts : register(b1)
{
float col1z : packoffset(c1.z); // 4+2
float col2w : packoffset(c2.w); // 8+3
};
float4 main() : SV_Target0
{
return test + float4(0.1f, 0.0f, 0.0f, 0.0f);
return test + col1z + float4(0.1f, 0.0f, 0.0f, 0.0f);
}
)EOSHADER";
@@ -312,8 +318,13 @@ float4 main() : SV_Target0
for(int i = 0; i < 512; i++)
cbufferdata[i] = Vec4f(float(i * 4 + 0), float(i * 4 + 1), float(i * 4 + 2), float(i * 4 + 3));
float packed_consts[12];
for(int i = 0; i < 12; i++)
packed_consts[i] = (float)i;
ID3D11BufferPtr vb = MakeBuffer().Vertex().Data(DefaultTri);
ID3D11BufferPtr cb = MakeBuffer().Constant().Data(cbufferdata);
ID3D11BufferPtr cb1 = MakeBuffer().Constant().Data(packed_consts);
ID3D11Texture2DPtr fltTex =
MakeTexture(DXGI_FORMAT_R32G32B32A32_FLOAT, screenWidth, screenHeight).RTV().SRV();
@@ -331,6 +342,7 @@ float4 main() : SV_Target0
ctx->PSSetShader(ps, NULL, 0);
ctx->PSSetConstantBuffers(0, 1, &cb.GetInterfacePtr());
ctx->PSSetConstantBuffers(1, 1, &cb1.GetInterfacePtr());
RSSetViewport({0.0f, 0.0f, (float)screenWidth, (float)screenHeight, 0.0f, 1.0f});
@@ -46,6 +46,12 @@ struct consts
float negoneVal : NEGONE;
};
cbuffer packed_consts : register(b1)
{
uint col1z : packoffset(c1.z);
uint col2w : packoffset(c2.w);
};
struct v2f
{
float4 pos : SV_POSITION;
@@ -816,6 +822,10 @@ float4 main(v2f IN) : SV_Target0
return structrwtest[z2+5].b;
}
if(IN.tri == 98)
{
return float4(col1z, col2w, 1.0, 2.0);
}
return float4(0.4f, 0.4f, 0.4f, 0.4f);
}
@@ -1139,6 +1149,13 @@ float4 main(v2f IN, uint samp : SV_SampleIndex) : SV_Target0
ctx->PSSetShaderResources(102, 1, &rgbsrv.GetInterfacePtr());
float packed_consts[12];
for(int i = 0; i < 12; i++)
packed_consts[i] = (float)i;
ID3D11BufferPtr cb = MakeBuffer().Constant().Data(packed_consts);
ctx->PSSetConstantBuffers(1, 1, &cb.GetInterfacePtr());
// Create resources for MSAA draw
ID3DBlobPtr vsmsaablob = Compile(D3DDefaultVertex, "main", "vs_5_0");
ID3DBlobPtr psmsaablob = Compile(msaaPixel, "main", "ps_5_0");
+43 -2
View File
@@ -295,6 +295,19 @@ cbuffer rootconsts : register(b1)
float3_1 root_d;
};
cbuffer packed_consts : register(b2)
{
float col1z : packoffset(c1.z); // 4+2
float col2w : packoffset(c2.w); // 8+3
};
struct ArrayStruct
{
float4 a;
};
ConstantBuffer<ArrayStruct> array_consts[2] : register(b3);
cbuffer hugespace : register(b0, space999999999)
{
float4 huge_val;
@@ -302,7 +315,7 @@ cbuffer hugespace : register(b0, space999999999)
float4 main() : SV_Target0
{
return test + root_zero + huge_val * 1e-30f + float4(0.1f, 0.0f, 0.0f, 0.0f);
return test + root_zero + huge_val * 1e-30f + col1z + array_consts[0].a + array_consts[1].a + float4(0.1f, 0.0f, 0.0f, 0.0f);
}
)EOSHADER";
@@ -349,6 +362,21 @@ float4 main() : SV_Target0
cbufferdata[bindOffset + i] =
Vec4f(float(i * 4 + 0), float(i * 4 + 1), float(i * 4 + 2), float(i * 4 + 3));
float packed_consts[12];
for(int i = 0; i < 12; i++)
packed_consts[i] = (float)i;
struct AlignedCB
{
Vec4f col;
Vec4f padding[15];
};
static_assert(sizeof(AlignedCB) == 256, "Invalid alignment for CB data");
AlignedCB array_consts[2];
for(uint32_t i = 0; i < 2; ++i)
array_consts[i].col = Vec4f(i / 1.0f, i + 1 / 1.0f, 0.5f, 0.5f);
RootData rootData = {};
rootData.root_a[0] = 10.0f;
@@ -373,12 +401,18 @@ float4 main() : SV_Target0
ID3D12ResourcePtr vb = MakeBuffer().Data(DefaultTri);
ID3D12ResourcePtr cb = MakeBuffer().Data(cbufferdata);
ID3D12ResourcePtr cbPacked = MakeBuffer().Data(packed_consts);
ID3D12ResourcePtr cbArray = MakeBuffer().Data(array_consts).Size(sizeof(AlignedCB) * 2);
for(uint32_t i = 0; i < 2; ++i)
MakeCBV(cbArray).SizeBytes(256).Offset(i * sizeof(AlignedCB)).CreateGPU(i);
ID3D12RootSignaturePtr sig = MakeSig({
cbvParam(D3D12_SHADER_VISIBILITY_PIXEL, 0, 7),
constParam(D3D12_SHADER_VISIBILITY_VERTEX, 0, 1, sizeof(rootData) / sizeof(uint32_t)),
constParam(D3D12_SHADER_VISIBILITY_PIXEL, 0, 1, sizeof(rootData) / sizeof(uint32_t)),
constParam(D3D12_SHADER_VISIBILITY_GEOMETRY, 0, 1, sizeof(rootData) / sizeof(uint32_t)),
cbvParam(D3D12_SHADER_VISIBILITY_PIXEL, 0, 2),
tableParam(D3D12_SHADER_VISIBILITY_PIXEL, D3D12_DESCRIPTOR_RANGE_TYPE_CBV, 0, 3, 2, 0),
cbvParam(D3D12_SHADER_VISIBILITY_PIXEL, 999999999, 0),
});
@@ -400,6 +434,10 @@ float4 main() : SV_Target0
ResourceBarrier(vb, D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER);
ResourceBarrier(cb, D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER);
ResourceBarrier(cbPacked, D3D12_RESOURCE_STATE_COMMON,
D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER);
ResourceBarrier(cbArray, D3D12_RESOURCE_STATE_COMMON,
D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER);
ID3D12ResourcePtr rtvtex = MakeTexture(DXGI_FORMAT_R32G32B32A32_FLOAT, screenWidth, screenHeight)
.RTV()
@@ -427,13 +465,16 @@ float4 main() : SV_Target0
IASetVertexBuffer(cmd, vb, sizeof(DefaultA2V), 0);
cmd->SetPipelineState(dxbcpso);
cmd->SetGraphicsRootSignature(sig);
cmd->SetDescriptorHeaps(1, &m_CBVUAVSRV.GetInterfacePtr());
cmd->SetGraphicsRootConstantBufferView(
0, cb->GetGPUVirtualAddress() + bindOffset * sizeof(Vec4f));
cmd->SetGraphicsRoot32BitConstants(1, sizeof(emptyRoot) / sizeof(uint32_t), &emptyRoot, 0);
cmd->SetGraphicsRoot32BitConstants(2, sizeof(rootData) / sizeof(uint32_t), &rootData, 0);
cmd->SetGraphicsRoot32BitConstants(3, sizeof(emptyRoot) / sizeof(uint32_t), &emptyRoot, 0);
cmd->SetGraphicsRootConstantBufferView(4, cbPacked->GetGPUVirtualAddress());
cmd->SetGraphicsRootDescriptorTable(5, m_CBVUAVSRV->GetGPUDescriptorHandleForHeapStart());
cmd->SetGraphicsRootConstantBufferView(
4, cb->GetGPUVirtualAddress() + bindOffset * sizeof(Vec4f) + 256);
6, cb->GetGPUVirtualAddress() + bindOffset * sizeof(Vec4f) + 256);
RSSetViewport(cmd, {0.0f, 0.0f, (float)screenWidth, (float)screenHeight, 0.0f, 1.0f});
RSSetScissorRect(cmd, {0, 0, screenWidth, screenHeight});
@@ -1104,6 +1104,12 @@ cbuffer consts : register(b0)
double doubleX;
};
cbuffer packed_consts : register(b1)
{
uint col1z : packoffset(c1.z);
uint col2w : packoffset(c2.w);
};
RWStructuredBuffer<uint4> bufIn : register(u0);
RWStructuredBuffer<uint4> bufOut : register(u1);
@@ -1152,6 +1158,12 @@ void main(int3 inTestIndex : SV_GroupID)
testResult.z = gsmStruct[gsmInt * 4].a.y;
testResult.w = gsmInt2DArray[ZERO][idx] + gsmInt2DArray[ONE][idx];
}
else if (testIndex == 2)
{
testResult = bufOut[0];
testResult.x += bufIn[0].x * (uint)col1z;
testResult.y += bufIn[0].y * (uint)col2w;
}
else
{
testResult.x = inTestIndex.x;
@@ -1890,6 +1902,7 @@ void main(int3 inTestIndex : SV_GroupID)
uavParam(D3D12_SHADER_VISIBILITY_ALL, 0, 0),
uavParam(D3D12_SHADER_VISIBILITY_ALL, 0, 1),
constParam(D3D12_SHADER_VISIBILITY_ALL, 0, 0, 4),
constParam(D3D12_SHADER_VISIBILITY_ALL, 0, 1, 12),
tableParam(D3D12_SHADER_VISIBILITY_ALL, D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 0, 2, 1, 3),
});
@@ -2123,7 +2136,9 @@ void main(int3 inTestIndex : SV_GroupID)
cmd->SetComputeRoot32BitConstant(2, 6, 1);
cmd->SetComputeRoot32BitConstant(2, 7, 2);
cmd->SetComputeRoot32BitConstant(2, 8, 3);
cmd->SetComputeRootDescriptorTable(3, m_CBVUAVSRV->GetGPUDescriptorHandleForHeapStart());
cmd->SetComputeRoot32BitConstant(3, 10, 4 + 2); // col1z
cmd->SetComputeRoot32BitConstant(3, 11, 8 + 3); // col2w
cmd->SetComputeRootDescriptorTable(4, m_CBVUAVSRV->GetGPUDescriptorHandleForHeapStart());
cmd->SetPipelineState(computePSOs[i]);
setMarker(cmd, computeSMs[i]);
+18 -9
View File
@@ -23,7 +23,12 @@ class D3D11_CBuffer_Zoo(rdtest.TestCase):
pipe.GetShaderEntryPoint(stage), 0,
cbuf.resource, cbuf.byteOffset, cbuf.byteSize))
self.check_cbuffer(var_check)
packed_check = rdtest.ConstantBufferChecker(
self.controller.GetCBufferVariableContents(pipe.GetGraphicsPipelineObject(),
pipe.GetShader(stage), stage,
pipe.GetShaderEntryPoint(stage), 1,
cbuf.resource, cbuf.byteOffset, cbuf.byteSize))
self.check_cbuffer(var_check, packed_check)
rdtest.log.success("CBuffer variables are as expected")
@@ -52,12 +57,12 @@ class D3D11_CBuffer_Zoo(rdtest.TestCase):
cbufferVars = self.combine_source_vars(cbufferVars)
self.check(len(cbufferVars) == 1)
self.check(len(cbufferVars) == 2)
self.check(cbufferVars[0].name == 'consts')
self.check(cbufferVars[1].name == 'packed_consts')
var_check = rdtest.ConstantBufferChecker(cbufferVars[0].members)
self.check_cbuffer(var_check)
packed_check = rdtest.ConstantBufferChecker(cbufferVars[1].members)
self.check_cbuffer(var_check, packed_check)
rdtest.log.success("Debugged CBuffer variables are as expected")
@@ -67,20 +72,20 @@ class D3D11_CBuffer_Zoo(rdtest.TestCase):
debugged = self.evaluate_source_var(output, variables)
if not rdtest.util.value_compare(debugged.value.f32v[0:4], [536.1, 537.0, 538.0, 539.0]):
if not rdtest.util.value_compare(debugged.value.f32v[0:4], [542.1, 543.0, 544.0, 545.0]):
raise rdtest.TestFailureException(
"Debugged output {} did not match expected {}".format(
debugged.value.f32v[0:4], [536.1, 537.0, 538.0, 539.0]))
debugged.value.f32v[0:4], [542.1, 543.0, 544.0, 545.0]))
rdtest.log.success("Debugged output matched as expected")
self.controller.FreeTrace(trace)
self.check_pixel_value(pipe.GetOutputTargets()[0].resource, 0.5, 0.5, [536.1, 537.0, 538.0, 539.0])
self.check_pixel_value(pipe.GetOutputTargets()[0].resource, 0.5, 0.5, [542.1, 543.0, 544.0, 545.0])
rdtest.log.success("Picked value is as expected")
def check_cbuffer(self, var_check):
def check_cbuffer(self, var_check, packed_check):
# For more detailed reference for the below checks, see the commented definition of the cbuffer
# in the shader source code in the demo itself
@@ -441,3 +446,7 @@ class D3D11_CBuffer_Zoo(rdtest.TestCase):
var_check.check('test').rows(1).cols(4).value([536.0, 537.0, 538.0, 539.0])
var_check.done()
packed_check.check('col1z').rows(1).cols(1).value([6.0])
packed_check.check('col2w').rows(1).cols(1).value([11.0])
packed_check.done()
+62 -13
View File
@@ -73,10 +73,12 @@ class D3D12_CBuffer_Zoo(rdtest.TestCase):
refl: rd.ShaderReflection = pipe.GetShaderReflection(stage)
# Make sure we have three constant buffers - b7 normal, b1 root constants, and space9999999:b0
# Make sure we have five constant buffers - b7 normal, b1 root constants, b2, b3 and space9999999:b0
binds = [
(0, 7),
(0, 1),
(0, 2),
(0, 3),
(999999999, 0),
]
@@ -106,18 +108,47 @@ class D3D12_CBuffer_Zoo(rdtest.TestCase):
pipe.GetShaderEntryPoint(stage), 1,
cbuf.resource, cbuf.byteOffset, cbuf.byteSize))
cbuf = pipe.GetConstantBlock(stage, 2, 0).descriptor
cbuf = pipe.GetConstantBlock(stage, 4, 0).descriptor
huge_check = rdtest.ConstantBufferChecker(
self.controller.GetCBufferVariableContents(pipe.GetGraphicsPipelineObject(),
pipe.GetShader(stage), stage,
pipe.GetShaderEntryPoint(stage), 4,
cbuf.resource, cbuf.byteOffset, cbuf.byteSize))
cbuf = pipe.GetConstantBlock(stage, 2, 0).descriptor
packed_check = rdtest.ConstantBufferChecker(
self.controller.GetCBufferVariableContents(pipe.GetGraphicsPipelineObject(),
pipe.GetShader(stage), stage,
pipe.GetShaderEntryPoint(stage), 2,
cbuf.resource, cbuf.byteOffset, cbuf.byteSize))
self.check_cbuffers(var_check, root_check, huge_check)
self.check_cbuffers(var_check, root_check, huge_check, packed_check)
rdtest.log.success("CBuffer variables are as expected")
cbuf = pipe.GetConstantBlock(stage, 3, 0).descriptor
arrays_check = rdtest.ConstantBufferChecker(
self.controller.GetCBufferVariableContents(pipe.GetGraphicsPipelineObject(),
pipe.GetShader(stage), stage,
pipe.GetShaderEntryPoint(stage), 3,
cbuf.resource, cbuf.byteOffset, cbuf.byteSize))
arrays_check.check('array_consts').rows(0).cols(0).structSize(1).members({
'a' : lambda y : y.rows(1).cols(4).value([0.0, 1.0, 0.5, 0.5])})
arrays_check.done()
cbuf = pipe.GetConstantBlock(stage, 3, 1).descriptor
arrays_check = rdtest.ConstantBufferChecker(
self.controller.GetCBufferVariableContents(pipe.GetGraphicsPipelineObject(),
pipe.GetShader(stage), stage,
pipe.GetShaderEntryPoint(stage), 3,
cbuf.resource, cbuf.byteOffset, cbuf.byteSize))
arrays_check.check('array_consts').rows(0).cols(0).structSize(1).members({
'a' : lambda y : y.rows(1).cols(4).value([1.0, 2.0, 0.5, 0.5])})
arrays_check.done()
rdtest.log.success("Array cbuffer variables are as expected")
if self.controller.GetAPIProperties().shaderDebugging and pipe.GetShaderReflection(
rd.ShaderStage.Pixel).debugInfo.debuggable:
trace: rd.ShaderDebugTrace = self.controller.DebugPixel(int(pipe.GetViewport(0).width / 2.0),
@@ -143,39 +174,49 @@ class D3D12_CBuffer_Zoo(rdtest.TestCase):
cbufferVars = self.combine_source_vars(cbufferVars)
self.check(len(cbufferVars) == 3)
self.check(len(cbufferVars) == 5)
self.check(cbufferVars[0].name == 'consts')
self.check(cbufferVars[1].name == 'rootconsts')
self.check(cbufferVars[2].name == 'hugespace')
self.check(cbufferVars[2].name == 'packed_consts')
self.check(cbufferVars[3].name == 'array_consts')
self.check(cbufferVars[4].name == 'hugespace')
var_check = rdtest.ConstantBufferChecker(cbufferVars[0].members)
root_check = rdtest.ConstantBufferChecker(cbufferVars[1].members)
huge_check = rdtest.ConstantBufferChecker(cbufferVars[2].members)
self.check_cbuffers(var_check, root_check, huge_check)
packed_check = rdtest.ConstantBufferChecker(cbufferVars[2].members)
arrays_check = rdtest.ConstantBufferChecker(cbufferVars[3].members)
huge_check = rdtest.ConstantBufferChecker(cbufferVars[4].members)
self.check_cbuffers(var_check, root_check, huge_check, packed_check)
rdtest.log.success("Debugged CBuffer variables are as expected")
arrays_check.check('[0]').rows(0).cols(0).members({
'a' : lambda y : y.rows(1).cols(4).value([0.0, 1.0, 0.5, 0.5])})
arrays_check.check('[1]').rows(0).cols(0).members({
'a' : lambda y : y.rows(1).cols(4).value([1.0, 2.0, 0.5, 0.5])})
arrays_check.done()
rdtest.log.success("Array cbuffer variables are as expected")
cycles, variables = self.process_trace(trace)
output = self.find_output_source_var(trace, rd.ShaderBuiltin.ColorOutput, 0)
debugged = self.evaluate_source_var(output, variables)
if not rdtest.util.value_compare(debugged.value.f32v[0:4], [536.1, 537.0, 538.0, 539.0]):
if not rdtest.util.value_compare(debugged.value.f32v[0:4], [543.1, 546.0, 545.0, 546.0]):
raise rdtest.TestFailureException(
"Debugged output {} did not match expected {}".format(
debugged.value.f32v[0:4], [536.1, 537.0, 538.0, 539.0]))
debugged.value.f32v[0:4], [543.1, 546.0, 545.0, 546.0]))
rdtest.log.success("Debugged output matched as expected")
self.controller.FreeTrace(trace)
self.check_pixel_value(pipe.GetOutputTargets()[0].resource, 0.5, 0.5, [536.1, 537.0, 538.0, 539.0])
self.check_pixel_value(pipe.GetOutputTargets()[0].resource, 0.5, 0.5, [543.1, 546.0, 545.0, 546.0])
rdtest.log.success("Picked value is as expected")
def check_cbuffers(self, var_check, root_check, huge_check):
def check_cbuffers(self, var_check, root_check, huge_check, packed_check):
# For more detailed reference for the below checks, see the commented definition of the cbuffer
# in the shader source code in the demo itself
@@ -565,5 +606,13 @@ class D3D12_CBuffer_Zoo(rdtest.TestCase):
# float4 huge_val;
huge_check.check('huge_val').rows(1).cols(4).value([64.0, 65.0, 66.0, 67.0])
huge_check.done()
rdtest.log.success("Huge space variables are as expected")
packed_check.check('col1z').rows(1).cols(1).value([6.0])
packed_check.check('col2w').rows(1).cols(1).value([11.0])
packed_check.done()
rdtest.log.success("Packed cbuffer variables are as expected")