xref: /aosp_15_r20/external/skia/tests/graphite/UniformManagerTest.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2022 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker 
8*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkFloatBits.h"
9*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkHalf.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkSLTypeShared.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/PipelineData.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/Uniform.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/UniformManager.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "tests/Test.h"
15*c8dee2aaSAndroid Build Coastguard Worker 
16*c8dee2aaSAndroid Build Coastguard Worker using namespace skgpu::graphite;
17*c8dee2aaSAndroid Build Coastguard Worker 
18*c8dee2aaSAndroid Build Coastguard Worker static constexpr Layout kLayouts[] = {
19*c8dee2aaSAndroid Build Coastguard Worker         Layout::kStd140,
20*c8dee2aaSAndroid Build Coastguard Worker         Layout::kStd430,
21*c8dee2aaSAndroid Build Coastguard Worker         Layout::kMetal,
22*c8dee2aaSAndroid Build Coastguard Worker };
23*c8dee2aaSAndroid Build Coastguard Worker 
24*c8dee2aaSAndroid Build Coastguard Worker // This list excludes SkSLTypes that we don't support in uniforms, like Bool, UInt or UShort.
25*c8dee2aaSAndroid Build Coastguard Worker static constexpr SkSLType kTypes[] = {
26*c8dee2aaSAndroid Build Coastguard Worker         SkSLType::kFloat,    SkSLType::kFloat2,   SkSLType::kFloat3,   SkSLType::kFloat4,   //
27*c8dee2aaSAndroid Build Coastguard Worker         SkSLType::kHalf,     SkSLType::kHalf2,    SkSLType::kHalf3,    SkSLType::kHalf4,    //
28*c8dee2aaSAndroid Build Coastguard Worker         SkSLType::kInt,      SkSLType::kInt2,     SkSLType::kInt3,     SkSLType::kInt4,     //
29*c8dee2aaSAndroid Build Coastguard Worker         SkSLType::kFloat2x2, SkSLType::kFloat3x3, SkSLType::kFloat4x4,                      //
30*c8dee2aaSAndroid Build Coastguard Worker         SkSLType::kHalf2x2,  SkSLType::kHalf3x3,  SkSLType::kHalf4x4,
31*c8dee2aaSAndroid Build Coastguard Worker };
32*c8dee2aaSAndroid Build Coastguard Worker 
33*c8dee2aaSAndroid Build Coastguard Worker static constexpr float kFloats[16] = { 1.0f,  2.0f,  3.0f,  4.0f,
34*c8dee2aaSAndroid Build Coastguard Worker                                        5.0f,  6.0f,  7.0f,  8.0f,
35*c8dee2aaSAndroid Build Coastguard Worker                                        9.0f, 10.0f, 11.0f, 12.0f,
36*c8dee2aaSAndroid Build Coastguard Worker                                       13.0f, 14.0f, 15.0f, 16.0f };
37*c8dee2aaSAndroid Build Coastguard Worker 
38*c8dee2aaSAndroid Build Coastguard Worker static constexpr SkHalf kHalfs[16] = { 0x3C00, 0x4000, 0x4200, 0x4400,
39*c8dee2aaSAndroid Build Coastguard Worker                                        0x4500, 0x4600, 0x4700, 0x4800,
40*c8dee2aaSAndroid Build Coastguard Worker                                        0x4880, 0x4900, 0x4980, 0x4A00,
41*c8dee2aaSAndroid Build Coastguard Worker                                        0x4A80, 0x4B00, 0x4B80, 0x4C00 };
42*c8dee2aaSAndroid Build Coastguard Worker 
43*c8dee2aaSAndroid Build Coastguard Worker static constexpr int32_t kInts[16] = { 1,  -2,  3,  -4,
44*c8dee2aaSAndroid Build Coastguard Worker                                        5,  -6,  7,  -8,
45*c8dee2aaSAndroid Build Coastguard Worker                                        9, -10, 11, -12,
46*c8dee2aaSAndroid Build Coastguard Worker                                       13, -14, 15, -16 };
47*c8dee2aaSAndroid Build Coastguard Worker 
element_size(Layout layout,SkSLType type)48*c8dee2aaSAndroid Build Coastguard Worker static size_t element_size(Layout layout, SkSLType type) {
49*c8dee2aaSAndroid Build Coastguard Worker     // Metal encodes half-precision uniforms in 16 bits.
50*c8dee2aaSAndroid Build Coastguard Worker     // Other layouts are expected to encode uniforms in 32 bits.
51*c8dee2aaSAndroid Build Coastguard Worker     return (layout == Layout::kMetal && !SkSLTypeIsFullPrecisionNumericType(type)) ? 2 : 4;
52*c8dee2aaSAndroid Build Coastguard Worker }
53*c8dee2aaSAndroid Build Coastguard Worker 
DEF_GRAPHITE_TEST(UniformManagerCheckSingleUniform,r,CtsEnforcement::kApiLevel_V)54*c8dee2aaSAndroid Build Coastguard Worker DEF_GRAPHITE_TEST(UniformManagerCheckSingleUniform, r, CtsEnforcement::kApiLevel_V) {
55*c8dee2aaSAndroid Build Coastguard Worker     // Verify that the uniform manager can hold all the basic uniform types, in every layout.
56*c8dee2aaSAndroid Build Coastguard Worker     for (Layout layout : kLayouts) {
57*c8dee2aaSAndroid Build Coastguard Worker         UniformManager mgr(layout);
58*c8dee2aaSAndroid Build Coastguard Worker 
59*c8dee2aaSAndroid Build Coastguard Worker         for (SkSLType type : kTypes) {
60*c8dee2aaSAndroid Build Coastguard Worker             const Uniform expectations[] = {{"uniform", type}};
61*c8dee2aaSAndroid Build Coastguard Worker             SkDEBUGCODE(mgr.setExpectedUniforms(SkSpan(expectations), /*isSubstruct=*/false);)
62*c8dee2aaSAndroid Build Coastguard Worker             mgr.write(expectations[0], kFloats);
63*c8dee2aaSAndroid Build Coastguard Worker             SkDEBUGCODE(mgr.doneWithExpectedUniforms();)
64*c8dee2aaSAndroid Build Coastguard Worker             REPORTER_ASSERT(r, mgr.size() > 0, "Layout: %s - Type: %s",
65*c8dee2aaSAndroid Build Coastguard Worker                             LayoutString(layout), SkSLTypeString(type));
66*c8dee2aaSAndroid Build Coastguard Worker             mgr.reset();
67*c8dee2aaSAndroid Build Coastguard Worker         }
68*c8dee2aaSAndroid Build Coastguard Worker     }
69*c8dee2aaSAndroid Build Coastguard Worker }
70*c8dee2aaSAndroid Build Coastguard Worker 
DEF_GRAPHITE_TEST(UniformManagerCheckFloatEncoding,r,CtsEnforcement::kApiLevel_V)71*c8dee2aaSAndroid Build Coastguard Worker DEF_GRAPHITE_TEST(UniformManagerCheckFloatEncoding, r, CtsEnforcement::kApiLevel_V) {
72*c8dee2aaSAndroid Build Coastguard Worker     // Verify that the uniform manager encodes float data properly.
73*c8dee2aaSAndroid Build Coastguard Worker     for (Layout layout : kLayouts) {
74*c8dee2aaSAndroid Build Coastguard Worker         UniformManager mgr(layout);
75*c8dee2aaSAndroid Build Coastguard Worker 
76*c8dee2aaSAndroid Build Coastguard Worker         for (SkSLType type : kTypes) {
77*c8dee2aaSAndroid Build Coastguard Worker             // Only test scalar and vector floats. (Matrices can introduce padding between values.)
78*c8dee2aaSAndroid Build Coastguard Worker             int vecLength = SkSLTypeVecLength(type);
79*c8dee2aaSAndroid Build Coastguard Worker             if (!SkSLTypeIsFloatType(type) || vecLength < 1) {
80*c8dee2aaSAndroid Build Coastguard Worker                 continue;
81*c8dee2aaSAndroid Build Coastguard Worker             }
82*c8dee2aaSAndroid Build Coastguard Worker 
83*c8dee2aaSAndroid Build Coastguard Worker             // Write our uniform float scalar/vector.
84*c8dee2aaSAndroid Build Coastguard Worker             const Uniform expectations[] = {{"uniform", type}};
85*c8dee2aaSAndroid Build Coastguard Worker             SkDEBUGCODE(mgr.setExpectedUniforms(SkSpan(expectations), /*isSubstruct=*/false);)
86*c8dee2aaSAndroid Build Coastguard Worker             mgr.write(expectations[0], kFloats);
87*c8dee2aaSAndroid Build Coastguard Worker             SkDEBUGCODE(mgr.doneWithExpectedUniforms();)
88*c8dee2aaSAndroid Build Coastguard Worker 
89*c8dee2aaSAndroid Build Coastguard Worker             // Read back the uniform data.
90*c8dee2aaSAndroid Build Coastguard Worker             SkSpan<const char> uniformData = mgr.finish();
91*c8dee2aaSAndroid Build Coastguard Worker             size_t elementSize = element_size(layout, type);
92*c8dee2aaSAndroid Build Coastguard Worker             const void* validData = (elementSize == 4) ? (const void*)kFloats : (const void*)kHalfs;
93*c8dee2aaSAndroid Build Coastguard Worker             REPORTER_ASSERT(r, uniformData.size() >= vecLength * elementSize);
94*c8dee2aaSAndroid Build Coastguard Worker             REPORTER_ASSERT(r, 0 == memcmp(validData, uniformData.data(), vecLength * elementSize),
95*c8dee2aaSAndroid Build Coastguard Worker                             "Layout: %s - Type: %s float encoding failed",
96*c8dee2aaSAndroid Build Coastguard Worker                             LayoutString(layout), SkSLTypeString(type));
97*c8dee2aaSAndroid Build Coastguard Worker             mgr.reset();
98*c8dee2aaSAndroid Build Coastguard Worker         }
99*c8dee2aaSAndroid Build Coastguard Worker     }
100*c8dee2aaSAndroid Build Coastguard Worker }
101*c8dee2aaSAndroid Build Coastguard Worker 
DEF_GRAPHITE_TEST(UniformManagerCheckIntEncoding,r,CtsEnforcement::kApiLevel_V)102*c8dee2aaSAndroid Build Coastguard Worker DEF_GRAPHITE_TEST(UniformManagerCheckIntEncoding, r, CtsEnforcement::kApiLevel_V) {
103*c8dee2aaSAndroid Build Coastguard Worker     // Verify that the uniform manager encodes int data properly.
104*c8dee2aaSAndroid Build Coastguard Worker     for (Layout layout : kLayouts) {
105*c8dee2aaSAndroid Build Coastguard Worker         UniformManager mgr(layout);
106*c8dee2aaSAndroid Build Coastguard Worker 
107*c8dee2aaSAndroid Build Coastguard Worker         for (SkSLType type : kTypes) {
108*c8dee2aaSAndroid Build Coastguard Worker             if (!SkSLTypeIsIntegralType(type)) {
109*c8dee2aaSAndroid Build Coastguard Worker                 continue;
110*c8dee2aaSAndroid Build Coastguard Worker             }
111*c8dee2aaSAndroid Build Coastguard Worker 
112*c8dee2aaSAndroid Build Coastguard Worker             // Write our uniform int scalar/vector.
113*c8dee2aaSAndroid Build Coastguard Worker             const Uniform expectations[] = {{"uniform", type}};
114*c8dee2aaSAndroid Build Coastguard Worker             SkDEBUGCODE(mgr.setExpectedUniforms(SkSpan(expectations), /*isSubstruct=*/false);)
115*c8dee2aaSAndroid Build Coastguard Worker             mgr.write(expectations[0], kInts);
116*c8dee2aaSAndroid Build Coastguard Worker             SkDEBUGCODE(mgr.doneWithExpectedUniforms();)
117*c8dee2aaSAndroid Build Coastguard Worker 
118*c8dee2aaSAndroid Build Coastguard Worker             // Read back the uniform data.
119*c8dee2aaSAndroid Build Coastguard Worker             SkSpan<const char> uniformData = mgr.finish();
120*c8dee2aaSAndroid Build Coastguard Worker             int vecLength = SkSLTypeVecLength(type);
121*c8dee2aaSAndroid Build Coastguard Worker             size_t elementSize = element_size(layout, type);
122*c8dee2aaSAndroid Build Coastguard Worker             REPORTER_ASSERT(r, uniformData.size() >= vecLength * elementSize);
123*c8dee2aaSAndroid Build Coastguard Worker             REPORTER_ASSERT(r, 0 == memcmp(kInts, uniformData.data(), vecLength * elementSize),
124*c8dee2aaSAndroid Build Coastguard Worker                             "Layout: %s - Type: %s int encoding failed",
125*c8dee2aaSAndroid Build Coastguard Worker                             LayoutString(layout), SkSLTypeString(type));
126*c8dee2aaSAndroid Build Coastguard Worker             mgr.reset();
127*c8dee2aaSAndroid Build Coastguard Worker         }
128*c8dee2aaSAndroid Build Coastguard Worker     }
129*c8dee2aaSAndroid Build Coastguard Worker }
130*c8dee2aaSAndroid Build Coastguard Worker 
DEF_GRAPHITE_TEST(UniformManagerCheckScalarVectorPacking,r,CtsEnforcement::kApiLevel_V)131*c8dee2aaSAndroid Build Coastguard Worker DEF_GRAPHITE_TEST(UniformManagerCheckScalarVectorPacking, r, CtsEnforcement::kApiLevel_V) {
132*c8dee2aaSAndroid Build Coastguard Worker     // Verify that the uniform manager can pack scalars and vectors of identical type correctly.
133*c8dee2aaSAndroid Build Coastguard Worker     for (Layout layout : kLayouts) {
134*c8dee2aaSAndroid Build Coastguard Worker         UniformManager mgr(layout);
135*c8dee2aaSAndroid Build Coastguard Worker 
136*c8dee2aaSAndroid Build Coastguard Worker         for (SkSLType type : kTypes) {
137*c8dee2aaSAndroid Build Coastguard Worker             int vecLength = SkSLTypeVecLength(type);
138*c8dee2aaSAndroid Build Coastguard Worker             if (vecLength < 1) {
139*c8dee2aaSAndroid Build Coastguard Worker                 continue;
140*c8dee2aaSAndroid Build Coastguard Worker             }
141*c8dee2aaSAndroid Build Coastguard Worker 
142*c8dee2aaSAndroid Build Coastguard Worker             // Write three matching uniforms.
143*c8dee2aaSAndroid Build Coastguard Worker             const Uniform expectations[] = {{"a", type}, {"b", type}, {"c", type}};
144*c8dee2aaSAndroid Build Coastguard Worker             SkDEBUGCODE(mgr.setExpectedUniforms(SkSpan(expectations), /*isSubstruct=*/false);)
145*c8dee2aaSAndroid Build Coastguard Worker             mgr.write(expectations[0], kFloats);
146*c8dee2aaSAndroid Build Coastguard Worker             mgr.write(expectations[1], kFloats);
147*c8dee2aaSAndroid Build Coastguard Worker             mgr.write(expectations[2], kFloats);
148*c8dee2aaSAndroid Build Coastguard Worker             SkDEBUGCODE(mgr.doneWithExpectedUniforms();)
149*c8dee2aaSAndroid Build Coastguard Worker 
150*c8dee2aaSAndroid Build Coastguard Worker             // Verify the uniform data packing.
151*c8dee2aaSAndroid Build Coastguard Worker             SkSpan<const char> uniformData = mgr.finish();
152*c8dee2aaSAndroid Build Coastguard Worker             size_t elementSize = element_size(layout, type);
153*c8dee2aaSAndroid Build Coastguard Worker             // Vec3s must be laid out as if they were vec4s.
154*c8dee2aaSAndroid Build Coastguard Worker             size_t effectiveVecLength = (vecLength == 3) ? 4 : vecLength;
155*c8dee2aaSAndroid Build Coastguard Worker             REPORTER_ASSERT(r, uniformData.size() == elementSize * effectiveVecLength * 3,
156*c8dee2aaSAndroid Build Coastguard Worker                             "Layout: %s - Type: %s tight packing failed",
157*c8dee2aaSAndroid Build Coastguard Worker                             LayoutString(layout), SkSLTypeString(type));
158*c8dee2aaSAndroid Build Coastguard Worker             mgr.reset();
159*c8dee2aaSAndroid Build Coastguard Worker         }
160*c8dee2aaSAndroid Build Coastguard Worker     }
161*c8dee2aaSAndroid Build Coastguard Worker }
162*c8dee2aaSAndroid Build Coastguard Worker 
DEF_GRAPHITE_TEST(UniformManagerCheckMatrixPacking,r,CtsEnforcement::kApiLevel_V)163*c8dee2aaSAndroid Build Coastguard Worker DEF_GRAPHITE_TEST(UniformManagerCheckMatrixPacking, r, CtsEnforcement::kApiLevel_V) {
164*c8dee2aaSAndroid Build Coastguard Worker     // Verify that the uniform manager can pack matrices correctly.
165*c8dee2aaSAndroid Build Coastguard Worker     for (Layout layout : kLayouts) {
166*c8dee2aaSAndroid Build Coastguard Worker         UniformManager mgr(layout);
167*c8dee2aaSAndroid Build Coastguard Worker 
168*c8dee2aaSAndroid Build Coastguard Worker         for (SkSLType type : kTypes) {
169*c8dee2aaSAndroid Build Coastguard Worker             int matrixSize = SkSLTypeMatrixSize(type);
170*c8dee2aaSAndroid Build Coastguard Worker             if (matrixSize < 2) {
171*c8dee2aaSAndroid Build Coastguard Worker                 continue;
172*c8dee2aaSAndroid Build Coastguard Worker             }
173*c8dee2aaSAndroid Build Coastguard Worker 
174*c8dee2aaSAndroid Build Coastguard Worker             // Write three matching uniforms.
175*c8dee2aaSAndroid Build Coastguard Worker             const Uniform expectations[] = {{"a", type}, {"b", type}, {"c", type}};
176*c8dee2aaSAndroid Build Coastguard Worker             SkDEBUGCODE(mgr.setExpectedUniforms(SkSpan(expectations), /*isSubstruct=*/false);)
177*c8dee2aaSAndroid Build Coastguard Worker             mgr.write(expectations[0], kFloats);
178*c8dee2aaSAndroid Build Coastguard Worker             mgr.write(expectations[1], kFloats);
179*c8dee2aaSAndroid Build Coastguard Worker             mgr.write(expectations[2], kFloats);
180*c8dee2aaSAndroid Build Coastguard Worker             SkDEBUGCODE(mgr.doneWithExpectedUniforms();)
181*c8dee2aaSAndroid Build Coastguard Worker 
182*c8dee2aaSAndroid Build Coastguard Worker             // Verify the uniform data packing.
183*c8dee2aaSAndroid Build Coastguard Worker             SkSpan<const char> uniformData = mgr.finish();
184*c8dee2aaSAndroid Build Coastguard Worker             size_t elementSize = element_size(layout, type);
185*c8dee2aaSAndroid Build Coastguard Worker             // In all layouts, mat3s burn 12 elements, not 9. In std140, mat2s burn 8 elements
186*c8dee2aaSAndroid Build Coastguard Worker             // instead of 4.
187*c8dee2aaSAndroid Build Coastguard Worker             size_t numElements;
188*c8dee2aaSAndroid Build Coastguard Worker             if (matrixSize == 3) {
189*c8dee2aaSAndroid Build Coastguard Worker                 numElements = 12;
190*c8dee2aaSAndroid Build Coastguard Worker             } else if (matrixSize == 2 && layout == Layout::kStd140) {
191*c8dee2aaSAndroid Build Coastguard Worker                 numElements = 8;
192*c8dee2aaSAndroid Build Coastguard Worker             } else {
193*c8dee2aaSAndroid Build Coastguard Worker                 numElements = matrixSize * matrixSize;
194*c8dee2aaSAndroid Build Coastguard Worker             }
195*c8dee2aaSAndroid Build Coastguard Worker             REPORTER_ASSERT(r, uniformData.size() == elementSize * numElements * 3,
196*c8dee2aaSAndroid Build Coastguard Worker                             "Layout: %s - Type: %s matrix packing failed",
197*c8dee2aaSAndroid Build Coastguard Worker                             LayoutString(layout), SkSLTypeString(type));
198*c8dee2aaSAndroid Build Coastguard Worker             mgr.reset();
199*c8dee2aaSAndroid Build Coastguard Worker         }
200*c8dee2aaSAndroid Build Coastguard Worker     }
201*c8dee2aaSAndroid Build Coastguard Worker }
202*c8dee2aaSAndroid Build Coastguard Worker 
DEF_GRAPHITE_TEST(UniformManagerCheckPaddingScalarVector,r,CtsEnforcement::kApiLevel_V)203*c8dee2aaSAndroid Build Coastguard Worker DEF_GRAPHITE_TEST(UniformManagerCheckPaddingScalarVector, r, CtsEnforcement::kApiLevel_V) {
204*c8dee2aaSAndroid Build Coastguard Worker     // Verify that the uniform manager properly adds padding between pairs of scalar/vector.
205*c8dee2aaSAndroid Build Coastguard Worker     for (Layout layout : kLayouts) {
206*c8dee2aaSAndroid Build Coastguard Worker         UniformManager mgr(layout);
207*c8dee2aaSAndroid Build Coastguard Worker 
208*c8dee2aaSAndroid Build Coastguard Worker         for (SkSLType type1 : kTypes) {
209*c8dee2aaSAndroid Build Coastguard Worker             const int vecLength1 = SkSLTypeVecLength(type1);
210*c8dee2aaSAndroid Build Coastguard Worker             if (vecLength1 < 1) {
211*c8dee2aaSAndroid Build Coastguard Worker                 continue;
212*c8dee2aaSAndroid Build Coastguard Worker             }
213*c8dee2aaSAndroid Build Coastguard Worker 
214*c8dee2aaSAndroid Build Coastguard Worker             for (SkSLType type2 : kTypes) {
215*c8dee2aaSAndroid Build Coastguard Worker                 const int vecLength2 = SkSLTypeVecLength(type2);
216*c8dee2aaSAndroid Build Coastguard Worker                 if (vecLength2 < 1) {
217*c8dee2aaSAndroid Build Coastguard Worker                     continue;
218*c8dee2aaSAndroid Build Coastguard Worker                 }
219*c8dee2aaSAndroid Build Coastguard Worker 
220*c8dee2aaSAndroid Build Coastguard Worker                 // Write two scalar/vector uniforms.
221*c8dee2aaSAndroid Build Coastguard Worker                 const Uniform expectations[] = {{"a", type1}, {"b", type2}};
222*c8dee2aaSAndroid Build Coastguard Worker                 SkDEBUGCODE(mgr.setExpectedUniforms(SkSpan(expectations), /*isSubstruct=*/false);)
223*c8dee2aaSAndroid Build Coastguard Worker                 mgr.write(expectations[0], kFloats);
224*c8dee2aaSAndroid Build Coastguard Worker                 mgr.write(expectations[1], kFloats);
225*c8dee2aaSAndroid Build Coastguard Worker                 SkDEBUGCODE(mgr.doneWithExpectedUniforms();)
226*c8dee2aaSAndroid Build Coastguard Worker 
227*c8dee2aaSAndroid Build Coastguard Worker                 // The expected packing varies depending on the bit-widths of each element.
228*c8dee2aaSAndroid Build Coastguard Worker                 const size_t elementSize1 = element_size(layout, type1);
229*c8dee2aaSAndroid Build Coastguard Worker                 const size_t elementSize2 = element_size(layout, type2);
230*c8dee2aaSAndroid Build Coastguard Worker                 if (elementSize1 == elementSize2) {
231*c8dee2aaSAndroid Build Coastguard Worker                     // Elements in the array correspond to the element size (either 16 or 32 bits).
232*c8dee2aaSAndroid Build Coastguard Worker                     // The expected uniform layout is listed as strings below.
233*c8dee2aaSAndroid Build Coastguard Worker                     // A/B: uniform values.
234*c8dee2aaSAndroid Build Coastguard Worker                     // a/b: padding as part of the uniform type (vec3 takes 4 slots)
235*c8dee2aaSAndroid Build Coastguard Worker                     // _  : padding between uniforms for alignment
236*c8dee2aaSAndroid Build Coastguard Worker                     static constexpr const char* kExpectedLayout[2][5][5] = {
237*c8dee2aaSAndroid Build Coastguard Worker                         // Metal (vec3 consumes vec4 size)
238*c8dee2aaSAndroid Build Coastguard Worker                         {{ "", "",         "",         "",         ""         },
239*c8dee2aaSAndroid Build Coastguard Worker                          { "", "AB",       "A_BB",     "A___BBBb", "A___BBBB" },
240*c8dee2aaSAndroid Build Coastguard Worker                          { "", "AAB_",     "AABB",     "AA__BBBb", "AA__BBBB" },
241*c8dee2aaSAndroid Build Coastguard Worker                          { "", "AAAaB___", "AAAaBB__", "AAAaBBBb", "AAAaBBBB" },
242*c8dee2aaSAndroid Build Coastguard Worker                          { "", "AAAAB___", "AAAABB__", "AAAABBBb", "AAAABBBB" }},
243*c8dee2aaSAndroid Build Coastguard Worker                         // std140 and std430 (vec3 aligns to vec4, but consumes only 3 elements)
244*c8dee2aaSAndroid Build Coastguard Worker                         {{ "", "",         "",         "",         ""         },
245*c8dee2aaSAndroid Build Coastguard Worker                          { "", "AB",       "A_BB",     "A___BBBb", "A___BBBB" },
246*c8dee2aaSAndroid Build Coastguard Worker                          { "", "AAB_",     "AABB",     "AA__BBBb", "AA__BBBB" },
247*c8dee2aaSAndroid Build Coastguard Worker                          { "", "AAAB",     "AAA_BB__", "AAA_BBBb", "AAA_BBBB" },
248*c8dee2aaSAndroid Build Coastguard Worker                          { "", "AAAAB___", "AAAABB__", "AAAABBBb", "AAAABBBB" }},
249*c8dee2aaSAndroid Build Coastguard Worker                     };
250*c8dee2aaSAndroid Build Coastguard Worker                     int layoutIdx = static_cast<int>(layout != Layout::kMetal);
251*c8dee2aaSAndroid Build Coastguard Worker                     const size_t size = strlen(kExpectedLayout[layoutIdx][vecLength1][vecLength2]) *
252*c8dee2aaSAndroid Build Coastguard Worker                                         elementSize1;
253*c8dee2aaSAndroid Build Coastguard Worker                     SkSpan<const char> uniformData = mgr.finish();
254*c8dee2aaSAndroid Build Coastguard Worker                     REPORTER_ASSERT(r, uniformData.size() == size,
255*c8dee2aaSAndroid Build Coastguard Worker                                     "Layout: %s - Types: %s, %s padding test failed",
256*c8dee2aaSAndroid Build Coastguard Worker                                     LayoutString(layout),
257*c8dee2aaSAndroid Build Coastguard Worker                                     SkSLTypeString(type1), SkSLTypeString(type2));
258*c8dee2aaSAndroid Build Coastguard Worker                 } else if (elementSize1 == 2 && elementSize2 == 4) {
259*c8dee2aaSAndroid Build Coastguard Worker                     // Elements in the array below correspond to 16 bits apiece.
260*c8dee2aaSAndroid Build Coastguard Worker                     // The expected uniform layout is listed as strings below.
261*c8dee2aaSAndroid Build Coastguard Worker                     // A/B: uniform values.
262*c8dee2aaSAndroid Build Coastguard Worker                     // a/b: padding as part of the uniform type (vec3 takes 4 slots)
263*c8dee2aaSAndroid Build Coastguard Worker                     // _  : padding between uniforms for alignment
264*c8dee2aaSAndroid Build Coastguard Worker                     static constexpr const char* kExpectedLayout[5][5] = {
265*c8dee2aaSAndroid Build Coastguard Worker                         { "", "",         "",         "",                 ""         },
266*c8dee2aaSAndroid Build Coastguard Worker                         { "", "A_BB",     "A___BBBB", "A_______BBBBBBbb", "A_______BBBBBBBB" },
267*c8dee2aaSAndroid Build Coastguard Worker                         { "", "AABB",     "AA__BBBB", "AA______BBBBBBbb", "AA______BBBBBBBB" },
268*c8dee2aaSAndroid Build Coastguard Worker                         { "", "AAAaBB__", "AAAaBBBB", "AAAa____BBBBBBbb", "AAAa____BBBBBBBB" },
269*c8dee2aaSAndroid Build Coastguard Worker                         { "", "AAAABB__", "AAAABBBB", "AAAA____BBBBBBbb", "AAAA____BBBBBBBB" },
270*c8dee2aaSAndroid Build Coastguard Worker                     };
271*c8dee2aaSAndroid Build Coastguard Worker                     const size_t size = strlen(kExpectedLayout[vecLength1][vecLength2]) * 2;
272*c8dee2aaSAndroid Build Coastguard Worker                     SkSpan<const char> uniformData = mgr.finish();
273*c8dee2aaSAndroid Build Coastguard Worker                     REPORTER_ASSERT(r, uniformData.size() == size,
274*c8dee2aaSAndroid Build Coastguard Worker                                     "Layout: %s - Types: %s, %s padding test failed",
275*c8dee2aaSAndroid Build Coastguard Worker                                     LayoutString(layout),
276*c8dee2aaSAndroid Build Coastguard Worker                                     SkSLTypeString(type1), SkSLTypeString(type2));
277*c8dee2aaSAndroid Build Coastguard Worker                 } else if (elementSize1 == 4 && elementSize2 == 2) {
278*c8dee2aaSAndroid Build Coastguard Worker                     // Elements in the array below correspond to 16 bits apiece.
279*c8dee2aaSAndroid Build Coastguard Worker                     // The expected uniform layout is listed as strings below.
280*c8dee2aaSAndroid Build Coastguard Worker                     // A/B: uniform values.
281*c8dee2aaSAndroid Build Coastguard Worker                     // a/b: padding as part of the uniform type (vec3 takes 4 slots)
282*c8dee2aaSAndroid Build Coastguard Worker                     // _  : padding between uniforms for alignment
283*c8dee2aaSAndroid Build Coastguard Worker                     static constexpr const char* kExpectedLayout[5][5] = {
284*c8dee2aaSAndroid Build Coastguard Worker                         { "", "", "", "", "" },
285*c8dee2aaSAndroid Build Coastguard Worker                         { "", "AAB_",     "AABB",     "AA__BBBb", "AA__BBBB" },
286*c8dee2aaSAndroid Build Coastguard Worker                         { "", "AAAAB___", "AAAABB__", "AAAABBBb", "AAAABBBB" },
287*c8dee2aaSAndroid Build Coastguard Worker                         { "",
288*c8dee2aaSAndroid Build Coastguard Worker                           "AAAAAAaaB_______",
289*c8dee2aaSAndroid Build Coastguard Worker                           "AAAAAAaaBB______",
290*c8dee2aaSAndroid Build Coastguard Worker                           "AAAAAAaaBBBb____",
291*c8dee2aaSAndroid Build Coastguard Worker                           "AAAAAAaaBBBB____" },
292*c8dee2aaSAndroid Build Coastguard Worker                         { "",
293*c8dee2aaSAndroid Build Coastguard Worker                           "AAAAAAAAB_______",
294*c8dee2aaSAndroid Build Coastguard Worker                           "AAAAAAAABB______",
295*c8dee2aaSAndroid Build Coastguard Worker                           "AAAAAAAABBBb____",
296*c8dee2aaSAndroid Build Coastguard Worker                           "AAAAAAAABBBB____" },
297*c8dee2aaSAndroid Build Coastguard Worker                     };
298*c8dee2aaSAndroid Build Coastguard Worker                     const size_t size = strlen(kExpectedLayout[vecLength1][vecLength2]) * 2;
299*c8dee2aaSAndroid Build Coastguard Worker                     SkSpan<const char> uniformData = mgr.finish();
300*c8dee2aaSAndroid Build Coastguard Worker                     REPORTER_ASSERT(r, uniformData.size() == size,
301*c8dee2aaSAndroid Build Coastguard Worker                                     "Layout: %s - Types: %s, %s padding test failed",
302*c8dee2aaSAndroid Build Coastguard Worker                                     LayoutString(layout),
303*c8dee2aaSAndroid Build Coastguard Worker                                     SkSLTypeString(type1), SkSLTypeString(type2));
304*c8dee2aaSAndroid Build Coastguard Worker                 } else {
305*c8dee2aaSAndroid Build Coastguard Worker                     ERRORF(r, "Unexpected element sizes: %zu %zu", elementSize1, elementSize2);
306*c8dee2aaSAndroid Build Coastguard Worker                 }
307*c8dee2aaSAndroid Build Coastguard Worker                 mgr.reset();
308*c8dee2aaSAndroid Build Coastguard Worker             }
309*c8dee2aaSAndroid Build Coastguard Worker         }
310*c8dee2aaSAndroid Build Coastguard Worker     }
311*c8dee2aaSAndroid Build Coastguard Worker }
312*c8dee2aaSAndroid Build Coastguard Worker 
DEF_GRAPHITE_TEST(UniformManagerCheckPaddingVectorMatrix,r,CtsEnforcement::kApiLevel_V)313*c8dee2aaSAndroid Build Coastguard Worker DEF_GRAPHITE_TEST(UniformManagerCheckPaddingVectorMatrix, r, CtsEnforcement::kApiLevel_V) {
314*c8dee2aaSAndroid Build Coastguard Worker     // Verify that the uniform manager properly adds padding between vectors and matrices.
315*c8dee2aaSAndroid Build Coastguard Worker     for (Layout layout : kLayouts) {
316*c8dee2aaSAndroid Build Coastguard Worker         UniformManager mgr(layout);
317*c8dee2aaSAndroid Build Coastguard Worker 
318*c8dee2aaSAndroid Build Coastguard Worker         for (SkSLType type1 : kTypes) {
319*c8dee2aaSAndroid Build Coastguard Worker             const int vecLength1 = SkSLTypeVecLength(type1);
320*c8dee2aaSAndroid Build Coastguard Worker             if (vecLength1 < 1) {
321*c8dee2aaSAndroid Build Coastguard Worker                 continue;
322*c8dee2aaSAndroid Build Coastguard Worker             }
323*c8dee2aaSAndroid Build Coastguard Worker 
324*c8dee2aaSAndroid Build Coastguard Worker             for (SkSLType type2 : kTypes) {
325*c8dee2aaSAndroid Build Coastguard Worker                 const int matSize2 = SkSLTypeMatrixSize(type2);
326*c8dee2aaSAndroid Build Coastguard Worker                 if (matSize2 < 2) {
327*c8dee2aaSAndroid Build Coastguard Worker                     continue;
328*c8dee2aaSAndroid Build Coastguard Worker                 }
329*c8dee2aaSAndroid Build Coastguard Worker 
330*c8dee2aaSAndroid Build Coastguard Worker                 // Write the scalar/vector and matrix uniforms.
331*c8dee2aaSAndroid Build Coastguard Worker                 const Uniform expectations[] = {{"a", type1}, {"b", type2}};
332*c8dee2aaSAndroid Build Coastguard Worker                 SkDEBUGCODE(mgr.setExpectedUniforms(SkSpan(expectations), /*isSubstruct=*/false);)
333*c8dee2aaSAndroid Build Coastguard Worker                 mgr.write(expectations[0], kFloats);
334*c8dee2aaSAndroid Build Coastguard Worker                 mgr.write(expectations[1], kFloats);
335*c8dee2aaSAndroid Build Coastguard Worker                 SkDEBUGCODE(mgr.doneWithExpectedUniforms();)
336*c8dee2aaSAndroid Build Coastguard Worker 
337*c8dee2aaSAndroid Build Coastguard Worker                 // The expected packing varies depending on the bit-widths of each element.
338*c8dee2aaSAndroid Build Coastguard Worker                 const size_t elementSize1 = element_size(layout, type1);
339*c8dee2aaSAndroid Build Coastguard Worker                 const size_t elementSize2 = element_size(layout, type2);
340*c8dee2aaSAndroid Build Coastguard Worker                 if (elementSize1 == elementSize2) {
341*c8dee2aaSAndroid Build Coastguard Worker                     // Elements in the array correspond to the element size (32 bits).
342*c8dee2aaSAndroid Build Coastguard Worker                     // The expected uniform layout is listed as strings below.
343*c8dee2aaSAndroid Build Coastguard Worker                     // A/B: uniform values.
344*c8dee2aaSAndroid Build Coastguard Worker                     // a/b: padding as part of the uniform type (vec3 takes 4 slots)
345*c8dee2aaSAndroid Build Coastguard Worker                     // _  : padding between uniforms for alignment
346*c8dee2aaSAndroid Build Coastguard Worker                     static constexpr const char* kExpectedLayout[2][5][5] = {
347*c8dee2aaSAndroid Build Coastguard Worker                         // std140 layout
348*c8dee2aaSAndroid Build Coastguard Worker                         {
349*c8dee2aaSAndroid Build Coastguard Worker                             { "", "", "",             "",                 "" },
350*c8dee2aaSAndroid Build Coastguard Worker                             { "", "", "A___BBbbBBbb", "A___BBBbBBBbBBBb", "A___BBBBBBBBBBBBBBBB" },
351*c8dee2aaSAndroid Build Coastguard Worker                             { "", "", "AA__BBbbBBbb", "AA__BBBbBBBbBBBb", "AA__BBBBBBBBBBBBBBBB" },
352*c8dee2aaSAndroid Build Coastguard Worker                             { "", "", "AAAaBBbbBBbb", "AAAaBBBbBBBbBBBb", "AAAaBBBBBBBBBBBBBBBB" },
353*c8dee2aaSAndroid Build Coastguard Worker                             { "", "", "AAAABBbbBBbb", "AAAABBBbBBBbBBBb", "AAAABBBBBBBBBBBBBBBB" },
354*c8dee2aaSAndroid Build Coastguard Worker                         },
355*c8dee2aaSAndroid Build Coastguard Worker                         // All other layouts
356*c8dee2aaSAndroid Build Coastguard Worker                         {
357*c8dee2aaSAndroid Build Coastguard Worker                             { "", "", "",         "",                 "" },
358*c8dee2aaSAndroid Build Coastguard Worker                             { "", "", "A_BBBB",   "A___BBBbBBBbBBBb", "A___BBBBBBBBBBBBBBBB" },
359*c8dee2aaSAndroid Build Coastguard Worker                             { "", "", "AABBBB",   "AA__BBBbBBBbBBBb", "AA__BBBBBBBBBBBBBBBB" },
360*c8dee2aaSAndroid Build Coastguard Worker                             { "", "", "AAAaBBBB", "AAAaBBBbBBBbBBBb", "AAAaBBBBBBBBBBBBBBBB" },
361*c8dee2aaSAndroid Build Coastguard Worker                             { "", "", "AAAABBBB", "AAAABBBbBBBbBBBb", "AAAABBBBBBBBBBBBBBBB" },
362*c8dee2aaSAndroid Build Coastguard Worker                         },
363*c8dee2aaSAndroid Build Coastguard Worker                     };
364*c8dee2aaSAndroid Build Coastguard Worker                     int layoutIdx = static_cast<int>(layout != Layout::kStd140);
365*c8dee2aaSAndroid Build Coastguard Worker                     const size_t size = strlen(kExpectedLayout[layoutIdx][vecLength1][matSize2]) *
366*c8dee2aaSAndroid Build Coastguard Worker                                         elementSize1;
367*c8dee2aaSAndroid Build Coastguard Worker                     SkSpan<const char> uniformData = mgr.finish();
368*c8dee2aaSAndroid Build Coastguard Worker                     REPORTER_ASSERT(r, uniformData.size() == size,
369*c8dee2aaSAndroid Build Coastguard Worker                                     "Layout: %s - Types: %s, %s vector-matrix padding test failed",
370*c8dee2aaSAndroid Build Coastguard Worker                                     LayoutString(layout),
371*c8dee2aaSAndroid Build Coastguard Worker                                     SkSLTypeString(type1), SkSLTypeString(type2));
372*c8dee2aaSAndroid Build Coastguard Worker                 } else if (elementSize1 == 2 && elementSize2 == 4) {
373*c8dee2aaSAndroid Build Coastguard Worker                     // Elements in the array below correspond to 16 bits apiece.
374*c8dee2aaSAndroid Build Coastguard Worker                     // The expected uniform layout is listed as strings below.
375*c8dee2aaSAndroid Build Coastguard Worker                     // A/B: uniform values.
376*c8dee2aaSAndroid Build Coastguard Worker                     // a/b: padding as part of the uniform type (vec3 takes 4 slots)
377*c8dee2aaSAndroid Build Coastguard Worker                     // _  : padding between uniforms for alignment
378*c8dee2aaSAndroid Build Coastguard Worker                     static constexpr const char* kExpectedLayout[5][5] = {
379*c8dee2aaSAndroid Build Coastguard Worker                             {"", "", "", "", ""},
380*c8dee2aaSAndroid Build Coastguard Worker                             {"", "",
381*c8dee2aaSAndroid Build Coastguard Worker                              "A___BBBBBBBB",
382*c8dee2aaSAndroid Build Coastguard Worker                              "A_______BBBBBBbbBBBBBBbbBBBBBBbb",
383*c8dee2aaSAndroid Build Coastguard Worker                              "A_______BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"},
384*c8dee2aaSAndroid Build Coastguard Worker                             {"", "",
385*c8dee2aaSAndroid Build Coastguard Worker                              "AA__BBBBBBBB",
386*c8dee2aaSAndroid Build Coastguard Worker                              "AA______BBBBBBbbBBBBBBbbBBBBBBbb",
387*c8dee2aaSAndroid Build Coastguard Worker                              "AA______BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"},
388*c8dee2aaSAndroid Build Coastguard Worker                             {"", "",
389*c8dee2aaSAndroid Build Coastguard Worker                              "AAAaBBBBBBBB",
390*c8dee2aaSAndroid Build Coastguard Worker                              "AAAa____BBBBBBbbBBBBBBbbBBBBBBbb",
391*c8dee2aaSAndroid Build Coastguard Worker                              "AAAa____BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"},
392*c8dee2aaSAndroid Build Coastguard Worker                             {"", "",
393*c8dee2aaSAndroid Build Coastguard Worker                              "AAAABBBBBBBB",
394*c8dee2aaSAndroid Build Coastguard Worker                              "AAAA____BBBBBBbbBBBBBBbbBBBBBBbb",
395*c8dee2aaSAndroid Build Coastguard Worker                              "AAAA____BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"},
396*c8dee2aaSAndroid Build Coastguard Worker                     };
397*c8dee2aaSAndroid Build Coastguard Worker                     const size_t size = strlen(kExpectedLayout[vecLength1][matSize2]) * 2;
398*c8dee2aaSAndroid Build Coastguard Worker                     SkSpan<const char> uniformData = mgr.finish();
399*c8dee2aaSAndroid Build Coastguard Worker                     REPORTER_ASSERT(r, uniformData.size() == size,
400*c8dee2aaSAndroid Build Coastguard Worker                                     "Layout: %s - Types: %s, %s vector-matrix padding test failed",
401*c8dee2aaSAndroid Build Coastguard Worker                                     LayoutString(layout),
402*c8dee2aaSAndroid Build Coastguard Worker                                     SkSLTypeString(type1), SkSLTypeString(type2));
403*c8dee2aaSAndroid Build Coastguard Worker                 } else if (elementSize1 == 4 && elementSize2 == 2) {
404*c8dee2aaSAndroid Build Coastguard Worker                     // Elements in the array below correspond to 16 bits apiece.
405*c8dee2aaSAndroid Build Coastguard Worker                     // The expected uniform layout is listed as strings below.
406*c8dee2aaSAndroid Build Coastguard Worker                     // A/B: uniform values.
407*c8dee2aaSAndroid Build Coastguard Worker                     // a/b: padding as part of the uniform type (vec3 takes 4 slots)
408*c8dee2aaSAndroid Build Coastguard Worker                     // _  : padding between uniforms for alignment
409*c8dee2aaSAndroid Build Coastguard Worker                     static constexpr const char* kExpectedLayout[5][5] = {
410*c8dee2aaSAndroid Build Coastguard Worker                             {"", "", "", "", ""},
411*c8dee2aaSAndroid Build Coastguard Worker                             {"", "", "AABBBB",   "AA__BBBbBBBbBBBb", "AA__BBBBBBBBBBBBBBBB"},
412*c8dee2aaSAndroid Build Coastguard Worker                             {"", "", "AAAABBBB", "AAAABBBbBBBbBBBb", "AAAABBBBBBBBBBBBBBBB"},
413*c8dee2aaSAndroid Build Coastguard Worker                             {"", "",
414*c8dee2aaSAndroid Build Coastguard Worker                              "AAAAAAaaBBBB____",
415*c8dee2aaSAndroid Build Coastguard Worker                              "AAAAAAaaBBBbBBBbBBBb____",
416*c8dee2aaSAndroid Build Coastguard Worker                              "AAAAAAaaBBBBBBBBBBBBBBBB"},
417*c8dee2aaSAndroid Build Coastguard Worker                             {"", "",
418*c8dee2aaSAndroid Build Coastguard Worker                              "AAAAAAAABBBB____",
419*c8dee2aaSAndroid Build Coastguard Worker                              "AAAAAAAABBBbBBBbBBBb____",
420*c8dee2aaSAndroid Build Coastguard Worker                              "AAAAAAAABBBBBBBBBBBBBBBB"},
421*c8dee2aaSAndroid Build Coastguard Worker                     };
422*c8dee2aaSAndroid Build Coastguard Worker                     const size_t size = strlen(kExpectedLayout[vecLength1][matSize2]) * 2;
423*c8dee2aaSAndroid Build Coastguard Worker                     SkSpan<const char> uniformData = mgr.finish();
424*c8dee2aaSAndroid Build Coastguard Worker                     REPORTER_ASSERT(r, uniformData.size() == size,
425*c8dee2aaSAndroid Build Coastguard Worker                                     "Layout: %s - Types: %s, %s vector-matrix padding test failed",
426*c8dee2aaSAndroid Build Coastguard Worker                                     LayoutString(layout),
427*c8dee2aaSAndroid Build Coastguard Worker                                     SkSLTypeString(type1), SkSLTypeString(type2));
428*c8dee2aaSAndroid Build Coastguard Worker                 }
429*c8dee2aaSAndroid Build Coastguard Worker                 mgr.reset();
430*c8dee2aaSAndroid Build Coastguard Worker             }
431*c8dee2aaSAndroid Build Coastguard Worker         }
432*c8dee2aaSAndroid Build Coastguard Worker     }
433*c8dee2aaSAndroid Build Coastguard Worker }
434*c8dee2aaSAndroid Build Coastguard Worker 
DEF_GRAPHITE_TEST(UniformManagerCheckPaddingMatrixVector,r,CtsEnforcement::kApiLevel_V)435*c8dee2aaSAndroid Build Coastguard Worker DEF_GRAPHITE_TEST(UniformManagerCheckPaddingMatrixVector, r, CtsEnforcement::kApiLevel_V) {
436*c8dee2aaSAndroid Build Coastguard Worker     // Verify that the uniform manager properly adds padding between matrices and vectors.
437*c8dee2aaSAndroid Build Coastguard Worker     for (Layout layout : kLayouts) {
438*c8dee2aaSAndroid Build Coastguard Worker         UniformManager mgr(layout);
439*c8dee2aaSAndroid Build Coastguard Worker 
440*c8dee2aaSAndroid Build Coastguard Worker         for (SkSLType type1 : kTypes) {
441*c8dee2aaSAndroid Build Coastguard Worker             const int matSize1 = SkSLTypeMatrixSize(type1);
442*c8dee2aaSAndroid Build Coastguard Worker             if (matSize1 < 2) {
443*c8dee2aaSAndroid Build Coastguard Worker                 continue;
444*c8dee2aaSAndroid Build Coastguard Worker             }
445*c8dee2aaSAndroid Build Coastguard Worker 
446*c8dee2aaSAndroid Build Coastguard Worker             for (SkSLType type2 : kTypes) {
447*c8dee2aaSAndroid Build Coastguard Worker                 const int vecLength2 = SkSLTypeVecLength(type2);
448*c8dee2aaSAndroid Build Coastguard Worker                 if (vecLength2 < 1) {
449*c8dee2aaSAndroid Build Coastguard Worker                     continue;
450*c8dee2aaSAndroid Build Coastguard Worker                 }
451*c8dee2aaSAndroid Build Coastguard Worker 
452*c8dee2aaSAndroid Build Coastguard Worker                 // Write the scalar/vector and matrix uniforms.
453*c8dee2aaSAndroid Build Coastguard Worker                 const Uniform expectations[] = {{"a", type1}, {"b", type2}};
454*c8dee2aaSAndroid Build Coastguard Worker                 SkDEBUGCODE(mgr.setExpectedUniforms(SkSpan(expectations), /*isSubstruct=*/false);)
455*c8dee2aaSAndroid Build Coastguard Worker                 mgr.write(expectations[0], kFloats);
456*c8dee2aaSAndroid Build Coastguard Worker                 mgr.write(expectations[1], kFloats);
457*c8dee2aaSAndroid Build Coastguard Worker                 SkDEBUGCODE(mgr.doneWithExpectedUniforms();)
458*c8dee2aaSAndroid Build Coastguard Worker 
459*c8dee2aaSAndroid Build Coastguard Worker                 // The expected packing varies depending on the bit-widths of each element.
460*c8dee2aaSAndroid Build Coastguard Worker                 const size_t elementSize1 = element_size(layout, type1);
461*c8dee2aaSAndroid Build Coastguard Worker                 const size_t elementSize2 = element_size(layout, type2);
462*c8dee2aaSAndroid Build Coastguard Worker                 if (elementSize1 == elementSize2) {
463*c8dee2aaSAndroid Build Coastguard Worker                     // Elements in the array correspond to the element size (32 bits).
464*c8dee2aaSAndroid Build Coastguard Worker                     // The expected uniform layout is listed as strings below.
465*c8dee2aaSAndroid Build Coastguard Worker                     // A/B: uniform values.
466*c8dee2aaSAndroid Build Coastguard Worker                     // a/b: padding as part of the uniform type (vec3 takes 4 slots)
467*c8dee2aaSAndroid Build Coastguard Worker                     // _  : padding between uniforms for alignment
468*c8dee2aaSAndroid Build Coastguard Worker                     static constexpr const char* kExpectedLayout[2][5][5] = {
469*c8dee2aaSAndroid Build Coastguard Worker                         // std140 layout
470*c8dee2aaSAndroid Build Coastguard Worker                         {
471*c8dee2aaSAndroid Build Coastguard Worker                             { "", "", "", "", "" },
472*c8dee2aaSAndroid Build Coastguard Worker                             { "", "", "", "", "" },
473*c8dee2aaSAndroid Build Coastguard Worker                             { "", "AAaaAAaaB___", "AAaaAAaaBB__", "AAaaAAaaBBBb", "AAaaAAaaBBBB" },
474*c8dee2aaSAndroid Build Coastguard Worker                             { "",
475*c8dee2aaSAndroid Build Coastguard Worker                               "AAAaAAAaAAAaB___",
476*c8dee2aaSAndroid Build Coastguard Worker                               "AAAaAAAaAAAaBB__",
477*c8dee2aaSAndroid Build Coastguard Worker                               "AAAaAAAaAAAaBBBb",
478*c8dee2aaSAndroid Build Coastguard Worker                               "AAAaAAAaAAAaBBBB" },
479*c8dee2aaSAndroid Build Coastguard Worker                             { "",
480*c8dee2aaSAndroid Build Coastguard Worker                               "AAAAAAAAAAAAAAAAB___",
481*c8dee2aaSAndroid Build Coastguard Worker                               "AAAAAAAAAAAAAAAABB__",
482*c8dee2aaSAndroid Build Coastguard Worker                               "AAAAAAAAAAAAAAAABBBb",
483*c8dee2aaSAndroid Build Coastguard Worker                               "AAAAAAAAAAAAAAAABBBB" },
484*c8dee2aaSAndroid Build Coastguard Worker                         },
485*c8dee2aaSAndroid Build Coastguard Worker                         // All other layouts
486*c8dee2aaSAndroid Build Coastguard Worker                         {
487*c8dee2aaSAndroid Build Coastguard Worker                             { "", "", "", "", "" },
488*c8dee2aaSAndroid Build Coastguard Worker                             { "", "", "", "", "" },
489*c8dee2aaSAndroid Build Coastguard Worker                             { "", "AAAAB_", "AAAABB", "AAAABBBb", "AAAABBBB" },
490*c8dee2aaSAndroid Build Coastguard Worker                             { "",
491*c8dee2aaSAndroid Build Coastguard Worker                               "AAAaAAAaAAAaB___",
492*c8dee2aaSAndroid Build Coastguard Worker                               "AAAaAAAaAAAaBB__",
493*c8dee2aaSAndroid Build Coastguard Worker                               "AAAaAAAaAAAaBBBb",
494*c8dee2aaSAndroid Build Coastguard Worker                               "AAAaAAAaAAAaBBBB" },
495*c8dee2aaSAndroid Build Coastguard Worker                             { "",
496*c8dee2aaSAndroid Build Coastguard Worker                               "AAAAAAAAAAAAAAAAB___",
497*c8dee2aaSAndroid Build Coastguard Worker                               "AAAAAAAAAAAAAAAABB__",
498*c8dee2aaSAndroid Build Coastguard Worker                               "AAAAAAAAAAAAAAAABBBb",
499*c8dee2aaSAndroid Build Coastguard Worker                               "AAAAAAAAAAAAAAAABBBB" },
500*c8dee2aaSAndroid Build Coastguard Worker                         },
501*c8dee2aaSAndroid Build Coastguard Worker                     };
502*c8dee2aaSAndroid Build Coastguard Worker                     int layoutIdx = static_cast<int>(layout != Layout::kStd140);
503*c8dee2aaSAndroid Build Coastguard Worker                     const size_t size = strlen(kExpectedLayout[layoutIdx][matSize1][vecLength2]) *
504*c8dee2aaSAndroid Build Coastguard Worker                                         elementSize1;
505*c8dee2aaSAndroid Build Coastguard Worker                     SkSpan<const char> uniformData = mgr.finish();
506*c8dee2aaSAndroid Build Coastguard Worker                     REPORTER_ASSERT(r, uniformData.size() == size,
507*c8dee2aaSAndroid Build Coastguard Worker                                     "Layout: %s - Types: %s, %s matrix-vector padding test failed",
508*c8dee2aaSAndroid Build Coastguard Worker                                     LayoutString(layout),
509*c8dee2aaSAndroid Build Coastguard Worker                                     SkSLTypeString(type1), SkSLTypeString(type2));
510*c8dee2aaSAndroid Build Coastguard Worker                 } else if (elementSize1 == 2 && elementSize2 == 4) {
511*c8dee2aaSAndroid Build Coastguard Worker                     // Elements in the array below correspond to 16 bits apiece.
512*c8dee2aaSAndroid Build Coastguard Worker                     // The expected uniform layout is listed as strings below.
513*c8dee2aaSAndroid Build Coastguard Worker                     // A/B: uniform values.
514*c8dee2aaSAndroid Build Coastguard Worker                     // a/b: padding as part of the uniform type (vec3 takes 4 slots)
515*c8dee2aaSAndroid Build Coastguard Worker                     // _  : padding between uniforms for alignment
516*c8dee2aaSAndroid Build Coastguard Worker                     static constexpr const char* kExpectedLayout[5][5] = {
517*c8dee2aaSAndroid Build Coastguard Worker                         { "", "", "", "", "" },
518*c8dee2aaSAndroid Build Coastguard Worker                         { "", "", "", "", "" },
519*c8dee2aaSAndroid Build Coastguard Worker                         { "", "AAAABB", "AAAABBBB", "AAAA____BBBBBBbb", "AAAA____BBBBBBBB" },
520*c8dee2aaSAndroid Build Coastguard Worker                         { "",
521*c8dee2aaSAndroid Build Coastguard Worker                           "AAAaAAAaAAAaBB__",
522*c8dee2aaSAndroid Build Coastguard Worker                           "AAAaAAAaAAAaBBBB",
523*c8dee2aaSAndroid Build Coastguard Worker                           "AAAaAAAaAAAa____BBBBBBbb",
524*c8dee2aaSAndroid Build Coastguard Worker                           "AAAaAAAaAAAa____BBBBBBBB" },
525*c8dee2aaSAndroid Build Coastguard Worker                         { "",
526*c8dee2aaSAndroid Build Coastguard Worker                           "AAAAAAAAAAAAAAAABB__",
527*c8dee2aaSAndroid Build Coastguard Worker                           "AAAAAAAAAAAAAAAABBBB",
528*c8dee2aaSAndroid Build Coastguard Worker                           "AAAAAAAAAAAAAAAABBBBBBbb",
529*c8dee2aaSAndroid Build Coastguard Worker                           "AAAAAAAAAAAAAAAABBBBBBBB" },
530*c8dee2aaSAndroid Build Coastguard Worker                     };
531*c8dee2aaSAndroid Build Coastguard Worker                     const size_t size = strlen(kExpectedLayout[matSize1][vecLength2]) * 2;
532*c8dee2aaSAndroid Build Coastguard Worker                     SkSpan<const char> uniformData = mgr.finish();
533*c8dee2aaSAndroid Build Coastguard Worker                     REPORTER_ASSERT(r, uniformData.size() == size,
534*c8dee2aaSAndroid Build Coastguard Worker                                     "Layout: %s - Types: %s, %s matrix-vector padding test failed",
535*c8dee2aaSAndroid Build Coastguard Worker                                     LayoutString(layout),
536*c8dee2aaSAndroid Build Coastguard Worker                                     SkSLTypeString(type1), SkSLTypeString(type2));
537*c8dee2aaSAndroid Build Coastguard Worker                 } else if (elementSize1 == 4 && elementSize2 == 2) {
538*c8dee2aaSAndroid Build Coastguard Worker                     // Elements in the array below correspond to 16 bits apiece.
539*c8dee2aaSAndroid Build Coastguard Worker                     // The expected uniform layout is listed as strings below.
540*c8dee2aaSAndroid Build Coastguard Worker                     // A/B: uniform values.
541*c8dee2aaSAndroid Build Coastguard Worker                     // a/b: padding as part of the uniform type (vec3 takes 4 slots)
542*c8dee2aaSAndroid Build Coastguard Worker                     // _  : padding between uniforms for alignment
543*c8dee2aaSAndroid Build Coastguard Worker                     static constexpr const char* kExpectedLayout[5][5] = {
544*c8dee2aaSAndroid Build Coastguard Worker                         { "", "", "", "", "" },
545*c8dee2aaSAndroid Build Coastguard Worker                         { "", "", "", "", "" },
546*c8dee2aaSAndroid Build Coastguard Worker                         { "", "AAAAAAAAB___", "AAAAAAAABB__", "AAAAAAAABBBb", "AAAAAAAABBBB" },
547*c8dee2aaSAndroid Build Coastguard Worker                         { "",
548*c8dee2aaSAndroid Build Coastguard Worker                           "AAAAAAaaAAAAAAaaAAAAAAaaB_______",
549*c8dee2aaSAndroid Build Coastguard Worker                           "AAAAAAaaAAAAAAaaAAAAAAaaBB______",
550*c8dee2aaSAndroid Build Coastguard Worker                           "AAAAAAaaAAAAAAaaAAAAAAaaBBBb____",
551*c8dee2aaSAndroid Build Coastguard Worker                           "AAAAAAaaAAAAAAaaAAAAAAaaBBBB____" },
552*c8dee2aaSAndroid Build Coastguard Worker                         { "",
553*c8dee2aaSAndroid Build Coastguard Worker                           "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB_______",
554*c8dee2aaSAndroid Build Coastguard Worker                           "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABB______",
555*c8dee2aaSAndroid Build Coastguard Worker                           "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBb____",
556*c8dee2aaSAndroid Build Coastguard Worker                           "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB____" },
557*c8dee2aaSAndroid Build Coastguard Worker                     };
558*c8dee2aaSAndroid Build Coastguard Worker                     const size_t size = strlen(kExpectedLayout[matSize1][vecLength2]) * 2;
559*c8dee2aaSAndroid Build Coastguard Worker                     SkSpan<const char> uniformData = mgr.finish();
560*c8dee2aaSAndroid Build Coastguard Worker                     REPORTER_ASSERT(r, uniformData.size() == size,
561*c8dee2aaSAndroid Build Coastguard Worker                                     "Layout: %s - Types: %s, %s matrix-vector padding test failed",
562*c8dee2aaSAndroid Build Coastguard Worker                                     LayoutString(layout),
563*c8dee2aaSAndroid Build Coastguard Worker                                     SkSLTypeString(type1), SkSLTypeString(type2));
564*c8dee2aaSAndroid Build Coastguard Worker                 }
565*c8dee2aaSAndroid Build Coastguard Worker                 mgr.reset();
566*c8dee2aaSAndroid Build Coastguard Worker             }
567*c8dee2aaSAndroid Build Coastguard Worker         }
568*c8dee2aaSAndroid Build Coastguard Worker     }
569*c8dee2aaSAndroid Build Coastguard Worker }
570*c8dee2aaSAndroid Build Coastguard Worker 
DEF_GRAPHITE_TEST(UniformManagerMetalArrayLayout,r,CtsEnforcement::kApiLevel_V)571*c8dee2aaSAndroid Build Coastguard Worker DEF_GRAPHITE_TEST(UniformManagerMetalArrayLayout, r, CtsEnforcement::kApiLevel_V) {
572*c8dee2aaSAndroid Build Coastguard Worker     UniformManager mgr(Layout::kMetal);
573*c8dee2aaSAndroid Build Coastguard Worker 
574*c8dee2aaSAndroid Build Coastguard Worker     // Tests set up a uniform block with a single half (to force alignment) and an array of 3
575*c8dee2aaSAndroid Build Coastguard Worker     // elements. Test every type that can appear in an array.
576*c8dee2aaSAndroid Build Coastguard Worker     constexpr size_t kArraySize = 3;
577*c8dee2aaSAndroid Build Coastguard Worker 
578*c8dee2aaSAndroid Build Coastguard Worker     // Buffer large enough to hold a float4x4[3] array.
579*c8dee2aaSAndroid Build Coastguard Worker     static constexpr uint8_t kBuffer[192] = {};
580*c8dee2aaSAndroid Build Coastguard Worker     static const char* kExpectedLayout[] = {
581*c8dee2aaSAndroid Build Coastguard Worker         // Each letter (A/B/a/b) corresponds to a single byte.
582*c8dee2aaSAndroid Build Coastguard Worker         // The expected uniform layout is listed as strings below.
583*c8dee2aaSAndroid Build Coastguard Worker         // A/B: uniform values.
584*c8dee2aaSAndroid Build Coastguard Worker         // a/b: padding as part of the uniform type.
585*c8dee2aaSAndroid Build Coastguard Worker         // _  : padding between uniforms for alignment.
586*c8dee2aaSAndroid Build Coastguard Worker 
587*c8dee2aaSAndroid Build Coastguard Worker         /* {half, float[3]}  */  "AA__BBBBBBBBBBBB",
588*c8dee2aaSAndroid Build Coastguard Worker         /* {half, float2[3]} */  "AA______BBBBBBBBBBBBBBBBBBBBBBBB",
589*c8dee2aaSAndroid Build Coastguard Worker         /* {half, float3[3]} */  "AA______________BBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbb",
590*c8dee2aaSAndroid Build Coastguard Worker         /* {half, float4[3]} */  "AA______________BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB",
591*c8dee2aaSAndroid Build Coastguard Worker         /* {half, half[3]}   */  "AABBBBBB",
592*c8dee2aaSAndroid Build Coastguard Worker         /* {half, half2[3]}  */  "AA__BBBBBBBBBBBB",
593*c8dee2aaSAndroid Build Coastguard Worker         /* {half, half3[3]}  */  "AA______BBBBBBbbBBBBBBbbBBBBBBbb",
594*c8dee2aaSAndroid Build Coastguard Worker         /* {half, half4[3]}  */  "AA______BBBBBBBBBBBBBBBBBBBBBBBB",
595*c8dee2aaSAndroid Build Coastguard Worker         /* {half, int[3]}    */  "AA__BBBBBBBBBBBB",
596*c8dee2aaSAndroid Build Coastguard Worker         /* {half, int2[3]}   */  "AA______BBBBBBBBBBBBBBBBBBBBBBBB",
597*c8dee2aaSAndroid Build Coastguard Worker         /* {half, int3[3]}   */  "AA______________BBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbb",
598*c8dee2aaSAndroid Build Coastguard Worker         /* {half, int4[3]}   */  "AA______________BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB",
599*c8dee2aaSAndroid Build Coastguard Worker 
600*c8dee2aaSAndroid Build Coastguard Worker         /* {half, float2x2[3] */ "AA______BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB",
601*c8dee2aaSAndroid Build Coastguard Worker         /* {half, float3x3[3] */ "AA______________"
602*c8dee2aaSAndroid Build Coastguard Worker                                  "BBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbb"
603*c8dee2aaSAndroid Build Coastguard Worker                                  "BBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbb"
604*c8dee2aaSAndroid Build Coastguard Worker                                  "BBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbb",
605*c8dee2aaSAndroid Build Coastguard Worker         /* {half, float4x4[3] */ "AA______________"
606*c8dee2aaSAndroid Build Coastguard Worker                                  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
607*c8dee2aaSAndroid Build Coastguard Worker                                  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
608*c8dee2aaSAndroid Build Coastguard Worker                                  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB",
609*c8dee2aaSAndroid Build Coastguard Worker 
610*c8dee2aaSAndroid Build Coastguard Worker         /* {half, half2x2[3] */  "AA__BBBBBBBBBBBBBBBBBBBBBBBB",
611*c8dee2aaSAndroid Build Coastguard Worker         /* {half, half3x3[3] */  "AA______"
612*c8dee2aaSAndroid Build Coastguard Worker                                  "BBBBBBbbBBBBBBbbBBBBBBbb"
613*c8dee2aaSAndroid Build Coastguard Worker                                  "BBBBBBbbBBBBBBbbBBBBBBbb"
614*c8dee2aaSAndroid Build Coastguard Worker                                  "BBBBBBbbBBBBBBbbBBBBBBbb",
615*c8dee2aaSAndroid Build Coastguard Worker         /* {half, half4x4[3] */  "AA______"
616*c8dee2aaSAndroid Build Coastguard Worker                                  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
617*c8dee2aaSAndroid Build Coastguard Worker                                  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
618*c8dee2aaSAndroid Build Coastguard Worker                                  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB",
619*c8dee2aaSAndroid Build Coastguard Worker     };
620*c8dee2aaSAndroid Build Coastguard Worker     for (size_t i = 0; i < std::size(kExpectedLayout); i++) {
621*c8dee2aaSAndroid Build Coastguard Worker         const SkSLType arrayType = kTypes[i];
622*c8dee2aaSAndroid Build Coastguard Worker         const Uniform expectations[] = {{"a", SkSLType::kHalf}, {"b", arrayType, kArraySize}};
623*c8dee2aaSAndroid Build Coastguard Worker 
624*c8dee2aaSAndroid Build Coastguard Worker         SkDEBUGCODE(mgr.setExpectedUniforms(SkSpan(expectations), /*isSubstruct=*/false);)
625*c8dee2aaSAndroid Build Coastguard Worker         mgr.write(expectations[0], kHalfs);
626*c8dee2aaSAndroid Build Coastguard Worker         mgr.write(expectations[1], kBuffer);
627*c8dee2aaSAndroid Build Coastguard Worker         SkDEBUGCODE(mgr.doneWithExpectedUniforms();)
628*c8dee2aaSAndroid Build Coastguard Worker 
629*c8dee2aaSAndroid Build Coastguard Worker         const size_t expectedSize = strlen(kExpectedLayout[i]);
630*c8dee2aaSAndroid Build Coastguard Worker         SkSpan<const char> uniformData = mgr.finish();
631*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(r, uniformData.size() == expectedSize,
632*c8dee2aaSAndroid Build Coastguard Worker                         "array test %d for type %s failed - expected size: %zu, actual size: %zu",
633*c8dee2aaSAndroid Build Coastguard Worker                         (int)i, SkSLTypeString(arrayType), expectedSize, uniformData.size());
634*c8dee2aaSAndroid Build Coastguard Worker 
635*c8dee2aaSAndroid Build Coastguard Worker         mgr.reset();
636*c8dee2aaSAndroid Build Coastguard Worker     }
637*c8dee2aaSAndroid Build Coastguard Worker }
638*c8dee2aaSAndroid Build Coastguard Worker 
DEF_GRAPHITE_TEST(UniformManagerStd430ArrayLayout,r,CtsEnforcement::kApiLevel_V)639*c8dee2aaSAndroid Build Coastguard Worker DEF_GRAPHITE_TEST(UniformManagerStd430ArrayLayout, r, CtsEnforcement::kApiLevel_V) {
640*c8dee2aaSAndroid Build Coastguard Worker     UniformManager mgr(Layout::kStd430);
641*c8dee2aaSAndroid Build Coastguard Worker 
642*c8dee2aaSAndroid Build Coastguard Worker     // Tests set up a uniform block with a single half (to force alignment) and an array of 3
643*c8dee2aaSAndroid Build Coastguard Worker     // elements. Test every type that can appear in an array.
644*c8dee2aaSAndroid Build Coastguard Worker     constexpr size_t kArraySize = 3;
645*c8dee2aaSAndroid Build Coastguard Worker 
646*c8dee2aaSAndroid Build Coastguard Worker     // Buffer large enough to hold a float4x4[3] array.
647*c8dee2aaSAndroid Build Coastguard Worker     static constexpr uint8_t kBuffer[192] = {};
648*c8dee2aaSAndroid Build Coastguard Worker     static const char* kExpectedLayout[] = {
649*c8dee2aaSAndroid Build Coastguard Worker         // Each letter (A/B/a/b) corresponds to a single byte.
650*c8dee2aaSAndroid Build Coastguard Worker         // The expected uniform layout is listed as strings below.
651*c8dee2aaSAndroid Build Coastguard Worker         // A/B: uniform values.
652*c8dee2aaSAndroid Build Coastguard Worker         // a/b: padding as part of the uniform type.
653*c8dee2aaSAndroid Build Coastguard Worker         // _  : padding between uniforms for alignment.
654*c8dee2aaSAndroid Build Coastguard Worker 
655*c8dee2aaSAndroid Build Coastguard Worker         /* {half, float[3]}  */  "AA__BBBBBBBBBBBB",
656*c8dee2aaSAndroid Build Coastguard Worker         /* {half, float2[3]} */  "AA______BBBBBBBBBBBBBBBBBBBBBBBB",
657*c8dee2aaSAndroid Build Coastguard Worker         /* {half, float3[3]} */  "AA______________BBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbb",
658*c8dee2aaSAndroid Build Coastguard Worker         /* {half, float4[3]} */  "AA______________BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB",
659*c8dee2aaSAndroid Build Coastguard Worker         /* {half, half[3]}   */  "AA__BBBBBBBBBBBB",
660*c8dee2aaSAndroid Build Coastguard Worker         /* {half, half2[3]}  */  "AA______BBBBBBBBBBBBBBBBBBBBBBBB",
661*c8dee2aaSAndroid Build Coastguard Worker         /* {half, half3[3]}  */  "AA______________BBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbb",
662*c8dee2aaSAndroid Build Coastguard Worker         /* {half, half4[3]}  */  "AA______________BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB",
663*c8dee2aaSAndroid Build Coastguard Worker         /* {half, int[3]}    */  "AA__BBBBBBBBBBBB",
664*c8dee2aaSAndroid Build Coastguard Worker         /* {half, int2[3]}   */  "AA______BBBBBBBBBBBBBBBBBBBBBBBB",
665*c8dee2aaSAndroid Build Coastguard Worker         /* {half, int3[3]}   */  "AA______________BBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbb",
666*c8dee2aaSAndroid Build Coastguard Worker         /* {half, int4[3]}   */  "AA______________BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB",
667*c8dee2aaSAndroid Build Coastguard Worker 
668*c8dee2aaSAndroid Build Coastguard Worker         /* {half, float2x2[3] */ "AA______BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB",
669*c8dee2aaSAndroid Build Coastguard Worker         /* {half, float3x3[3] */ "AA______________"
670*c8dee2aaSAndroid Build Coastguard Worker                                  "BBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbb"
671*c8dee2aaSAndroid Build Coastguard Worker                                  "BBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbb"
672*c8dee2aaSAndroid Build Coastguard Worker                                  "BBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbb",
673*c8dee2aaSAndroid Build Coastguard Worker         /* {half, float4x4[3] */ "AA______________"
674*c8dee2aaSAndroid Build Coastguard Worker                                  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
675*c8dee2aaSAndroid Build Coastguard Worker                                  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
676*c8dee2aaSAndroid Build Coastguard Worker                                  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB",
677*c8dee2aaSAndroid Build Coastguard Worker 
678*c8dee2aaSAndroid Build Coastguard Worker         /* {half, half2x2[3]  */ "AA______BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB",
679*c8dee2aaSAndroid Build Coastguard Worker         /* {half, half3x3[3]  */ "AA______________"
680*c8dee2aaSAndroid Build Coastguard Worker                                  "BBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbb"
681*c8dee2aaSAndroid Build Coastguard Worker                                  "BBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbb"
682*c8dee2aaSAndroid Build Coastguard Worker                                  "BBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbb",
683*c8dee2aaSAndroid Build Coastguard Worker         /* {half, half4x4[3]  */ "AA______________"
684*c8dee2aaSAndroid Build Coastguard Worker                                  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
685*c8dee2aaSAndroid Build Coastguard Worker                                  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
686*c8dee2aaSAndroid Build Coastguard Worker                                  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB",
687*c8dee2aaSAndroid Build Coastguard Worker     };
688*c8dee2aaSAndroid Build Coastguard Worker     for (size_t i = 0; i < std::size(kExpectedLayout); i++) {
689*c8dee2aaSAndroid Build Coastguard Worker         const SkSLType arrayType = kTypes[i];
690*c8dee2aaSAndroid Build Coastguard Worker         const Uniform expectations[] = {{"a", SkSLType::kHalf}, {"b", arrayType, kArraySize}};
691*c8dee2aaSAndroid Build Coastguard Worker 
692*c8dee2aaSAndroid Build Coastguard Worker         SkDEBUGCODE(mgr.setExpectedUniforms(SkSpan(expectations), /*isSubstruct=*/false);)
693*c8dee2aaSAndroid Build Coastguard Worker         mgr.write(expectations[0], kHalfs);
694*c8dee2aaSAndroid Build Coastguard Worker         mgr.write(expectations[1], kBuffer);
695*c8dee2aaSAndroid Build Coastguard Worker         SkDEBUGCODE(mgr.doneWithExpectedUniforms();)
696*c8dee2aaSAndroid Build Coastguard Worker 
697*c8dee2aaSAndroid Build Coastguard Worker         const size_t expectedSize = strlen(kExpectedLayout[i]);
698*c8dee2aaSAndroid Build Coastguard Worker         SkSpan<const char> uniformData = mgr.finish();
699*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(r, uniformData.size() == expectedSize,
700*c8dee2aaSAndroid Build Coastguard Worker                         "array test %d for type %s failed - expected size: %zu, actual size: %zu",
701*c8dee2aaSAndroid Build Coastguard Worker                         (int)i, SkSLTypeString(arrayType), expectedSize, uniformData.size());
702*c8dee2aaSAndroid Build Coastguard Worker 
703*c8dee2aaSAndroid Build Coastguard Worker         mgr.reset();
704*c8dee2aaSAndroid Build Coastguard Worker     }
705*c8dee2aaSAndroid Build Coastguard Worker }
706*c8dee2aaSAndroid Build Coastguard Worker 
DEF_GRAPHITE_TEST(UniformManagerStd140ArrayLayout,r,CtsEnforcement::kApiLevel_V)707*c8dee2aaSAndroid Build Coastguard Worker DEF_GRAPHITE_TEST(UniformManagerStd140ArrayLayout, r, CtsEnforcement::kApiLevel_V) {
708*c8dee2aaSAndroid Build Coastguard Worker     UniformManager mgr(Layout::kStd140);
709*c8dee2aaSAndroid Build Coastguard Worker 
710*c8dee2aaSAndroid Build Coastguard Worker     // Tests set up a uniform block with a single half (to force alignment) and an array of 3
711*c8dee2aaSAndroid Build Coastguard Worker     // elements. Test every type that can appear in an array.
712*c8dee2aaSAndroid Build Coastguard Worker     constexpr size_t kArraySize = 3;
713*c8dee2aaSAndroid Build Coastguard Worker 
714*c8dee2aaSAndroid Build Coastguard Worker     // Buffer large enough to hold a float4x4[3] array.
715*c8dee2aaSAndroid Build Coastguard Worker     static constexpr uint8_t kBuffer[192] = {};
716*c8dee2aaSAndroid Build Coastguard Worker     static const char* kExpectedLayout[] = {
717*c8dee2aaSAndroid Build Coastguard Worker         // Each letter (A/B/a/b) corresponds to a single byte.
718*c8dee2aaSAndroid Build Coastguard Worker         // The expected uniform layout is listed as strings below.
719*c8dee2aaSAndroid Build Coastguard Worker         // A/B: uniform values.
720*c8dee2aaSAndroid Build Coastguard Worker         // a/b: padding as part of the uniform type.
721*c8dee2aaSAndroid Build Coastguard Worker         // _  : padding between uniforms for alignment.
722*c8dee2aaSAndroid Build Coastguard Worker 
723*c8dee2aaSAndroid Build Coastguard Worker         /* {half, float[3]}  */  "AA______________BBBBbbbbbbbbbbbbBBBBbbbbbbbbbbbbBBBBbbbbbbbbbbbb",
724*c8dee2aaSAndroid Build Coastguard Worker         /* {half, float2[3]} */  "AA______________BBBBBBBBbbbbbbbbBBBBBBBBbbbbbbbbBBBBBBBBbbbbbbbb",
725*c8dee2aaSAndroid Build Coastguard Worker         /* {half, float3[3]} */  "AA______________BBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbb",
726*c8dee2aaSAndroid Build Coastguard Worker         /* {half, float4[3]} */  "AA______________BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB",
727*c8dee2aaSAndroid Build Coastguard Worker         /* {half, half[3]}   */  "AA______________BBbbbbbbbbbbbbbbBBbbbbbbbbbbbbbbBBbbbbbbbbbbbbbb",
728*c8dee2aaSAndroid Build Coastguard Worker         /* {half, half2[3]}  */  "AA______________BBBBbbbbbbbbbbbbBBBBbbbbbbbbbbbbBBBBbbbbbbbbbbbb",
729*c8dee2aaSAndroid Build Coastguard Worker         /* {half, half3[3]}  */  "AA______________BBBBBBbbbbbbbbbbBBBBBBbbbbbbbbbbBBBBBBbbbbbbbbbb",
730*c8dee2aaSAndroid Build Coastguard Worker         /* {half, half4[3]}  */  "AA______________BBBBBBBBbbbbbbbbBBBBBBBBbbbbbbbbBBBBBBBBbbbbbbbb",
731*c8dee2aaSAndroid Build Coastguard Worker         /* {half, int[3]}    */  "AA______________BBBBbbbbbbbbbbbbBBBBbbbbbbbbbbbbBBBBbbbbbbbbbbbb",
732*c8dee2aaSAndroid Build Coastguard Worker         /* {half, int2[3]}   */  "AA______________BBBBBBBBbbbbbbbbBBBBBBBBbbbbbbbbBBBBBBBBbbbbbbbb",
733*c8dee2aaSAndroid Build Coastguard Worker         /* {half, int3[3]}   */  "AA______________BBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbb",
734*c8dee2aaSAndroid Build Coastguard Worker         /* {half, int4[3]}   */  "AA______________BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB",
735*c8dee2aaSAndroid Build Coastguard Worker 
736*c8dee2aaSAndroid Build Coastguard Worker         /* {half, float2x2[3] */ "AA______________"
737*c8dee2aaSAndroid Build Coastguard Worker                                  "BBBBBBBBbbbbbbbbBBBBBBBBbbbbbbbb"
738*c8dee2aaSAndroid Build Coastguard Worker                                  "BBBBBBBBbbbbbbbbBBBBBBBBbbbbbbbb"
739*c8dee2aaSAndroid Build Coastguard Worker                                  "BBBBBBBBbbbbbbbbBBBBBBBBbbbbbbbb",
740*c8dee2aaSAndroid Build Coastguard Worker         /* {half, float3x3[3] */ "AA______________"
741*c8dee2aaSAndroid Build Coastguard Worker                                  "BBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbb"
742*c8dee2aaSAndroid Build Coastguard Worker                                  "BBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbb"
743*c8dee2aaSAndroid Build Coastguard Worker                                  "BBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbb",
744*c8dee2aaSAndroid Build Coastguard Worker         /* {half, float4x4[3] */ "AA______________"
745*c8dee2aaSAndroid Build Coastguard Worker                                  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
746*c8dee2aaSAndroid Build Coastguard Worker                                  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
747*c8dee2aaSAndroid Build Coastguard Worker                                  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB",
748*c8dee2aaSAndroid Build Coastguard Worker 
749*c8dee2aaSAndroid Build Coastguard Worker         /* {half, half2x2[3]  */ "AA______________"
750*c8dee2aaSAndroid Build Coastguard Worker                                  "BBBBBBBBbbbbbbbbBBBBBBBBbbbbbbbb"
751*c8dee2aaSAndroid Build Coastguard Worker                                  "BBBBBBBBbbbbbbbbBBBBBBBBbbbbbbbb"
752*c8dee2aaSAndroid Build Coastguard Worker                                  "BBBBBBBBbbbbbbbbBBBBBBBBbbbbbbbb",
753*c8dee2aaSAndroid Build Coastguard Worker         /* {half, half3x3[3]  */ "AA______________"
754*c8dee2aaSAndroid Build Coastguard Worker                                  "BBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbb"
755*c8dee2aaSAndroid Build Coastguard Worker                                  "BBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbb"
756*c8dee2aaSAndroid Build Coastguard Worker                                  "BBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbb",
757*c8dee2aaSAndroid Build Coastguard Worker         /* {half, half4x4[3]  */ "AA______________"
758*c8dee2aaSAndroid Build Coastguard Worker                                  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
759*c8dee2aaSAndroid Build Coastguard Worker                                  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
760*c8dee2aaSAndroid Build Coastguard Worker                                  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB",
761*c8dee2aaSAndroid Build Coastguard Worker     };
762*c8dee2aaSAndroid Build Coastguard Worker     for (size_t i = 0; i < std::size(kExpectedLayout); i++) {
763*c8dee2aaSAndroid Build Coastguard Worker         const SkSLType arrayType = kTypes[i];
764*c8dee2aaSAndroid Build Coastguard Worker         const Uniform expectations[] = {{"a", SkSLType::kHalf}, {"b", arrayType, kArraySize}};
765*c8dee2aaSAndroid Build Coastguard Worker 
766*c8dee2aaSAndroid Build Coastguard Worker         SkDEBUGCODE(mgr.setExpectedUniforms(SkSpan(expectations), /*isSubstruct=*/false);)
767*c8dee2aaSAndroid Build Coastguard Worker         mgr.write(expectations[0], kHalfs);
768*c8dee2aaSAndroid Build Coastguard Worker         mgr.write(expectations[1], kBuffer);
769*c8dee2aaSAndroid Build Coastguard Worker         SkDEBUGCODE(mgr.doneWithExpectedUniforms();)
770*c8dee2aaSAndroid Build Coastguard Worker 
771*c8dee2aaSAndroid Build Coastguard Worker         const size_t expectedSize = strlen(kExpectedLayout[i]);
772*c8dee2aaSAndroid Build Coastguard Worker         SkSpan<const char> uniformData = mgr.finish();
773*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(r, uniformData.size() == expectedSize,
774*c8dee2aaSAndroid Build Coastguard Worker                         "array test %d for type %s failed - expected size: %zu, actual size: %zu",
775*c8dee2aaSAndroid Build Coastguard Worker                         (int)i, SkSLTypeString(arrayType), expectedSize, uniformData.size());
776*c8dee2aaSAndroid Build Coastguard Worker 
777*c8dee2aaSAndroid Build Coastguard Worker         mgr.reset();
778*c8dee2aaSAndroid Build Coastguard Worker     }
779*c8dee2aaSAndroid Build Coastguard Worker }
780*c8dee2aaSAndroid Build Coastguard Worker 
781*c8dee2aaSAndroid Build Coastguard Worker // This test validates that the uniform data for matrix types get written out according to the
782*c8dee2aaSAndroid Build Coastguard Worker // layout expectations.
DEF_GRAPHITE_TEST(UniformManagerStd140MatrixLayoutContents,r,CtsEnforcement::kApiLevel_V)783*c8dee2aaSAndroid Build Coastguard Worker DEF_GRAPHITE_TEST(UniformManagerStd140MatrixLayoutContents, r, CtsEnforcement::kApiLevel_V) {
784*c8dee2aaSAndroid Build Coastguard Worker     UniformManager mgr(Layout::kStd140);
785*c8dee2aaSAndroid Build Coastguard Worker 
786*c8dee2aaSAndroid Build Coastguard Worker     // float2x2, half2x2
787*c8dee2aaSAndroid Build Coastguard Worker     for (SkSLType type : {SkSLType::kFloat2x2, SkSLType::kHalf2x2}) {
788*c8dee2aaSAndroid Build Coastguard Worker         const Uniform expectations[] = {{"m", type}};
789*c8dee2aaSAndroid Build Coastguard Worker         SkDEBUGCODE(mgr.setExpectedUniforms(SkSpan(expectations), /*isSubstruct=*/false);)
790*c8dee2aaSAndroid Build Coastguard Worker         mgr.write(expectations[0], kFloats);
791*c8dee2aaSAndroid Build Coastguard Worker         SkDEBUGCODE(mgr.doneWithExpectedUniforms();)
792*c8dee2aaSAndroid Build Coastguard Worker         SkSpan<const char> uniformData = mgr.finish();
793*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(r, uniformData.size() == 32,
794*c8dee2aaSAndroid Build Coastguard Worker                         "%s layout size expected 32, got %zu",
795*c8dee2aaSAndroid Build Coastguard Worker                         SkSLTypeString(type), uniformData.size());
796*c8dee2aaSAndroid Build Coastguard Worker 
797*c8dee2aaSAndroid Build Coastguard Worker         // The expected offsets of the 4 matrix elements.
798*c8dee2aaSAndroid Build Coastguard Worker         const int kOffsets[4] = {0, 1, 4, 5};
799*c8dee2aaSAndroid Build Coastguard Worker         const float* elements = reinterpret_cast<const float*>(uniformData.data());
800*c8dee2aaSAndroid Build Coastguard Worker         for (size_t i = 0u; i < std::size(kOffsets); ++i) {
801*c8dee2aaSAndroid Build Coastguard Worker             float expected = kFloats[i];
802*c8dee2aaSAndroid Build Coastguard Worker             float el = elements[kOffsets[i]];
803*c8dee2aaSAndroid Build Coastguard Worker             REPORTER_ASSERT(r, el == expected,
804*c8dee2aaSAndroid Build Coastguard Worker                             "Incorrect %s element %zu - expected %f, got %f",
805*c8dee2aaSAndroid Build Coastguard Worker                             SkSLTypeString(type), i, expected, el);
806*c8dee2aaSAndroid Build Coastguard Worker         }
807*c8dee2aaSAndroid Build Coastguard Worker         mgr.reset();
808*c8dee2aaSAndroid Build Coastguard Worker     }
809*c8dee2aaSAndroid Build Coastguard Worker 
810*c8dee2aaSAndroid Build Coastguard Worker     // float3x3, half3x3
811*c8dee2aaSAndroid Build Coastguard Worker     for (SkSLType type : {SkSLType::kFloat3x3, SkSLType::kHalf3x3}) {
812*c8dee2aaSAndroid Build Coastguard Worker         const Uniform expectations[] = {{"m", type}};
813*c8dee2aaSAndroid Build Coastguard Worker         SkDEBUGCODE(mgr.setExpectedUniforms(SkSpan(expectations), /*isSubstruct=*/false);)
814*c8dee2aaSAndroid Build Coastguard Worker         mgr.write(expectations[0], kFloats);
815*c8dee2aaSAndroid Build Coastguard Worker         SkDEBUGCODE(mgr.doneWithExpectedUniforms();)
816*c8dee2aaSAndroid Build Coastguard Worker         SkSpan<const char> uniformData = mgr.finish();
817*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(r, uniformData.size() == 48,
818*c8dee2aaSAndroid Build Coastguard Worker                         "%s layout size expected 48, got %zu",
819*c8dee2aaSAndroid Build Coastguard Worker                         SkSLTypeString(type), uniformData.size());
820*c8dee2aaSAndroid Build Coastguard Worker 
821*c8dee2aaSAndroid Build Coastguard Worker         // The expected offsets of the 9 matrix elements.
822*c8dee2aaSAndroid Build Coastguard Worker         const int kOffsets[9] = {0, 1, 2, 4, 5, 6, 8, 9, 10};
823*c8dee2aaSAndroid Build Coastguard Worker         const float* elements = reinterpret_cast<const float*>(uniformData.data());
824*c8dee2aaSAndroid Build Coastguard Worker         for (size_t i = 0u; i < std::size(kOffsets); ++i) {
825*c8dee2aaSAndroid Build Coastguard Worker             float expected = kFloats[i];
826*c8dee2aaSAndroid Build Coastguard Worker             float el = elements[kOffsets[i]];
827*c8dee2aaSAndroid Build Coastguard Worker             REPORTER_ASSERT(r, el == expected,
828*c8dee2aaSAndroid Build Coastguard Worker                             "Incorrect %s element %zu - expected %f, got %f",
829*c8dee2aaSAndroid Build Coastguard Worker                             SkSLTypeString(type), i, expected, el);
830*c8dee2aaSAndroid Build Coastguard Worker         }
831*c8dee2aaSAndroid Build Coastguard Worker         mgr.reset();
832*c8dee2aaSAndroid Build Coastguard Worker     }
833*c8dee2aaSAndroid Build Coastguard Worker }
834*c8dee2aaSAndroid Build Coastguard Worker 
835*c8dee2aaSAndroid Build Coastguard Worker // This test validates that the uniform data for matrix types get written out according to the
836*c8dee2aaSAndroid Build Coastguard Worker // layout expectations.
DEF_GRAPHITE_TEST(UniformManagerStd430MatrixLayoutContents,r,CtsEnforcement::kApiLevel_V)837*c8dee2aaSAndroid Build Coastguard Worker DEF_GRAPHITE_TEST(UniformManagerStd430MatrixLayoutContents, r, CtsEnforcement::kApiLevel_V) {
838*c8dee2aaSAndroid Build Coastguard Worker     UniformManager mgr(Layout::kStd430);
839*c8dee2aaSAndroid Build Coastguard Worker 
840*c8dee2aaSAndroid Build Coastguard Worker     // float2x2, half2x2
841*c8dee2aaSAndroid Build Coastguard Worker     for (SkSLType type : {SkSLType::kFloat2x2, SkSLType::kHalf2x2}) {
842*c8dee2aaSAndroid Build Coastguard Worker         const Uniform expectations[] = {{"m", type}};
843*c8dee2aaSAndroid Build Coastguard Worker         SkDEBUGCODE(mgr.setExpectedUniforms(SkSpan(expectations), /*isSubstruct=*/false);)
844*c8dee2aaSAndroid Build Coastguard Worker         mgr.write(expectations[0], kFloats);
845*c8dee2aaSAndroid Build Coastguard Worker         SkDEBUGCODE(mgr.doneWithExpectedUniforms();)
846*c8dee2aaSAndroid Build Coastguard Worker         SkSpan<const char> uniformData = mgr.finish();
847*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(r, uniformData.size() == 16,
848*c8dee2aaSAndroid Build Coastguard Worker                         "%s layout size expected 16, got %zu",
849*c8dee2aaSAndroid Build Coastguard Worker                         SkSLTypeString(type), uniformData.size());
850*c8dee2aaSAndroid Build Coastguard Worker 
851*c8dee2aaSAndroid Build Coastguard Worker         // The expected offsets of the 4 matrix elements. This uses a tighter packing than std140
852*c8dee2aaSAndroid Build Coastguard Worker         // layout.
853*c8dee2aaSAndroid Build Coastguard Worker         const int kOffsets[4] = {0, 1, 2, 3};
854*c8dee2aaSAndroid Build Coastguard Worker         const float* elements = reinterpret_cast<const float*>(uniformData.data());
855*c8dee2aaSAndroid Build Coastguard Worker         for (size_t i = 0u; i < std::size(kOffsets); ++i) {
856*c8dee2aaSAndroid Build Coastguard Worker             float expected = kFloats[i];
857*c8dee2aaSAndroid Build Coastguard Worker             float el = elements[kOffsets[i]];
858*c8dee2aaSAndroid Build Coastguard Worker             REPORTER_ASSERT(r, el == expected,
859*c8dee2aaSAndroid Build Coastguard Worker                             "Incorrect %s element %zu - expected %f, got %f",
860*c8dee2aaSAndroid Build Coastguard Worker                             SkSLTypeString(type), i, expected, el);
861*c8dee2aaSAndroid Build Coastguard Worker         }
862*c8dee2aaSAndroid Build Coastguard Worker         mgr.reset();
863*c8dee2aaSAndroid Build Coastguard Worker     }
864*c8dee2aaSAndroid Build Coastguard Worker 
865*c8dee2aaSAndroid Build Coastguard Worker     // float3x3, half3x3
866*c8dee2aaSAndroid Build Coastguard Worker     for (SkSLType type : {SkSLType::kFloat3x3, SkSLType::kHalf3x3}) {
867*c8dee2aaSAndroid Build Coastguard Worker         const Uniform expectations[] = {{"m", type}};
868*c8dee2aaSAndroid Build Coastguard Worker         SkDEBUGCODE(mgr.setExpectedUniforms(SkSpan(expectations), /*isSubstruct=*/false);)
869*c8dee2aaSAndroid Build Coastguard Worker         mgr.write(expectations[0], kFloats);
870*c8dee2aaSAndroid Build Coastguard Worker         SkDEBUGCODE(mgr.doneWithExpectedUniforms();)
871*c8dee2aaSAndroid Build Coastguard Worker         SkSpan<const char> uniformData = mgr.finish();
872*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(r, uniformData.size() == 48,
873*c8dee2aaSAndroid Build Coastguard Worker                         "%s layout size expected 48, got %zu",
874*c8dee2aaSAndroid Build Coastguard Worker                         SkSLTypeString(type), uniformData.size());
875*c8dee2aaSAndroid Build Coastguard Worker 
876*c8dee2aaSAndroid Build Coastguard Worker         // The expected offsets of the 9 matrix elements. This is the same as std140 layout.
877*c8dee2aaSAndroid Build Coastguard Worker         const int kOffsets[9] = {0, 1, 2, 4, 5, 6, 8, 9, 10};
878*c8dee2aaSAndroid Build Coastguard Worker         const float* elements = reinterpret_cast<const float*>(uniformData.data());
879*c8dee2aaSAndroid Build Coastguard Worker         for (size_t i = 0u; i < std::size(kOffsets); ++i) {
880*c8dee2aaSAndroid Build Coastguard Worker             float expected = kFloats[i];
881*c8dee2aaSAndroid Build Coastguard Worker             float el = elements[kOffsets[i]];
882*c8dee2aaSAndroid Build Coastguard Worker             REPORTER_ASSERT(r, el == expected,
883*c8dee2aaSAndroid Build Coastguard Worker                             "Incorrect %s element %zu - expected %f, got %f",
884*c8dee2aaSAndroid Build Coastguard Worker                             SkSLTypeString(type), i, expected, el);
885*c8dee2aaSAndroid Build Coastguard Worker         }
886*c8dee2aaSAndroid Build Coastguard Worker         mgr.reset();
887*c8dee2aaSAndroid Build Coastguard Worker     }
888*c8dee2aaSAndroid Build Coastguard Worker }
889*c8dee2aaSAndroid Build Coastguard Worker 
890*c8dee2aaSAndroid Build Coastguard Worker // These tests validate that substructs are written and aligned appropriately.
DEF_GRAPHITE_TEST(UniformManagerStructLayout,r,CtsEnforcement::kNextRelease)891*c8dee2aaSAndroid Build Coastguard Worker DEF_GRAPHITE_TEST(UniformManagerStructLayout, r, CtsEnforcement::kNextRelease) {
892*c8dee2aaSAndroid Build Coastguard Worker     static constexpr uint32_t _ = 0; // 0s will only be written as padding
893*c8dee2aaSAndroid Build Coastguard Worker     static const struct TestCase {
894*c8dee2aaSAndroid Build Coastguard Worker         // For convenience, these should only have kFloat[2,3,4] as their types. However the values
895*c8dee2aaSAndroid Build Coastguard Worker         // written are integers and will be bit-punned to floats so that expectations are easy to
896*c8dee2aaSAndroid Build Coastguard Worker         // define (UniformManager and Skia have no defined kInt3 object type). Written integers
897*c8dee2aaSAndroid Build Coastguard Worker         // start at 1 and are incremented with each component across uniforms.
898*c8dee2aaSAndroid Build Coastguard Worker         std::vector<Uniform> fPreStruct;  // before beginStruct(), top-level fields or struct
899*c8dee2aaSAndroid Build Coastguard Worker         std::vector<Uniform> fSubstruct;  // within beginStruct()/endStruct()
900*c8dee2aaSAndroid Build Coastguard Worker         std::vector<Uniform> fPostStruct; // after endStruct(), top-level fields
901*c8dee2aaSAndroid Build Coastguard Worker 
902*c8dee2aaSAndroid Build Coastguard Worker         std::pair<int, std::vector<uint32_t>> fExpectedAlignmentAndData[std::size(kLayouts)];
903*c8dee2aaSAndroid Build Coastguard Worker 
904*c8dee2aaSAndroid Build Coastguard Worker         // If non-empty, holds base alignments for fPreStruct base alignment as a struct
905*c8dee2aaSAndroid Build Coastguard Worker         std::vector<int> fPreStructAlignments = {};
906*c8dee2aaSAndroid Build Coastguard Worker     } kCases[] = {
907*c8dee2aaSAndroid Build Coastguard Worker         // Struct tests with no preceeding or following top-level fields
908*c8dee2aaSAndroid Build Coastguard Worker         {/*prestruct=*/ {},
909*c8dee2aaSAndroid Build Coastguard Worker          /*substruct=*/ {{"u1", SkSLType::kFloat},
910*c8dee2aaSAndroid Build Coastguard Worker                          {"u2", SkSLType::kFloat},
911*c8dee2aaSAndroid Build Coastguard Worker                          {"u3", SkSLType::kFloat},
912*c8dee2aaSAndroid Build Coastguard Worker                          {"u4", SkSLType::kFloat}},
913*c8dee2aaSAndroid Build Coastguard Worker          /*poststruct=*/{},
914*c8dee2aaSAndroid Build Coastguard Worker          /*expect=*/{
915*c8dee2aaSAndroid Build Coastguard Worker             /*std140=*/{/*baseAlign=*/16, /*data=*/{1, 2, 3, 4}},
916*c8dee2aaSAndroid Build Coastguard Worker             /*std430=*/{/*baseAlign=*/4,  /*data=*/{1, 2, 3, 4}},
917*c8dee2aaSAndroid Build Coastguard Worker             /*metal=*/ {/*baseAlign=*/4,  /*data=*/{1, 2, 3, 4}}
918*c8dee2aaSAndroid Build Coastguard Worker          }},
919*c8dee2aaSAndroid Build Coastguard Worker 
920*c8dee2aaSAndroid Build Coastguard Worker         {/*prestruct=*/ {},
921*c8dee2aaSAndroid Build Coastguard Worker          /*substruct=*/ {{"u1", SkSLType::kFloat3},
922*c8dee2aaSAndroid Build Coastguard Worker                          {"u2", SkSLType::kFloat}},
923*c8dee2aaSAndroid Build Coastguard Worker          /*poststruct=*/{},
924*c8dee2aaSAndroid Build Coastguard Worker          /*expect=*/{
925*c8dee2aaSAndroid Build Coastguard Worker             /*std140=*/{/*baseAlign=*/16, /*data=*/{1,2,3, 4}},
926*c8dee2aaSAndroid Build Coastguard Worker             /*std430=*/{/*baseAlign=*/16, /*data=*/{1,2,3, 4}},
927*c8dee2aaSAndroid Build Coastguard Worker             /*metal=*/ {/*baseAlign=*/16, /*data=*/{1,2,3,_, 4,_,_,_}}
928*c8dee2aaSAndroid Build Coastguard Worker          }},
929*c8dee2aaSAndroid Build Coastguard Worker 
930*c8dee2aaSAndroid Build Coastguard Worker         {/*prestruct=*/ {},
931*c8dee2aaSAndroid Build Coastguard Worker          /*substruct=*/ {{"u1", SkSLType::kFloat2},
932*c8dee2aaSAndroid Build Coastguard Worker                          {"u2", SkSLType::kFloat},
933*c8dee2aaSAndroid Build Coastguard Worker                          {"u3", SkSLType::kFloat},
934*c8dee2aaSAndroid Build Coastguard Worker                          {"u4", SkSLType::kFloat}},
935*c8dee2aaSAndroid Build Coastguard Worker          /*poststruct=*/{},
936*c8dee2aaSAndroid Build Coastguard Worker          /*expect=*/{
937*c8dee2aaSAndroid Build Coastguard Worker             /*std140=*/{/*baseAlign=*/16, /*data=*/{1,2, 3, 4, 5,_,_,_}},
938*c8dee2aaSAndroid Build Coastguard Worker             /*std430=*/{/*baseAlign=*/8,  /*data=*/{1,2, 3, 4, 5,_}},
939*c8dee2aaSAndroid Build Coastguard Worker             /*metal=*/ {/*baseAlign=*/8,  /*data=*/{1,2, 3, 4, 5,_}}
940*c8dee2aaSAndroid Build Coastguard Worker          }},
941*c8dee2aaSAndroid Build Coastguard Worker 
942*c8dee2aaSAndroid Build Coastguard Worker         {/*prestruct=*/ {},
943*c8dee2aaSAndroid Build Coastguard Worker          /*substruct=*/ {{"u1", SkSLType::kFloat},
944*c8dee2aaSAndroid Build Coastguard Worker                          {"u2", SkSLType::kFloat4},
945*c8dee2aaSAndroid Build Coastguard Worker                          {"u3", SkSLType::kFloat2},
946*c8dee2aaSAndroid Build Coastguard Worker                          {"u4", SkSLType::kFloat3}},
947*c8dee2aaSAndroid Build Coastguard Worker          /*poststruct=*/{},
948*c8dee2aaSAndroid Build Coastguard Worker          /*expect=*/{
949*c8dee2aaSAndroid Build Coastguard Worker             /*std140=*/{/*baseAlign=*/16, /*data=*/{1,_,_,_, 2,3,4,5, 6,7,_,_, 8,9,10,_}},
950*c8dee2aaSAndroid Build Coastguard Worker             /*std430=*/{/*baseAlign=*/16, /*data=*/{1,_,_,_, 2,3,4,5, 6,7,_,_, 8,9,10,_}},
951*c8dee2aaSAndroid Build Coastguard Worker             /*metal=*/ {/*baseAlign=*/16, /*data=*/{1,_,_,_, 2,3,4,5, 6,7,_,_, 8,9,10,_}}
952*c8dee2aaSAndroid Build Coastguard Worker          }},
953*c8dee2aaSAndroid Build Coastguard Worker 
954*c8dee2aaSAndroid Build Coastguard Worker 
955*c8dee2aaSAndroid Build Coastguard Worker         // Struct tests with a preceeding float to require padding to the struct's base alignment
956*c8dee2aaSAndroid Build Coastguard Worker         {/*prestruct=*/ {{"p1", SkSLType::kFloat}},
957*c8dee2aaSAndroid Build Coastguard Worker          /*substruct=*/ {{"u1", SkSLType::kFloat},
958*c8dee2aaSAndroid Build Coastguard Worker                          {"u2", SkSLType::kFloat},
959*c8dee2aaSAndroid Build Coastguard Worker                          {"u3", SkSLType::kFloat},
960*c8dee2aaSAndroid Build Coastguard Worker                          {"u4", SkSLType::kFloat}},
961*c8dee2aaSAndroid Build Coastguard Worker          /*poststruct=*/{},
962*c8dee2aaSAndroid Build Coastguard Worker          /*expect=*/{
963*c8dee2aaSAndroid Build Coastguard Worker             /*std140=*/{/*baseAlign=*/16, /*data=*/{1,_,_,_, 2, 3, 4, 5}},
964*c8dee2aaSAndroid Build Coastguard Worker             /*std430=*/{/*baseAlign=*/4,  /*data=*/{1, 2, 3, 4, 5}},
965*c8dee2aaSAndroid Build Coastguard Worker             /*metal=*/ {/*baseAlign=*/4,  /*data=*/{1, 2, 3, 4, 5}}
966*c8dee2aaSAndroid Build Coastguard Worker          }},
967*c8dee2aaSAndroid Build Coastguard Worker 
968*c8dee2aaSAndroid Build Coastguard Worker         {/*prestruct=*/ {{"p1", SkSLType::kFloat}},
969*c8dee2aaSAndroid Build Coastguard Worker          /*substruct=*/ {{"u1", SkSLType::kFloat3},
970*c8dee2aaSAndroid Build Coastguard Worker                          {"u2", SkSLType::kFloat}},
971*c8dee2aaSAndroid Build Coastguard Worker          /*poststruct=*/{},
972*c8dee2aaSAndroid Build Coastguard Worker          /*expect=*/{
973*c8dee2aaSAndroid Build Coastguard Worker             /*std140=*/{/*baseAlign=*/16, /*data=*/{1,_,_,_, 2,3,4, 5}},
974*c8dee2aaSAndroid Build Coastguard Worker             /*std430=*/{/*baseAlign=*/16, /*data=*/{1,_,_,_, 2,3,4, 5}},
975*c8dee2aaSAndroid Build Coastguard Worker             /*metal=*/ {/*baseAlign=*/16, /*data=*/{1,_,_,_, 2,3,4,_, 5,_,_,_}}
976*c8dee2aaSAndroid Build Coastguard Worker          }},
977*c8dee2aaSAndroid Build Coastguard Worker 
978*c8dee2aaSAndroid Build Coastguard Worker         {/*prestruct=*/ {{"p1", SkSLType::kFloat}},
979*c8dee2aaSAndroid Build Coastguard Worker          /*substruct=*/ {{"u1", SkSLType::kFloat2},
980*c8dee2aaSAndroid Build Coastguard Worker                          {"u2", SkSLType::kFloat},
981*c8dee2aaSAndroid Build Coastguard Worker                          {"u3", SkSLType::kFloat},
982*c8dee2aaSAndroid Build Coastguard Worker                          {"u4", SkSLType::kFloat}},
983*c8dee2aaSAndroid Build Coastguard Worker          /*poststruct=*/{},
984*c8dee2aaSAndroid Build Coastguard Worker          /*expect=*/{
985*c8dee2aaSAndroid Build Coastguard Worker             /*std140=*/{/*baseAlign=*/16, /*data=*/{1,_,_,_, 2,3, 4, 5, 6,_,_,_}},
986*c8dee2aaSAndroid Build Coastguard Worker             /*std430=*/{/*baseAlign=*/8,  /*data=*/{1,_, 2,3, 4, 5, 6,_}},
987*c8dee2aaSAndroid Build Coastguard Worker             /*metal=*/ {/*baseAlign=*/8,  /*data=*/{1,_, 2,3, 4, 5, 6,_}}
988*c8dee2aaSAndroid Build Coastguard Worker          }},
989*c8dee2aaSAndroid Build Coastguard Worker 
990*c8dee2aaSAndroid Build Coastguard Worker         {/*prestruct=*/ {{"p1", SkSLType::kFloat}},
991*c8dee2aaSAndroid Build Coastguard Worker          /*substruct=*/ {{"u1", SkSLType::kFloat},
992*c8dee2aaSAndroid Build Coastguard Worker                          {"u2", SkSLType::kFloat4},
993*c8dee2aaSAndroid Build Coastguard Worker                          {"u3", SkSLType::kFloat2},
994*c8dee2aaSAndroid Build Coastguard Worker                          {"u4", SkSLType::kFloat3}},
995*c8dee2aaSAndroid Build Coastguard Worker          /*poststruct=*/{},
996*c8dee2aaSAndroid Build Coastguard Worker          /*expect=*/{
997*c8dee2aaSAndroid Build Coastguard Worker             /*std140=*/{/*baseAlign=*/16, /*data=*/{1,_,_,_, 2,_,_,_, 3,4,5,6, 7,8,_,_, 9,10,11,_}},
998*c8dee2aaSAndroid Build Coastguard Worker             /*std430=*/{/*baseAlign=*/16, /*data=*/{1,_,_,_, 2,_,_,_, 3,4,5,6, 7,8,_,_, 9,10,11,_}},
999*c8dee2aaSAndroid Build Coastguard Worker             /*metal=*/ {/*baseAlign=*/16, /*data=*/{1,_,_,_, 2,_,_,_, 3,4,5,6, 7,8,_,_, 9,10,11,_}}
1000*c8dee2aaSAndroid Build Coastguard Worker          }},
1001*c8dee2aaSAndroid Build Coastguard Worker 
1002*c8dee2aaSAndroid Build Coastguard Worker         // Struct tests with a preceeding float to require padding to the struct's base alignment,
1003*c8dee2aaSAndroid Build Coastguard Worker         // and a following float4 to test alignment after a struct.
1004*c8dee2aaSAndroid Build Coastguard Worker         {/*prestruct=*/ {{"p1", SkSLType::kFloat}},
1005*c8dee2aaSAndroid Build Coastguard Worker          /*substruct=*/ {{"u1", SkSLType::kFloat},
1006*c8dee2aaSAndroid Build Coastguard Worker                          {"u2", SkSLType::kFloat},
1007*c8dee2aaSAndroid Build Coastguard Worker                          {"u3", SkSLType::kFloat},
1008*c8dee2aaSAndroid Build Coastguard Worker                          {"u4", SkSLType::kFloat}},
1009*c8dee2aaSAndroid Build Coastguard Worker          /*poststruct=*/{{"p2", SkSLType::kFloat4}},
1010*c8dee2aaSAndroid Build Coastguard Worker          /*expect=*/{
1011*c8dee2aaSAndroid Build Coastguard Worker             /*std140=*/{/*baseAlign=*/16, /*data=*/{1,_,_,_, 2, 3, 4, 5, 6,7,8,9}},
1012*c8dee2aaSAndroid Build Coastguard Worker             /*std430=*/{/*baseAlign=*/4,  /*data=*/{1, 2, 3, 4, 5, _,_,_,6,7,8,9}},
1013*c8dee2aaSAndroid Build Coastguard Worker             /*metal=*/ {/*baseAlign=*/4,  /*data=*/{1, 2, 3, 4, 5, _,_,_,6,7,8,9}}
1014*c8dee2aaSAndroid Build Coastguard Worker          }},
1015*c8dee2aaSAndroid Build Coastguard Worker 
1016*c8dee2aaSAndroid Build Coastguard Worker         {/*prestruct=*/ {{"p1", SkSLType::kFloat}},
1017*c8dee2aaSAndroid Build Coastguard Worker          /*substruct=*/ {{"u1", SkSLType::kFloat3},
1018*c8dee2aaSAndroid Build Coastguard Worker                          {"u2", SkSLType::kFloat}},
1019*c8dee2aaSAndroid Build Coastguard Worker          /*poststruct=*/{{"p2", SkSLType::kFloat4}},
1020*c8dee2aaSAndroid Build Coastguard Worker          /*expect=*/{
1021*c8dee2aaSAndroid Build Coastguard Worker             /*std140=*/{/*baseAlign=*/16, /*data=*/{1,_,_,_, 2,3,4, 5, 6,7,8,9}},
1022*c8dee2aaSAndroid Build Coastguard Worker             /*std430=*/{/*baseAlign=*/16, /*data=*/{1,_,_,_, 2,3,4, 5, 6,7,8,9}},
1023*c8dee2aaSAndroid Build Coastguard Worker             /*metal=*/ {/*baseAlign=*/16, /*data=*/{1,_,_,_, 2,3,4,_, 5,_,_,_, 6,7,8,9}}
1024*c8dee2aaSAndroid Build Coastguard Worker          }},
1025*c8dee2aaSAndroid Build Coastguard Worker 
1026*c8dee2aaSAndroid Build Coastguard Worker         {/*prestruct=*/ {{"p1", SkSLType::kFloat}},
1027*c8dee2aaSAndroid Build Coastguard Worker          /*substruct=*/ {{"u1", SkSLType::kFloat2},
1028*c8dee2aaSAndroid Build Coastguard Worker                          {"u2", SkSLType::kFloat},
1029*c8dee2aaSAndroid Build Coastguard Worker                          {"u3", SkSLType::kFloat},
1030*c8dee2aaSAndroid Build Coastguard Worker                          {"u4", SkSLType::kFloat}},
1031*c8dee2aaSAndroid Build Coastguard Worker          /*poststruct=*/{{"p2", SkSLType::kFloat4}},
1032*c8dee2aaSAndroid Build Coastguard Worker          /*expect=*/{
1033*c8dee2aaSAndroid Build Coastguard Worker             /*std140=*/{/*baseAlign=*/16, /*data=*/{1,_,_,_, 2,3, 4, 5, 6,_,_,_, 7,8,9,10}},
1034*c8dee2aaSAndroid Build Coastguard Worker             /*std430=*/{/*baseAlign=*/8,  /*data=*/{1,_, 2,3, 4, 5, 6,_, 7,8,9,10}},
1035*c8dee2aaSAndroid Build Coastguard Worker             /*metal=*/ {/*baseAlign=*/8,  /*data=*/{1,_, 2,3, 4, 5, 6,_, 7,8,9,10}}
1036*c8dee2aaSAndroid Build Coastguard Worker          }},
1037*c8dee2aaSAndroid Build Coastguard Worker 
1038*c8dee2aaSAndroid Build Coastguard Worker         {/*prestruct=*/ {{"p1", SkSLType::kFloat}},
1039*c8dee2aaSAndroid Build Coastguard Worker          /*substruct=*/ {{"u1", SkSLType::kFloat},
1040*c8dee2aaSAndroid Build Coastguard Worker                          {"u2", SkSLType::kFloat4},
1041*c8dee2aaSAndroid Build Coastguard Worker                          {"u3", SkSLType::kFloat2},
1042*c8dee2aaSAndroid Build Coastguard Worker                          {"u4", SkSLType::kFloat3}},
1043*c8dee2aaSAndroid Build Coastguard Worker          /*poststruct=*/{{"p2", SkSLType::kFloat4}},
1044*c8dee2aaSAndroid Build Coastguard Worker          /*expect=*/{
1045*c8dee2aaSAndroid Build Coastguard Worker             /*std140=*/{/*baseAlign=*/16, /*data=*/{1,_,_,_, 2,_,_,_, 3,4,5,6, 7,8,_,_, 9,10,11,_, 12,13,14,15}},
1046*c8dee2aaSAndroid Build Coastguard Worker             /*std430=*/{/*baseAlign=*/16, /*data=*/{1,_,_,_, 2,_,_,_, 3,4,5,6, 7,8,_,_, 9,10,11,_, 12,13,14,15}},
1047*c8dee2aaSAndroid Build Coastguard Worker             /*metal=*/ {/*baseAlign=*/16, /*data=*/{1,_,_,_, 2,_,_,_, 3,4,5,6, 7,8,_,_, 9,10,11,_, 12,13,14,15}}
1048*c8dee2aaSAndroid Build Coastguard Worker          }},
1049*c8dee2aaSAndroid Build Coastguard Worker 
1050*c8dee2aaSAndroid Build Coastguard Worker         // Struct tests with two adjacent structs
1051*c8dee2aaSAndroid Build Coastguard Worker         {/*prestruct=*/ {{"p1", SkSLType::kFloat2},
1052*c8dee2aaSAndroid Build Coastguard Worker                          {"p2", SkSLType::kFloat}},
1053*c8dee2aaSAndroid Build Coastguard Worker          /*substruct=*/ {{"u1", SkSLType::kFloat},
1054*c8dee2aaSAndroid Build Coastguard Worker                          {"u2", SkSLType::kFloat}},
1055*c8dee2aaSAndroid Build Coastguard Worker          /*poststruct=*/{},
1056*c8dee2aaSAndroid Build Coastguard Worker          /*expect=*/{
1057*c8dee2aaSAndroid Build Coastguard Worker             /*std140=*/{/*baseAlign=*/16, /*data=*/{1,2, 3,_, 4, 5,_,_}},
1058*c8dee2aaSAndroid Build Coastguard Worker             /*std430=*/{/*baseAlign=*/4,  /*data=*/{1,2, 3,_, 4, 5}},
1059*c8dee2aaSAndroid Build Coastguard Worker             /*metal=*/ {/*baseAlign=*/4,  /*data=*/{1,2, 3,_, 4, 5}}
1060*c8dee2aaSAndroid Build Coastguard Worker          },
1061*c8dee2aaSAndroid Build Coastguard Worker          /*preStructAlignments=*/{
1062*c8dee2aaSAndroid Build Coastguard Worker             /*std140=*/16,
1063*c8dee2aaSAndroid Build Coastguard Worker             /*std430=*/8,
1064*c8dee2aaSAndroid Build Coastguard Worker             /*metal=*/ 8
1065*c8dee2aaSAndroid Build Coastguard Worker          }}
1066*c8dee2aaSAndroid Build Coastguard Worker     };
1067*c8dee2aaSAndroid Build Coastguard Worker 
1068*c8dee2aaSAndroid Build Coastguard Worker     auto writeFields = [](UniformManager* mgr, SkSpan<const Uniform> fields, uint32_t baseValue) {
1069*c8dee2aaSAndroid Build Coastguard Worker         for (const Uniform& f : fields) {
1070*c8dee2aaSAndroid Build Coastguard Worker             switch(f.type()) {
1071*c8dee2aaSAndroid Build Coastguard Worker                 case SkSLType::kFloat:
1072*c8dee2aaSAndroid Build Coastguard Worker                     mgr->write(SkBits2Float(baseValue++));
1073*c8dee2aaSAndroid Build Coastguard Worker                     break;
1074*c8dee2aaSAndroid Build Coastguard Worker                 case SkSLType::kFloat2:
1075*c8dee2aaSAndroid Build Coastguard Worker                     mgr->write(SkV2{SkBits2Float(baseValue++),
1076*c8dee2aaSAndroid Build Coastguard Worker                                     SkBits2Float(baseValue++)});
1077*c8dee2aaSAndroid Build Coastguard Worker                     break;
1078*c8dee2aaSAndroid Build Coastguard Worker                 case SkSLType::kFloat3:
1079*c8dee2aaSAndroid Build Coastguard Worker                     mgr->write(SkV3{SkBits2Float(baseValue++),
1080*c8dee2aaSAndroid Build Coastguard Worker                                     SkBits2Float(baseValue++),
1081*c8dee2aaSAndroid Build Coastguard Worker                                     SkBits2Float(baseValue++)});
1082*c8dee2aaSAndroid Build Coastguard Worker                     break;
1083*c8dee2aaSAndroid Build Coastguard Worker                 case SkSLType::kFloat4:
1084*c8dee2aaSAndroid Build Coastguard Worker                     mgr->write(SkV4{SkBits2Float(baseValue++),
1085*c8dee2aaSAndroid Build Coastguard Worker                                     SkBits2Float(baseValue++),
1086*c8dee2aaSAndroid Build Coastguard Worker                                     SkBits2Float(baseValue++),
1087*c8dee2aaSAndroid Build Coastguard Worker                                     SkBits2Float(baseValue++)});
1088*c8dee2aaSAndroid Build Coastguard Worker                     break;
1089*c8dee2aaSAndroid Build Coastguard Worker                 default:
1090*c8dee2aaSAndroid Build Coastguard Worker                     SkUNREACHABLE;
1091*c8dee2aaSAndroid Build Coastguard Worker             }
1092*c8dee2aaSAndroid Build Coastguard Worker         }
1093*c8dee2aaSAndroid Build Coastguard Worker         return baseValue;
1094*c8dee2aaSAndroid Build Coastguard Worker     };
1095*c8dee2aaSAndroid Build Coastguard Worker 
1096*c8dee2aaSAndroid Build Coastguard Worker     bool dataMatchFailureLogged = false;
1097*c8dee2aaSAndroid Build Coastguard Worker     for (size_t l = 0; l < std::size(kLayouts); ++l) {
1098*c8dee2aaSAndroid Build Coastguard Worker         const Layout layout = kLayouts[l];
1099*c8dee2aaSAndroid Build Coastguard Worker         skiatest::ReporterContext layoutLabel(r, LayoutString(layout));
1100*c8dee2aaSAndroid Build Coastguard Worker 
1101*c8dee2aaSAndroid Build Coastguard Worker         for (size_t t = 0; t < std::size(kCases); ++t) {
1102*c8dee2aaSAndroid Build Coastguard Worker             const TestCase& test = kCases[t];
1103*c8dee2aaSAndroid Build Coastguard Worker             skiatest::ReporterContext testLabel(r, std::to_string(t));
1104*c8dee2aaSAndroid Build Coastguard Worker 
1105*c8dee2aaSAndroid Build Coastguard Worker             auto [baseAlignment, expectedData] = test.fExpectedAlignmentAndData[l];
1106*c8dee2aaSAndroid Build Coastguard Worker 
1107*c8dee2aaSAndroid Build Coastguard Worker             UniformManager mgr{layout};
1108*c8dee2aaSAndroid Build Coastguard Worker             int baseValue = 1;
1109*c8dee2aaSAndroid Build Coastguard Worker             if (!test.fPreStruct.empty()) {
1110*c8dee2aaSAndroid Build Coastguard Worker                 // pre-struct fields
1111*c8dee2aaSAndroid Build Coastguard Worker                 const bool preStructIsStruct = !test.fPreStructAlignments.empty();
1112*c8dee2aaSAndroid Build Coastguard Worker                 SkDEBUGCODE(mgr.setExpectedUniforms(test.fPreStruct, preStructIsStruct);)
1113*c8dee2aaSAndroid Build Coastguard Worker                 if (preStructIsStruct) {
1114*c8dee2aaSAndroid Build Coastguard Worker                     mgr.beginStruct(test.fPreStructAlignments[l]);
1115*c8dee2aaSAndroid Build Coastguard Worker                 }
1116*c8dee2aaSAndroid Build Coastguard Worker                 baseValue = writeFields(&mgr, test.fPreStruct, baseValue);
1117*c8dee2aaSAndroid Build Coastguard Worker                 if (preStructIsStruct) {
1118*c8dee2aaSAndroid Build Coastguard Worker                     mgr.endStruct();
1119*c8dee2aaSAndroid Build Coastguard Worker                 }
1120*c8dee2aaSAndroid Build Coastguard Worker                 SkDEBUGCODE(mgr.doneWithExpectedUniforms();)
1121*c8dee2aaSAndroid Build Coastguard Worker             }
1122*c8dee2aaSAndroid Build Coastguard Worker             if (!test.fSubstruct.empty()) {
1123*c8dee2aaSAndroid Build Coastguard Worker                 // substruct fields
1124*c8dee2aaSAndroid Build Coastguard Worker                 SkDEBUGCODE(mgr.setExpectedUniforms(test.fSubstruct, /*isSubstruct=*/true);)
1125*c8dee2aaSAndroid Build Coastguard Worker                 mgr.beginStruct(baseAlignment);
1126*c8dee2aaSAndroid Build Coastguard Worker                 baseValue = writeFields(&mgr, test.fSubstruct, baseValue);
1127*c8dee2aaSAndroid Build Coastguard Worker                 mgr.endStruct();
1128*c8dee2aaSAndroid Build Coastguard Worker                 SkDEBUGCODE(mgr.doneWithExpectedUniforms();)
1129*c8dee2aaSAndroid Build Coastguard Worker             }
1130*c8dee2aaSAndroid Build Coastguard Worker             if (!test.fPostStruct.empty()) {
1131*c8dee2aaSAndroid Build Coastguard Worker                 // post-struct fields
1132*c8dee2aaSAndroid Build Coastguard Worker                 SkDEBUGCODE(mgr.setExpectedUniforms(test.fPostStruct, /*isSubstruct=*/false);)
1133*c8dee2aaSAndroid Build Coastguard Worker                 baseValue = writeFields(&mgr, test.fPostStruct, baseValue);
1134*c8dee2aaSAndroid Build Coastguard Worker                 SkDEBUGCODE(mgr.doneWithExpectedUniforms();)
1135*c8dee2aaSAndroid Build Coastguard Worker             }
1136*c8dee2aaSAndroid Build Coastguard Worker 
1137*c8dee2aaSAndroid Build Coastguard Worker             SkSpan<const char> data = mgr.finish();
1138*c8dee2aaSAndroid Build Coastguard Worker 
1139*c8dee2aaSAndroid Build Coastguard Worker             bool sizeMatch = data.size() == sizeof(uint32_t)*expectedData.size();
1140*c8dee2aaSAndroid Build Coastguard Worker             // To reduce logging/asserts, pretend contents "match" if the sizes differ since that
1141*c8dee2aaSAndroid Build Coastguard Worker             // will already be triggering test failures
1142*c8dee2aaSAndroid Build Coastguard Worker             bool contentsMatch = !sizeMatch ||
1143*c8dee2aaSAndroid Build Coastguard Worker                                  memcmp(data.data(), expectedData.data(), data.size()) == 0;
1144*c8dee2aaSAndroid Build Coastguard Worker             REPORTER_ASSERT(r, sizeMatch, "Size mismatch between written (%zu) and expected (%zu)",
1145*c8dee2aaSAndroid Build Coastguard Worker                             data.size(), expectedData.size());
1146*c8dee2aaSAndroid Build Coastguard Worker             REPORTER_ASSERT(r, contentsMatch, "Contents differ between written and expected");
1147*c8dee2aaSAndroid Build Coastguard Worker 
1148*c8dee2aaSAndroid Build Coastguard Worker             if (!contentsMatch && !dataMatchFailureLogged) {
1149*c8dee2aaSAndroid Build Coastguard Worker                 // Print out actual and expected values once if it's only the contents that are
1150*c8dee2aaSAndroid Build Coastguard Worker                 // incorrect (don't bother printing contents if their lengths differ).
1151*c8dee2aaSAndroid Build Coastguard Worker                 SkDebugf("Expected contents:\n");
1152*c8dee2aaSAndroid Build Coastguard Worker                 for (size_t i = 0; i < expectedData.size(); ++i) {
1153*c8dee2aaSAndroid Build Coastguard Worker                     SkDebugf("%s%u", i % 4 == 0 ? " " : ",", expectedData[i]);
1154*c8dee2aaSAndroid Build Coastguard Worker                 }
1155*c8dee2aaSAndroid Build Coastguard Worker                 SkDebugf("\nActual contents:\n");
1156*c8dee2aaSAndroid Build Coastguard Worker                 SkASSERT(data.size() % 4 == 0);
1157*c8dee2aaSAndroid Build Coastguard Worker                 const uint32_t* actualData = reinterpret_cast<const uint32_t*>(data.begin());
1158*c8dee2aaSAndroid Build Coastguard Worker                 for (size_t i = 0; i < expectedData.size(); ++i) {
1159*c8dee2aaSAndroid Build Coastguard Worker                     SkDebugf("%s%u", i % 4 == 0 ? " " : ",", actualData[i]);
1160*c8dee2aaSAndroid Build Coastguard Worker                 }
1161*c8dee2aaSAndroid Build Coastguard Worker                 SkDebugf("\n\n");
1162*c8dee2aaSAndroid Build Coastguard Worker                 dataMatchFailureLogged = true;
1163*c8dee2aaSAndroid Build Coastguard Worker             }
1164*c8dee2aaSAndroid Build Coastguard Worker         }
1165*c8dee2aaSAndroid Build Coastguard Worker     }
1166*c8dee2aaSAndroid Build Coastguard Worker }
1167