Check that we handle padding and alignment around structs

* On all APIs structs are aligned up to 16-byte alignment, and on D3D as with
  arrays then elements coming after the struct can be packed into the padding
  after the last struct element.
This commit is contained in:
baldurk
2019-11-28 17:12:47 +00:00
parent 89d794ed5a
commit 77b5c391e9
8 changed files with 187 additions and 22 deletions
+15 -1
View File
@@ -36,6 +36,8 @@ struct float3_1 { float3 a; float b; };
struct nested { float3_1 a; float4 b[4]; float3_1 c[4]; };
struct float2_struct { float x; float y; };
struct nested_with_padding
{
float a; // 0, <1, 2, 3>
@@ -239,7 +241,19 @@ cbuffer consts : register(b0)
nested_with_padding ak[2]; // 440 - 467, 468 - 495
float4 test; // {496, 497, 498, 499}
float4 dummy13; // forces no trailing overlap with ak
float al; // {500}, <501, 502, 503>
// struct is always float4 aligned, can't be packed with al
float2_struct am; // {504, 505}, <506, 507>
// struct allows trailing things into padding
float an; // {506}
float4 gldummy4; // account for an not overlapping in GL/VK
float4 test; // {512, 513, 514, 515}
};
float4 main() : SV_Target0
+15 -1
View File
@@ -36,6 +36,8 @@ struct float3_1 { float3 a; float b; };
struct nested { float3_1 a; float4 b[4]; float3_1 c[4]; };
struct float2_struct { float x; float y; };
struct nested_with_padding
{
float a; // 0, <1, 2, 3>
@@ -239,7 +241,19 @@ cbuffer consts : register(b0)
nested_with_padding ak[2]; // 440 - 467, 468 - 495
float4 test; // {496, 497, 498, 499}
float4 dummy13; // forces no trailing overlap with ak
float al; // {500}, <501, 502, 503>
// struct is always float4 aligned, can't be packed with al
float2_struct am; // {504, 505}, <506, 507>
// struct allows trailing things into padding
float an; // {506}
float4 gldummy4; // account for an not overlapping in GL/VK
float4 test; // {512, 513, 514, 515}
};
// this comes from root signature constants
+16 -4
View File
@@ -71,6 +71,8 @@ struct vec3_1 { vec3 a; float b; };
struct nested { vec3_1 a; vec4 b[4]; vec3_1 c[4]; };
struct float2_struct { float x; float y; };
struct nested_with_padding
{
float a; // 0, <1, 2, 3>
@@ -270,14 +272,24 @@ layout(binding = 0, std140) uniform constsbuf
nested_with_padding ak[2]; // 440 - 467, 468 - 495
vec4 test; // {496, 497, 498, 499}
vec4 dummy12; // forces no trailing overlap with ak
float al; // {500}, <501, 502, 503>
// struct is always float4 aligned, can't be packed with al
float2_struct am; // {504, 505}, <506, 507>
// struct doesn't allow trailing things into padding
float an; // {506}
vec4 test; // {512, 513, 514, 515}
// because GL has worse handling of multidimensional arrays than other APIs, we add an extra test
// here with more than 2 dimensions
vec4 multiarray2[4][3][2]; // [0][0][0] = {500, 501, 502, 503}
// [0][0][1] = {504, 505, 506, 507}
// [0][1][0] = {508, ..., ..., ...}
vec4 multiarray2[4][3][2]; // [0][0][0] = {516, 517, 518, ...}
// [0][0][1] = {..., ..., ..., ...}
// [0][1][0] = {..., ..., ..., ...}
// [0][1][1] = {..., ..., ..., ...}
// [0][2][0] = {..., ..., ..., ...}
// [0][2][1] = {..., ..., ..., ...}
+27 -3
View File
@@ -70,6 +70,8 @@ struct vec3_1 { vec3 a; float b; };
struct nested { vec3_1 a; vec4 b[4]; vec3_1 c[4]; };
struct float2_struct { float x; float y; };
struct nested_with_padding
{
float a; // 0, <1, 2, 3>
@@ -269,7 +271,17 @@ layout(set = 0, binding = 0, std140) uniform constsbuf
nested_with_padding ak[2]; // 440 - 467, 468 - 495
vec4 test; // {496, 497, 498, 499}
vec4 dummy12; // forces no trailing overlap with ak
float al; // {500}, <501, 502, 503>
// struct is always float4 aligned, can't be packed with al
float2_struct am; // {504, 505}, <506, 507>
// struct doesn't allow trailing things into padding
float an; // {508}
vec4 test; // {512, 513, 514, 515}
};
layout (constant_id = 0) const int A = 10;
@@ -289,6 +301,8 @@ struct float3_1 { float3 a; float b; };
struct nested { float3_1 a; float4 b[4]; float3_1 c[4]; };
struct float2_struct { float x; float y; };
struct nested_with_padding
{
float a; // 0, <1, 2, 3>
@@ -496,9 +510,19 @@ layout(set = 0, binding = 0) cbuffer consts
// <435, 439>
// }
nested_with_padding ak[2]; // 440 - 467, 468 - 495
nested_with_padding ak[2]; // 440 - 467, 468 - 494
float4 dummy14; // forces no trailing overlap with ak
float4 test; // {496, 497, 498, 499}
float al; // {500}, <501, 502, 503>
// struct is always float4 aligned, can't be packed with al
float2_struct am; // {504, 505}, <506, 507>
// struct doesn't allow trailing things into padding
float an; // {508}
float4 test; // {512, 513, 514, 515}
};
float4 main() : SV_Target0
+24 -2
View File
@@ -335,13 +335,35 @@ class D3D11_CBuffer_Zoo(rdtest.TestCase):
}),
})
# float2 dummy13;
var_check.check('dummy13')
# float al;
var_check.check('al').rows(1).cols(1).value([500.0])
# struct float2_struct
# {
# float x, y;
# };
# float2_struct am;
var_check.check('am').rows(0).cols(0).members({
'x': lambda y: y.rows(1).cols(1).value([504.0]),
'y': lambda y: y.rows(1).cols(1).value([505.0]),
})
# float an;
var_check.check('an').rows(1).cols(1).value([506.0])
# float4 gldummy4;
var_check.check('gldummy4')
# float4 test;
var_check.check('test').rows(1).cols(4).value([496.0, 497.0, 498.0, 499.0])
var_check.check('test').rows(1).cols(4).value([512.0, 513.0, 514.0, 515.0])
var_check.done()
rdtest.log.success("CBuffer variables are as expected")
self.check_pixel_value(pipe.GetOutputTargets()[0].resourceId, 0.5, 0.5, [496.1, 497.0, 498.0, 499.0])
self.check_pixel_value(pipe.GetOutputTargets()[0].resourceId, 0.5, 0.5, [512.1, 513.0, 514.0, 515.0])
rdtest.log.success("Picked value is as expected")
+24 -2
View File
@@ -357,14 +357,36 @@ class D3D12_CBuffer_Zoo(rdtest.TestCase):
}),
})
# float2 dummy13;
var_check.check('dummy13')
# float al;
var_check.check('al').rows(1).cols(1).value([500.0])
# struct float2_struct
# {
# float x, y;
# };
# float2_struct am;
var_check.check('am').rows(0).cols(0).members({
'x': lambda y: y.rows(1).cols(1).value([504.0]),
'y': lambda y: y.rows(1).cols(1).value([505.0]),
})
# float an;
var_check.check('an').rows(1).cols(1).value([506.0])
# float4 gldummy4;
var_check.check('gldummy4')
# float4 test;
var_check.check('test').rows(1).cols(4).value([496.0, 497.0, 498.0, 499.0])
var_check.check('test').rows(1).cols(4).value([512.0, 513.0, 514.0, 515.0])
var_check.done()
rdtest.log.success("CBuffer variables are as expected")
self.check_pixel_value(pipe.GetOutputTargets()[0].resourceId, 0.5, 0.5, [496.1, 497.0, 498.0, 499.0])
self.check_pixel_value(pipe.GetOutputTargets()[0].resourceId, 0.5, 0.5, [512.1, 513.0, 514.0, 515.0])
rdtest.log.success("Picked value is as expected")
+23 -4
View File
@@ -320,11 +320,30 @@ class GL_CBuffer_Zoo(rdtest.TestCase):
}),
})
# vec4 test;
var_check.check('test').rows(1).cols(4).value([496.0, 497.0, 498.0, 499.0])
# float2 dummy12;
var_check.check('dummy12')
# float al;
var_check.check('al').rows(1).cols(1).value([500.0])
# struct float2_struct
# {
# float x, y;
# };
# float2_struct am;
var_check.check('am').rows(0).cols(0).members({
'x': lambda y: y.rows(1).cols(1).value([504.0]),
'y': lambda y: y.rows(1).cols(1).value([505.0]),
})
# float an;
var_check.check('an').rows(1).cols(1).value([508.0])
# float4 test;
var_check.check('test').rows(1).cols(4).value([512.0, 513.0, 514.0, 515.0])
# to save duplicating if this array changes, we calculate out from the start, as the array is tightly packed
base = 500.0
base = 516.0
exp_vals = lambda wi,yi,xi: [base + wi * 24.0 + yi * 8.0 + xi * 4.0 + c * 1.0 for c in range(0,4)]
@@ -392,7 +411,7 @@ class GL_CBuffer_Zoo(rdtest.TestCase):
rdtest.log.success("CBuffer variables are as expected")
self.check_pixel_value(pipe.GetOutputTargets()[0].resourceId, 0.5, 0.5, [496.1, 497.0, 498.0, 499.0])
self.check_pixel_value(pipe.GetOutputTargets()[0].resourceId, 0.5, 0.5, [512.1, 513.0, 514.0, 515.0])
rdtest.log.success("Picked value is as expected")
+43 -5
View File
@@ -327,14 +327,33 @@ class VK_CBuffer_Zoo(rdtest.TestCase):
}),
})
# vec4 test;
var_check.check('test').rows(1).cols(4).value([496.0, 497.0, 498.0, 499.0])
# vec4 dummy12;
var_check.check('dummy12')
# float al;
var_check.check('al').rows(1).cols(1).value([500.0])
# struct float2_struct
# {
# float x, y;
# };
# float2_struct am;
var_check.check('am').rows(0).cols(0).members({
'x': lambda y: y.rows(1).cols(1).value([504.0]),
'y': lambda y: y.rows(1).cols(1).value([505.0]),
})
# float an;
var_check.check('an').rows(1).cols(1).value([508.0])
# float4 test;
var_check.check('test').rows(1).cols(4).value([512.0, 513.0, 514.0, 515.0])
var_check.done()
rdtest.log.success("GLSL CBuffer variables are as expected")
self.check_pixel_value(pipe.GetOutputTargets()[0].resourceId, 0.5, 0.5, [496.1, 497.0, 498.0, 499.0])
self.check_pixel_value(pipe.GetOutputTargets()[0].resourceId, 0.5, 0.5, [512.1, 513.0, 514.0, 515.0])
rdtest.log.success("GLSL picked value is as expected")
@@ -704,13 +723,32 @@ class VK_CBuffer_Zoo(rdtest.TestCase):
}),
})
# float4 dummy14;
var_check.check('dummy14')
# float al;
var_check.check('al').rows(1).cols(1).value([500.0])
# struct float2_struct
# {
# float x, y;
# };
# float2_struct am;
var_check.check('am').rows(0).cols(0).members({
'x': lambda y: y.rows(1).cols(1).value([504.0]),
'y': lambda y: y.rows(1).cols(1).value([505.0]),
})
# float an;
var_check.check('an').rows(1).cols(1).value([508.0])
# float4 test;
var_check.check('test').rows(1).cols(4).value([496.0, 497.0, 498.0, 499.0])
var_check.check('test').rows(1).cols(4).value([512.0, 513.0, 514.0, 515.0])
var_check.done()
rdtest.log.success("HLSL CBuffer variables are as expected")
self.check_pixel_value(pipe.GetOutputTargets()[0].resourceId, 0.5, 0.5, [496.1, 497.0, 498.0, 499.0])
self.check_pixel_value(pipe.GetOutputTargets()[0].resourceId, 0.5, 0.5, [512.1, 513.0, 514.0, 515.0])
rdtest.log.success("HLSL picked value is as expected")