• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2022 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "src/base/SkHalf.h"
9 #include "src/core/SkSLTypeShared.h"
10 #include "src/gpu/graphite/PipelineData.h"
11 #include "src/gpu/graphite/Uniform.h"
12 #include "src/gpu/graphite/UniformManager.h"
13 #include "tests/Test.h"
14 
15 using namespace skgpu::graphite;
16 
17 static constexpr Layout kLayouts[] = {
18         Layout::kStd140,
19         Layout::kStd430,
20         Layout::kMetal,
21 };
22 
23 // This list excludes SkSLTypes that we don't support in uniforms, like Bool, UInt or UShort.
24 static constexpr SkSLType kTypes[] = {
25         SkSLType::kFloat,    SkSLType::kFloat2,   SkSLType::kFloat3,   SkSLType::kFloat4,   //
26         SkSLType::kHalf,     SkSLType::kHalf2,    SkSLType::kHalf3,    SkSLType::kHalf4,    //
27         SkSLType::kInt,      SkSLType::kInt2,     SkSLType::kInt3,     SkSLType::kInt4,     //
28         SkSLType::kFloat2x2, SkSLType::kFloat3x3, SkSLType::kFloat4x4,                      //
29         SkSLType::kHalf2x2,  SkSLType::kHalf3x3,  SkSLType::kHalf4x4,
30 };
31 
32 static constexpr float kFloats[16] = { 1.0f,  2.0f,  3.0f,  4.0f,
33                                        5.0f,  6.0f,  7.0f,  8.0f,
34                                        9.0f, 10.0f, 11.0f, 12.0f,
35                                       13.0f, 14.0f, 15.0f, 16.0f };
36 
37 static constexpr SkHalf kHalfs[16] = { 0x3C00, 0x4000, 0x4200, 0x4400,
38                                        0x4500, 0x4600, 0x4700, 0x4800,
39                                        0x4880, 0x4900, 0x4980, 0x4A00,
40                                        0x4A80, 0x4B00, 0x4B80, 0x4C00 };
41 
42 static constexpr int32_t kInts[16] = { 1,  -2,  3,  -4,
43                                        5,  -6,  7,  -8,
44                                        9, -10, 11, -12,
45                                       13, -14, 15, -16 };
46 
element_size(Layout layout,SkSLType type)47 static size_t element_size(Layout layout, SkSLType type) {
48     // Metal encodes half-precision uniforms in 16 bits.
49     // Other layouts are expected to encode uniforms in 32 bits.
50     return (layout == Layout::kMetal && !SkSLTypeIsFullPrecisionNumericType(type)) ? 2 : 4;
51 }
52 
DEF_GRAPHITE_TEST(UniformManagerCheckSingleUniform,r,CtsEnforcement::kNextRelease)53 DEF_GRAPHITE_TEST(UniformManagerCheckSingleUniform, r, CtsEnforcement::kNextRelease) {
54     // Verify that the uniform manager can hold all the basic uniform types, in every layout.
55     for (Layout layout : kLayouts) {
56         UniformManager mgr(layout);
57 
58         for (SkSLType type : kTypes) {
59             const Uniform expectations[] = {{"uniform", type}};
60             SkDEBUGCODE(mgr.setExpectedUniforms(SkSpan(expectations));)
61             mgr.write(expectations[0], kFloats);
62             SkDEBUGCODE(mgr.doneWithExpectedUniforms();)
63             REPORTER_ASSERT(r, mgr.size() > 0, "Layout: %s - Type: %s",
64                             LayoutString(layout), SkSLTypeString(type));
65             mgr.reset();
66         }
67     }
68 }
69 
DEF_GRAPHITE_TEST(UniformManagerCheckFloatEncoding,r,CtsEnforcement::kNextRelease)70 DEF_GRAPHITE_TEST(UniformManagerCheckFloatEncoding, r, CtsEnforcement::kNextRelease) {
71     // Verify that the uniform manager encodes float data properly.
72     for (Layout layout : kLayouts) {
73         UniformManager mgr(layout);
74 
75         for (SkSLType type : kTypes) {
76             // Only test scalar and vector floats. (Matrices can introduce padding between values.)
77             int vecLength = SkSLTypeVecLength(type);
78             if (!SkSLTypeIsFloatType(type) || vecLength < 1) {
79                 continue;
80             }
81 
82             // Write our uniform float scalar/vector.
83             const Uniform expectations[] = {{"uniform", type}};
84             SkDEBUGCODE(mgr.setExpectedUniforms(SkSpan(expectations));)
85             mgr.write(expectations[0], kFloats);
86             SkDEBUGCODE(mgr.doneWithExpectedUniforms();)
87 
88             // Read back the uniform data.
89             UniformDataBlock uniformData = mgr.finishUniformDataBlock();
90             size_t elementSize = element_size(layout, type);
91             const void* validData = (elementSize == 4) ? (const void*)kFloats : (const void*)kHalfs;
92             REPORTER_ASSERT(r, uniformData.size() >= vecLength * elementSize);
93             REPORTER_ASSERT(r, 0 == memcmp(validData, uniformData.data(), vecLength * elementSize),
94                             "Layout: %s - Type: %s float encoding failed",
95                             LayoutString(layout), SkSLTypeString(type));
96             mgr.reset();
97         }
98     }
99 }
100 
DEF_GRAPHITE_TEST(UniformManagerCheckIntEncoding,r,CtsEnforcement::kNextRelease)101 DEF_GRAPHITE_TEST(UniformManagerCheckIntEncoding, r, CtsEnforcement::kNextRelease) {
102     // Verify that the uniform manager encodes int data properly.
103     for (Layout layout : kLayouts) {
104         UniformManager mgr(layout);
105 
106         for (SkSLType type : kTypes) {
107             if (!SkSLTypeIsIntegralType(type)) {
108                 continue;
109             }
110 
111             // Write our uniform int scalar/vector.
112             const Uniform expectations[] = {{"uniform", type}};
113             SkDEBUGCODE(mgr.setExpectedUniforms(SkSpan(expectations));)
114             mgr.write(expectations[0], kInts);
115             SkDEBUGCODE(mgr.doneWithExpectedUniforms();)
116 
117             // Read back the uniform data.
118             UniformDataBlock uniformData = mgr.finishUniformDataBlock();
119             int vecLength = SkSLTypeVecLength(type);
120             size_t elementSize = element_size(layout, type);
121             REPORTER_ASSERT(r, uniformData.size() >= vecLength * elementSize);
122             REPORTER_ASSERT(r, 0 == memcmp(kInts, uniformData.data(), vecLength * elementSize),
123                             "Layout: %s - Type: %s int encoding failed",
124                             LayoutString(layout), SkSLTypeString(type));
125             mgr.reset();
126         }
127     }
128 }
129 
DEF_GRAPHITE_TEST(UniformManagerCheckScalarVectorPacking,r,CtsEnforcement::kNextRelease)130 DEF_GRAPHITE_TEST(UniformManagerCheckScalarVectorPacking, r, CtsEnforcement::kNextRelease) {
131     // Verify that the uniform manager can pack scalars and vectors of identical type correctly.
132     for (Layout layout : kLayouts) {
133         UniformManager mgr(layout);
134 
135         for (SkSLType type : kTypes) {
136             int vecLength = SkSLTypeVecLength(type);
137             if (vecLength < 1) {
138                 continue;
139             }
140 
141             // Write three matching uniforms.
142             const Uniform expectations[] = {{"a", type}, {"b", type}, {"c", type}};
143             SkDEBUGCODE(mgr.setExpectedUniforms(SkSpan(expectations));)
144             mgr.write(expectations[0], kFloats);
145             mgr.write(expectations[1], kFloats);
146             mgr.write(expectations[2], kFloats);
147             SkDEBUGCODE(mgr.doneWithExpectedUniforms();)
148 
149             // Verify the uniform data packing.
150             UniformDataBlock uniformData = mgr.finishUniformDataBlock();
151             size_t elementSize = element_size(layout, type);
152             // Vec3s must be laid out as if they were vec4s.
153             size_t effectiveVecLength = (vecLength == 3) ? 4 : vecLength;
154             REPORTER_ASSERT(r, uniformData.size() == elementSize * effectiveVecLength * 3,
155                             "Layout: %s - Type: %s tight packing failed",
156                             LayoutString(layout), SkSLTypeString(type));
157             mgr.reset();
158         }
159     }
160 }
161 
DEF_GRAPHITE_TEST(UniformManagerCheckMatrixPacking,r,CtsEnforcement::kNextRelease)162 DEF_GRAPHITE_TEST(UniformManagerCheckMatrixPacking, r, CtsEnforcement::kNextRelease) {
163     // Verify that the uniform manager can pack matrices correctly.
164     for (Layout layout : kLayouts) {
165         UniformManager mgr(layout);
166 
167         for (SkSLType type : kTypes) {
168             int matrixSize = SkSLTypeMatrixSize(type);
169             if (matrixSize < 2) {
170                 continue;
171             }
172 
173             // Write three matching uniforms.
174             const Uniform expectations[] = {{"a", type}, {"b", type}, {"c", type}};
175             SkDEBUGCODE(mgr.setExpectedUniforms(SkSpan(expectations));)
176             mgr.write(expectations[0], kFloats);
177             mgr.write(expectations[1], kFloats);
178             mgr.write(expectations[2], kFloats);
179             SkDEBUGCODE(mgr.doneWithExpectedUniforms();)
180 
181             // Verify the uniform data packing.
182             UniformDataBlock uniformData = mgr.finishUniformDataBlock();
183             size_t elementSize = element_size(layout, type);
184             // In all layouts, mat3s burn 12 elements, not 9. In std140, mat2s burn 8 elements
185             // instead of 4.
186             size_t numElements;
187             if (matrixSize == 3) {
188                 numElements = 12;
189             } else if (matrixSize == 2 && layout == Layout::kStd140) {
190                 numElements = 8;
191             } else {
192                 numElements = matrixSize * matrixSize;
193             }
194             REPORTER_ASSERT(r, uniformData.size() == elementSize * numElements * 3,
195                             "Layout: %s - Type: %s matrix packing failed",
196                             LayoutString(layout), SkSLTypeString(type));
197             mgr.reset();
198         }
199     }
200 }
201 
DEF_GRAPHITE_TEST(UniformManagerCheckPaddingScalarVector,r,CtsEnforcement::kNextRelease)202 DEF_GRAPHITE_TEST(UniformManagerCheckPaddingScalarVector, r, CtsEnforcement::kNextRelease) {
203     // Verify that the uniform manager properly adds padding between pairs of scalar/vector.
204     for (Layout layout : kLayouts) {
205         UniformManager mgr(layout);
206 
207         for (SkSLType type1 : kTypes) {
208             const int vecLength1 = SkSLTypeVecLength(type1);
209             if (vecLength1 < 1) {
210                 continue;
211             }
212 
213             for (SkSLType type2 : kTypes) {
214                 const int vecLength2 = SkSLTypeVecLength(type2);
215                 if (vecLength2 < 1) {
216                     continue;
217                 }
218 
219                 // Write two scalar/vector uniforms.
220                 const Uniform expectations[] = {{"a", type1}, {"b", type2}};
221                 SkDEBUGCODE(mgr.setExpectedUniforms(SkSpan(expectations));)
222                 mgr.write(expectations[0], kFloats);
223                 mgr.write(expectations[1], kFloats);
224                 SkDEBUGCODE(mgr.doneWithExpectedUniforms();)
225 
226                 // The expected packing varies depending on the bit-widths of each element.
227                 const size_t elementSize1 = element_size(layout, type1);
228                 const size_t elementSize2 = element_size(layout, type2);
229                 if (elementSize1 == elementSize2) {
230                     // Elements in the array correspond to the element size (either 16 or 32 bits).
231                     // The expected uniform layout is listed as strings below.
232                     // A/B: uniform values.
233                     // a/b: padding as part of the uniform type (vec3 takes 4 slots)
234                     // _  : padding between uniforms for alignment
235                     static constexpr const char* kExpectedLayout[2][5][5] = {
236                         // Metal (vec3 consumes vec4 size)
237                         {{ "", "",         "",         "",         ""         },
238                          { "", "AB",       "A_BB",     "A___BBBb", "A___BBBB" },
239                          { "", "AAB_",     "AABB",     "AA__BBBb", "AA__BBBB" },
240                          { "", "AAAaB___", "AAAaBB__", "AAAaBBBb", "AAAaBBBB" },
241                          { "", "AAAAB___", "AAAABB__", "AAAABBBb", "AAAABBBB" }},
242                         // std140 and std430 (vec3 aligns to vec4, but consumes only 3 elements)
243                         {{ "", "",         "",         "",         ""         },
244                          { "", "AB",       "A_BB",     "A___BBBb", "A___BBBB" },
245                          { "", "AAB_",     "AABB",     "AA__BBBb", "AA__BBBB" },
246                          { "", "AAAB",     "AAA_BB__", "AAA_BBBb", "AAA_BBBB" },
247                          { "", "AAAAB___", "AAAABB__", "AAAABBBb", "AAAABBBB" }},
248                     };
249                     int layoutIdx = static_cast<int>(layout != Layout::kMetal);
250                     const size_t size = strlen(kExpectedLayout[layoutIdx][vecLength1][vecLength2]) *
251                                         elementSize1;
252                     UniformDataBlock uniformData = mgr.finishUniformDataBlock();
253                     REPORTER_ASSERT(r, uniformData.size() == size,
254                                     "Layout: %s - Types: %s, %s padding test failed",
255                                     LayoutString(layout),
256                                     SkSLTypeString(type1), SkSLTypeString(type2));
257                 } else if (elementSize1 == 2 && elementSize2 == 4) {
258                     // Elements in the array below correspond to 16 bits apiece.
259                     // The expected uniform layout is listed as strings below.
260                     // A/B: uniform values.
261                     // a/b: padding as part of the uniform type (vec3 takes 4 slots)
262                     // _  : padding between uniforms for alignment
263                     static constexpr const char* kExpectedLayout[5][5] = {
264                         { "", "",         "",         "",                 ""         },
265                         { "", "A_BB",     "A___BBBB", "A_______BBBBBBbb", "A_______BBBBBBBB" },
266                         { "", "AABB",     "AA__BBBB", "AA______BBBBBBbb", "AA______BBBBBBBB" },
267                         { "", "AAAaBB__", "AAAaBBBB", "AAAa____BBBBBBbb", "AAAa____BBBBBBBB" },
268                         { "", "AAAABB__", "AAAABBBB", "AAAA____BBBBBBbb", "AAAA____BBBBBBBB" },
269                     };
270                     const size_t size = strlen(kExpectedLayout[vecLength1][vecLength2]) * 2;
271                     UniformDataBlock uniformData = mgr.finishUniformDataBlock();
272                     REPORTER_ASSERT(r, uniformData.size() == size,
273                                     "Layout: %s - Types: %s, %s padding test failed",
274                                     LayoutString(layout),
275                                     SkSLTypeString(type1), SkSLTypeString(type2));
276                 } else if (elementSize1 == 4 && elementSize2 == 2) {
277                     // Elements in the array below correspond to 16 bits apiece.
278                     // The expected uniform layout is listed as strings below.
279                     // A/B: uniform values.
280                     // a/b: padding as part of the uniform type (vec3 takes 4 slots)
281                     // _  : padding between uniforms for alignment
282                     static constexpr const char* kExpectedLayout[5][5] = {
283                         { "", "", "", "", "" },
284                         { "", "AAB_",     "AABB",     "AA__BBBb", "AA__BBBB" },
285                         { "", "AAAAB___", "AAAABB__", "AAAABBBb", "AAAABBBB" },
286                         { "",
287                           "AAAAAAaaB_______",
288                           "AAAAAAaaBB______",
289                           "AAAAAAaaBBBb____",
290                           "AAAAAAaaBBBB____" },
291                         { "",
292                           "AAAAAAAAB_______",
293                           "AAAAAAAABB______",
294                           "AAAAAAAABBBb____",
295                           "AAAAAAAABBBB____" },
296                     };
297                     const size_t size = strlen(kExpectedLayout[vecLength1][vecLength2]) * 2;
298                     UniformDataBlock uniformData = mgr.finishUniformDataBlock();
299                     REPORTER_ASSERT(r, uniformData.size() == size,
300                                     "Layout: %s - Types: %s, %s padding test failed",
301                                     LayoutString(layout),
302                                     SkSLTypeString(type1), SkSLTypeString(type2));
303                 } else {
304                     ERRORF(r, "Unexpected element sizes: %zu %zu", elementSize1, elementSize2);
305                 }
306                 mgr.reset();
307             }
308         }
309     }
310 }
311 
DEF_GRAPHITE_TEST(UniformManagerCheckPaddingVectorMatrix,r,CtsEnforcement::kNextRelease)312 DEF_GRAPHITE_TEST(UniformManagerCheckPaddingVectorMatrix, r, CtsEnforcement::kNextRelease) {
313     // Verify that the uniform manager properly adds padding between vectors and matrices.
314     for (Layout layout : kLayouts) {
315         UniformManager mgr(layout);
316 
317         for (SkSLType type1 : kTypes) {
318             const int vecLength1 = SkSLTypeVecLength(type1);
319             if (vecLength1 < 1) {
320                 continue;
321             }
322 
323             for (SkSLType type2 : kTypes) {
324                 const int matSize2 = SkSLTypeMatrixSize(type2);
325                 if (matSize2 < 2) {
326                     continue;
327                 }
328 
329                 // Write the scalar/vector and matrix uniforms.
330                 const Uniform expectations[] = {{"a", type1}, {"b", type2}};
331                 SkDEBUGCODE(mgr.setExpectedUniforms(SkSpan(expectations));)
332                 mgr.write(expectations[0], kFloats);
333                 mgr.write(expectations[1], kFloats);
334                 SkDEBUGCODE(mgr.doneWithExpectedUniforms();)
335 
336                 // The expected packing varies depending on the bit-widths of each element.
337                 const size_t elementSize1 = element_size(layout, type1);
338                 const size_t elementSize2 = element_size(layout, type2);
339                 if (elementSize1 == elementSize2) {
340                     // Elements in the array correspond to the element size (32 bits).
341                     // The expected uniform layout is listed as strings below.
342                     // A/B: uniform values.
343                     // a/b: padding as part of the uniform type (vec3 takes 4 slots)
344                     // _  : padding between uniforms for alignment
345                     static constexpr const char* kExpectedLayout[2][5][5] = {
346                         // std140 layout
347                         {
348                             { "", "", "",             "",                 "" },
349                             { "", "", "A___BBbbBBbb", "A___BBBbBBBbBBBb", "A___BBBBBBBBBBBBBBBB" },
350                             { "", "", "AA__BBbbBBbb", "AA__BBBbBBBbBBBb", "AA__BBBBBBBBBBBBBBBB" },
351                             { "", "", "AAAaBBbbBBbb", "AAAaBBBbBBBbBBBb", "AAAaBBBBBBBBBBBBBBBB" },
352                             { "", "", "AAAABBbbBBbb", "AAAABBBbBBBbBBBb", "AAAABBBBBBBBBBBBBBBB" },
353                         },
354                         // All other layouts
355                         {
356                             { "", "", "",         "",                 "" },
357                             { "", "", "A_BBBB",   "A___BBBbBBBbBBBb", "A___BBBBBBBBBBBBBBBB" },
358                             { "", "", "AABBBB",   "AA__BBBbBBBbBBBb", "AA__BBBBBBBBBBBBBBBB" },
359                             { "", "", "AAAaBBBB", "AAAaBBBbBBBbBBBb", "AAAaBBBBBBBBBBBBBBBB" },
360                             { "", "", "AAAABBBB", "AAAABBBbBBBbBBBb", "AAAABBBBBBBBBBBBBBBB" },
361                         },
362                     };
363                     int layoutIdx = static_cast<int>(layout != Layout::kStd140);
364                     const size_t size = strlen(kExpectedLayout[layoutIdx][vecLength1][matSize2]) *
365                                         elementSize1;
366                     UniformDataBlock uniformData = mgr.finishUniformDataBlock();
367                     REPORTER_ASSERT(r, uniformData.size() == size,
368                                     "Layout: %s - Types: %s, %s vector-matrix padding test failed",
369                                     LayoutString(layout),
370                                     SkSLTypeString(type1), SkSLTypeString(type2));
371                 } else if (elementSize1 == 2 && elementSize2 == 4) {
372                     // Elements in the array below correspond to 16 bits apiece.
373                     // The expected uniform layout is listed as strings below.
374                     // A/B: uniform values.
375                     // a/b: padding as part of the uniform type (vec3 takes 4 slots)
376                     // _  : padding between uniforms for alignment
377                     static constexpr const char* kExpectedLayout[5][5] = {
378                             {"", "", "", "", ""},
379                             {"", "",
380                              "A___BBBBBBBB",
381                              "A_______BBBBBBbbBBBBBBbbBBBBBBbb",
382                              "A_______BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"},
383                             {"", "",
384                              "AA__BBBBBBBB",
385                              "AA______BBBBBBbbBBBBBBbbBBBBBBbb",
386                              "AA______BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"},
387                             {"", "",
388                              "AAAaBBBBBBBB",
389                              "AAAa____BBBBBBbbBBBBBBbbBBBBBBbb",
390                              "AAAa____BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"},
391                             {"", "",
392                              "AAAABBBBBBBB",
393                              "AAAA____BBBBBBbbBBBBBBbbBBBBBBbb",
394                              "AAAA____BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"},
395                     };
396                     const size_t size = strlen(kExpectedLayout[vecLength1][matSize2]) * 2;
397                     UniformDataBlock uniformData = mgr.finishUniformDataBlock();
398                     REPORTER_ASSERT(r, uniformData.size() == size,
399                                     "Layout: %s - Types: %s, %s vector-matrix padding test failed",
400                                     LayoutString(layout),
401                                     SkSLTypeString(type1), SkSLTypeString(type2));
402                 } else if (elementSize1 == 4 && elementSize2 == 2) {
403                     // Elements in the array below correspond to 16 bits apiece.
404                     // The expected uniform layout is listed as strings below.
405                     // A/B: uniform values.
406                     // a/b: padding as part of the uniform type (vec3 takes 4 slots)
407                     // _  : padding between uniforms for alignment
408                     static constexpr const char* kExpectedLayout[5][5] = {
409                             {"", "", "", "", ""},
410                             {"", "", "AABBBB",   "AA__BBBbBBBbBBBb", "AA__BBBBBBBBBBBBBBBB"},
411                             {"", "", "AAAABBBB", "AAAABBBbBBBbBBBb", "AAAABBBBBBBBBBBBBBBB"},
412                             {"", "",
413                              "AAAAAAaaBBBB____",
414                              "AAAAAAaaBBBbBBBbBBBb____",
415                              "AAAAAAaaBBBBBBBBBBBBBBBB"},
416                             {"", "",
417                              "AAAAAAAABBBB____",
418                              "AAAAAAAABBBbBBBbBBBb____",
419                              "AAAAAAAABBBBBBBBBBBBBBBB"},
420                     };
421                     const size_t size = strlen(kExpectedLayout[vecLength1][matSize2]) * 2;
422                     UniformDataBlock uniformData = mgr.finishUniformDataBlock();
423                     REPORTER_ASSERT(r, uniformData.size() == size,
424                                     "Layout: %s - Types: %s, %s vector-matrix padding test failed",
425                                     LayoutString(layout),
426                                     SkSLTypeString(type1), SkSLTypeString(type2));
427                 }
428                 mgr.reset();
429             }
430         }
431     }
432 }
433 
DEF_GRAPHITE_TEST(UniformManagerCheckPaddingMatrixVector,r,CtsEnforcement::kNextRelease)434 DEF_GRAPHITE_TEST(UniformManagerCheckPaddingMatrixVector, r, CtsEnforcement::kNextRelease) {
435     // Verify that the uniform manager properly adds padding between matrices and vectors.
436     for (Layout layout : kLayouts) {
437         UniformManager mgr(layout);
438 
439         for (SkSLType type1 : kTypes) {
440             const int matSize1 = SkSLTypeMatrixSize(type1);
441             if (matSize1 < 2) {
442                 continue;
443             }
444 
445             for (SkSLType type2 : kTypes) {
446                 const int vecLength2 = SkSLTypeVecLength(type2);
447                 if (vecLength2 < 1) {
448                     continue;
449                 }
450 
451                 // Write the scalar/vector and matrix uniforms.
452                 const Uniform expectations[] = {{"a", type1}, {"b", type2}};
453                 SkDEBUGCODE(mgr.setExpectedUniforms(SkSpan(expectations));)
454                 mgr.write(expectations[0], kFloats);
455                 mgr.write(expectations[1], kFloats);
456                 SkDEBUGCODE(mgr.doneWithExpectedUniforms();)
457 
458                 // The expected packing varies depending on the bit-widths of each element.
459                 const size_t elementSize1 = element_size(layout, type1);
460                 const size_t elementSize2 = element_size(layout, type2);
461                 if (elementSize1 == elementSize2) {
462                     // Elements in the array correspond to the element size (32 bits).
463                     // The expected uniform layout is listed as strings below.
464                     // A/B: uniform values.
465                     // a/b: padding as part of the uniform type (vec3 takes 4 slots)
466                     // _  : padding between uniforms for alignment
467                     static constexpr const char* kExpectedLayout[2][5][5] = {
468                         // std140 layout
469                         {
470                             { "", "", "", "", "" },
471                             { "", "", "", "", "" },
472                             { "", "AAaaAAaaB___", "AAaaAAaaBB__", "AAaaAAaaBBBb", "AAaaAAaaBBBB" },
473                             { "",
474                               "AAAaAAAaAAAaB___",
475                               "AAAaAAAaAAAaBB__",
476                               "AAAaAAAaAAAaBBBb",
477                               "AAAaAAAaAAAaBBBB" },
478                             { "",
479                               "AAAAAAAAAAAAAAAAB___",
480                               "AAAAAAAAAAAAAAAABB__",
481                               "AAAAAAAAAAAAAAAABBBb",
482                               "AAAAAAAAAAAAAAAABBBB" },
483                         },
484                         // All other layouts
485                         {
486                             { "", "", "", "", "" },
487                             { "", "", "", "", "" },
488                             { "", "AAAAB_", "AAAABB", "AAAABBBb", "AAAABBBB" },
489                             { "",
490                               "AAAaAAAaAAAaB___",
491                               "AAAaAAAaAAAaBB__",
492                               "AAAaAAAaAAAaBBBb",
493                               "AAAaAAAaAAAaBBBB" },
494                             { "",
495                               "AAAAAAAAAAAAAAAAB___",
496                               "AAAAAAAAAAAAAAAABB__",
497                               "AAAAAAAAAAAAAAAABBBb",
498                               "AAAAAAAAAAAAAAAABBBB" },
499                         },
500                     };
501                     int layoutIdx = static_cast<int>(layout != Layout::kStd140);
502                     const size_t size = strlen(kExpectedLayout[layoutIdx][matSize1][vecLength2]) *
503                                         elementSize1;
504                     UniformDataBlock uniformData = mgr.finishUniformDataBlock();
505                     REPORTER_ASSERT(r, uniformData.size() == size,
506                                     "Layout: %s - Types: %s, %s matrix-vector padding test failed",
507                                     LayoutString(layout),
508                                     SkSLTypeString(type1), SkSLTypeString(type2));
509                 } else if (elementSize1 == 2 && elementSize2 == 4) {
510                     // Elements in the array below correspond to 16 bits apiece.
511                     // The expected uniform layout is listed as strings below.
512                     // A/B: uniform values.
513                     // a/b: padding as part of the uniform type (vec3 takes 4 slots)
514                     // _  : padding between uniforms for alignment
515                     static constexpr const char* kExpectedLayout[5][5] = {
516                         { "", "", "", "", "" },
517                         { "", "", "", "", "" },
518                         { "", "AAAABB", "AAAABBBB", "AAAA____BBBBBBbb", "AAAA____BBBBBBBB" },
519                         { "",
520                           "AAAaAAAaAAAaBB__",
521                           "AAAaAAAaAAAaBBBB",
522                           "AAAaAAAaAAAa____BBBBBBbb",
523                           "AAAaAAAaAAAa____BBBBBBBB" },
524                         { "",
525                           "AAAAAAAAAAAAAAAABB__",
526                           "AAAAAAAAAAAAAAAABBBB",
527                           "AAAAAAAAAAAAAAAABBBBBBbb",
528                           "AAAAAAAAAAAAAAAABBBBBBBB" },
529                     };
530                     const size_t size = strlen(kExpectedLayout[matSize1][vecLength2]) * 2;
531                     UniformDataBlock uniformData = mgr.finishUniformDataBlock();
532                     REPORTER_ASSERT(r, uniformData.size() == size,
533                                     "Layout: %s - Types: %s, %s matrix-vector padding test failed",
534                                     LayoutString(layout),
535                                     SkSLTypeString(type1), SkSLTypeString(type2));
536                 } else if (elementSize1 == 4 && elementSize2 == 2) {
537                     // Elements in the array below correspond to 16 bits apiece.
538                     // The expected uniform layout is listed as strings below.
539                     // A/B: uniform values.
540                     // a/b: padding as part of the uniform type (vec3 takes 4 slots)
541                     // _  : padding between uniforms for alignment
542                     static constexpr const char* kExpectedLayout[5][5] = {
543                         { "", "", "", "", "" },
544                         { "", "", "", "", "" },
545                         { "", "AAAAAAAAB___", "AAAAAAAABB__", "AAAAAAAABBBb", "AAAAAAAABBBB" },
546                         { "",
547                           "AAAAAAaaAAAAAAaaAAAAAAaaB_______",
548                           "AAAAAAaaAAAAAAaaAAAAAAaaBB______",
549                           "AAAAAAaaAAAAAAaaAAAAAAaaBBBb____",
550                           "AAAAAAaaAAAAAAaaAAAAAAaaBBBB____" },
551                         { "",
552                           "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB_______",
553                           "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABB______",
554                           "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBb____",
555                           "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB____" },
556                     };
557                     const size_t size = strlen(kExpectedLayout[matSize1][vecLength2]) * 2;
558                     UniformDataBlock uniformData = mgr.finishUniformDataBlock();
559                     REPORTER_ASSERT(r, uniformData.size() == size,
560                                     "Layout: %s - Types: %s, %s matrix-vector padding test failed",
561                                     LayoutString(layout),
562                                     SkSLTypeString(type1), SkSLTypeString(type2));
563                 }
564                 mgr.reset();
565             }
566         }
567     }
568 }
569 
DEF_GRAPHITE_TEST(UniformManagerMetalArrayLayout,r,CtsEnforcement::kNextRelease)570 DEF_GRAPHITE_TEST(UniformManagerMetalArrayLayout, r, CtsEnforcement::kNextRelease) {
571     UniformManager mgr(Layout::kMetal);
572 
573     // Tests set up a uniform block with a single half (to force alignment) and an array of 3
574     // elements. Test every type that can appear in an array.
575     constexpr size_t kArraySize = 3;
576 
577     // Buffer large enough to hold a float4x4[3] array.
578     static constexpr uint8_t kBuffer[192] = {};
579     static const char* kExpectedLayout[] = {
580         // Each letter (A/B/a/b) corresponds to a single byte.
581         // The expected uniform layout is listed as strings below.
582         // A/B: uniform values.
583         // a/b: padding as part of the uniform type.
584         // _  : padding between uniforms for alignment.
585 
586         /* {half, float[3]}  */  "AA__BBBBBBBBBBBB",
587         /* {half, float2[3]} */  "AA______BBBBBBBBBBBBBBBBBBBBBBBB",
588         /* {half, float3[3]} */  "AA______________BBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbb",
589         /* {half, float4[3]} */  "AA______________BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB",
590         /* {half, half[3]}   */  "AABBBBBB",
591         /* {half, half2[3]}  */  "AA__BBBBBBBBBBBB",
592         /* {half, half3[3]}  */  "AA______BBBBBBbbBBBBBBbbBBBBBBbb",
593         /* {half, half4[3]}  */  "AA______BBBBBBBBBBBBBBBBBBBBBBBB",
594         /* {half, int[3]}    */  "AA__BBBBBBBBBBBB",
595         /* {half, int2[3]}   */  "AA______BBBBBBBBBBBBBBBBBBBBBBBB",
596         /* {half, int3[3]}   */  "AA______________BBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbb",
597         /* {half, int4[3]}   */  "AA______________BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB",
598 
599         /* {half, float2x2[3] */ "AA______BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB",
600         /* {half, float3x3[3] */ "AA______________"
601                                  "BBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbb"
602                                  "BBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbb"
603                                  "BBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbb",
604         /* {half, float4x4[3] */ "AA______________"
605                                  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
606                                  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
607                                  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB",
608 
609         /* {half, half2x2[3] */  "AA__BBBBBBBBBBBBBBBBBBBBBBBB",
610         /* {half, half3x3[3] */  "AA______"
611                                  "BBBBBBbbBBBBBBbbBBBBBBbb"
612                                  "BBBBBBbbBBBBBBbbBBBBBBbb"
613                                  "BBBBBBbbBBBBBBbbBBBBBBbb",
614         /* {half, half4x4[3] */  "AA______"
615                                  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
616                                  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
617                                  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB",
618     };
619     for (size_t i = 0; i < std::size(kExpectedLayout); i++) {
620         const SkSLType arrayType = kTypes[i];
621         const Uniform expectations[] = {{"a", SkSLType::kHalf}, {"b", arrayType, kArraySize}};
622 
623         SkDEBUGCODE(mgr.setExpectedUniforms(SkSpan(expectations));)
624         mgr.write(expectations[0], kHalfs);
625         mgr.write(expectations[1], kBuffer);
626         SkDEBUGCODE(mgr.doneWithExpectedUniforms();)
627 
628         const size_t expectedSize = strlen(kExpectedLayout[i]);
629         const UniformDataBlock uniformData = mgr.finishUniformDataBlock();
630         REPORTER_ASSERT(r, uniformData.size() == expectedSize,
631                         "array test %d for type %s failed - expected size: %zu, actual size: %zu",
632                         (int)i, SkSLTypeString(arrayType), expectedSize, uniformData.size());
633 
634         mgr.reset();
635     }
636 }
637 
DEF_GRAPHITE_TEST(UniformManagerStd430ArrayLayout,r,CtsEnforcement::kNextRelease)638 DEF_GRAPHITE_TEST(UniformManagerStd430ArrayLayout, r, CtsEnforcement::kNextRelease) {
639     UniformManager mgr(Layout::kStd430);
640 
641     // Tests set up a uniform block with a single half (to force alignment) and an array of 3
642     // elements. Test every type that can appear in an array.
643     constexpr size_t kArraySize = 3;
644 
645     // Buffer large enough to hold a float4x4[3] array.
646     static constexpr uint8_t kBuffer[192] = {};
647     static const char* kExpectedLayout[] = {
648         // Each letter (A/B/a/b) corresponds to a single byte.
649         // The expected uniform layout is listed as strings below.
650         // A/B: uniform values.
651         // a/b: padding as part of the uniform type.
652         // _  : padding between uniforms for alignment.
653 
654         /* {half, float[3]}  */  "AA__BBBBBBBBBBBB",
655         /* {half, float2[3]} */  "AA______BBBBBBBBBBBBBBBBBBBBBBBB",
656         /* {half, float3[3]} */  "AA______________BBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbb",
657         /* {half, float4[3]} */  "AA______________BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB",
658         /* {half, half[3]}   */  "AA__BBBBBBBBBBBB",
659         /* {half, half2[3]}  */  "AA______BBBBBBBBBBBBBBBBBBBBBBBB",
660         /* {half, half3[3]}  */  "AA______________BBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbb",
661         /* {half, half4[3]}  */  "AA______________BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB",
662         /* {half, int[3]}    */  "AA__BBBBBBBBBBBB",
663         /* {half, int2[3]}   */  "AA______BBBBBBBBBBBBBBBBBBBBBBBB",
664         /* {half, int3[3]}   */  "AA______________BBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbb",
665         /* {half, int4[3]}   */  "AA______________BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB",
666 
667         /* {half, float2x2[3] */ "AA______BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB",
668         /* {half, float3x3[3] */ "AA______________"
669                                  "BBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbb"
670                                  "BBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbb"
671                                  "BBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbb",
672         /* {half, float4x4[3] */ "AA______________"
673                                  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
674                                  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
675                                  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB",
676 
677         /* {half, half2x2[3]  */ "AA______BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB",
678         /* {half, half3x3[3]  */ "AA______________"
679                                  "BBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbb"
680                                  "BBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbb"
681                                  "BBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbb",
682         /* {half, half4x4[3]  */ "AA______________"
683                                  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
684                                  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
685                                  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB",
686     };
687     for (size_t i = 0; i < std::size(kExpectedLayout); i++) {
688         const SkSLType arrayType = kTypes[i];
689         const Uniform expectations[] = {{"a", SkSLType::kHalf}, {"b", arrayType, kArraySize}};
690 
691         SkDEBUGCODE(mgr.setExpectedUniforms(SkSpan(expectations));)
692         mgr.write(expectations[0], kHalfs);
693         mgr.write(expectations[1], kBuffer);
694         SkDEBUGCODE(mgr.doneWithExpectedUniforms();)
695 
696         const size_t expectedSize = strlen(kExpectedLayout[i]);
697         const UniformDataBlock uniformData = mgr.finishUniformDataBlock();
698         REPORTER_ASSERT(r, uniformData.size() == expectedSize,
699                         "array test %d for type %s failed - expected size: %zu, actual size: %zu",
700                         (int)i, SkSLTypeString(arrayType), expectedSize, uniformData.size());
701 
702         mgr.reset();
703     }
704 }
705 
DEF_GRAPHITE_TEST(UniformManagerStd140ArrayLayout,r,CtsEnforcement::kNextRelease)706 DEF_GRAPHITE_TEST(UniformManagerStd140ArrayLayout, r, CtsEnforcement::kNextRelease) {
707     UniformManager mgr(Layout::kStd140);
708 
709     // Tests set up a uniform block with a single half (to force alignment) and an array of 3
710     // elements. Test every type that can appear in an array.
711     constexpr size_t kArraySize = 3;
712 
713     // Buffer large enough to hold a float4x4[3] array.
714     static constexpr uint8_t kBuffer[192] = {};
715     static const char* kExpectedLayout[] = {
716         // Each letter (A/B/a/b) corresponds to a single byte.
717         // The expected uniform layout is listed as strings below.
718         // A/B: uniform values.
719         // a/b: padding as part of the uniform type.
720         // _  : padding between uniforms for alignment.
721 
722         /* {half, float[3]}  */  "AA______________BBBBbbbbbbbbbbbbBBBBbbbbbbbbbbbbBBBBbbbbbbbbbbbb",
723         /* {half, float2[3]} */  "AA______________BBBBBBBBbbbbbbbbBBBBBBBBbbbbbbbbBBBBBBBBbbbbbbbb",
724         /* {half, float3[3]} */  "AA______________BBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbb",
725         /* {half, float4[3]} */  "AA______________BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB",
726         /* {half, half[3]}   */  "AA______________BBbbbbbbbbbbbbbbBBbbbbbbbbbbbbbbBBbbbbbbbbbbbbbb",
727         /* {half, half2[3]}  */  "AA______________BBBBbbbbbbbbbbbbBBBBbbbbbbbbbbbbBBBBbbbbbbbbbbbb",
728         /* {half, half3[3]}  */  "AA______________BBBBBBbbbbbbbbbbBBBBBBbbbbbbbbbbBBBBBBbbbbbbbbbb",
729         /* {half, half4[3]}  */  "AA______________BBBBBBBBbbbbbbbbBBBBBBBBbbbbbbbbBBBBBBBBbbbbbbbb",
730         /* {half, int[3]}    */  "AA______________BBBBbbbbbbbbbbbbBBBBbbbbbbbbbbbbBBBBbbbbbbbbbbbb",
731         /* {half, int2[3]}   */  "AA______________BBBBBBBBbbbbbbbbBBBBBBBBbbbbbbbbBBBBBBBBbbbbbbbb",
732         /* {half, int3[3]}   */  "AA______________BBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbb",
733         /* {half, int4[3]}   */  "AA______________BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB",
734 
735         /* {half, float2x2[3] */ "AA______________"
736                                  "BBBBBBBBbbbbbbbbBBBBBBBBbbbbbbbb"
737                                  "BBBBBBBBbbbbbbbbBBBBBBBBbbbbbbbb"
738                                  "BBBBBBBBbbbbbbbbBBBBBBBBbbbbbbbb",
739         /* {half, float3x3[3] */ "AA______________"
740                                  "BBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbb"
741                                  "BBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbb"
742                                  "BBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbb",
743         /* {half, float4x4[3] */ "AA______________"
744                                  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
745                                  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
746                                  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB",
747 
748         /* {half, half2x2[3]  */ "AA______________"
749                                  "BBBBBBBBbbbbbbbbBBBBBBBBbbbbbbbb"
750                                  "BBBBBBBBbbbbbbbbBBBBBBBBbbbbbbbb"
751                                  "BBBBBBBBbbbbbbbbBBBBBBBBbbbbbbbb",
752         /* {half, half3x3[3]  */ "AA______________"
753                                  "BBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbb"
754                                  "BBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbb"
755                                  "BBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbbBBBBBBBBBBBBbbbb",
756         /* {half, half4x4[3]  */ "AA______________"
757                                  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
758                                  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
759                                  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB",
760     };
761     for (size_t i = 0; i < std::size(kExpectedLayout); i++) {
762         const SkSLType arrayType = kTypes[i];
763         const Uniform expectations[] = {{"a", SkSLType::kHalf}, {"b", arrayType, kArraySize}};
764 
765         SkDEBUGCODE(mgr.setExpectedUniforms(SkSpan(expectations));)
766         mgr.write(expectations[0], kHalfs);
767         mgr.write(expectations[1], kBuffer);
768         SkDEBUGCODE(mgr.doneWithExpectedUniforms();)
769 
770         const size_t expectedSize = strlen(kExpectedLayout[i]);
771         const UniformDataBlock uniformData = mgr.finishUniformDataBlock();
772         REPORTER_ASSERT(r, uniformData.size() == expectedSize,
773                         "array test %d for type %s failed - expected size: %zu, actual size: %zu",
774                         (int)i, SkSLTypeString(arrayType), expectedSize, uniformData.size());
775 
776         mgr.reset();
777     }
778 }
779 
780 // This test validates that the uniform data for matrix types get written out according to the
781 // layout expectations.
DEF_GRAPHITE_TEST(UniformManagerStd140MatrixLayoutContents,r,CtsEnforcement::kNextRelease)782 DEF_GRAPHITE_TEST(UniformManagerStd140MatrixLayoutContents, r, CtsEnforcement::kNextRelease) {
783     UniformManager mgr(Layout::kStd140);
784 
785     // float2x2, half2x2
786     for (SkSLType type : {SkSLType::kFloat2x2, SkSLType::kHalf2x2}) {
787         const Uniform expectations[] = {{"m", type}};
788         SkDEBUGCODE(mgr.setExpectedUniforms(SkSpan(expectations));)
789         mgr.write(expectations[0], kFloats);
790         SkDEBUGCODE(mgr.doneWithExpectedUniforms();)
791         const UniformDataBlock uniformData = mgr.finishUniformDataBlock();
792         REPORTER_ASSERT(r, uniformData.size() == 32,
793                         "%s layout size expected 32, got %zu",
794                         SkSLTypeString(type), uniformData.size());
795 
796         // The expected offsets of the 4 matrix elements.
797         const int kOffsets[4] = {0, 1, 4, 5};
798         const float* elements = reinterpret_cast<const float*>(uniformData.data());
799         for (size_t i = 0u; i < std::size(kOffsets); ++i) {
800             float expected = kFloats[i];
801             float el = elements[kOffsets[i]];
802             REPORTER_ASSERT(r, el == expected,
803                             "Incorrect %s element %zu - expected %f, got %f",
804                             SkSLTypeString(type), i, expected, el);
805         }
806         mgr.reset();
807     }
808 
809     // float3x3, half3x3
810     for (SkSLType type : {SkSLType::kFloat3x3, SkSLType::kHalf3x3}) {
811         const Uniform expectations[] = {{"m", type}};
812         SkDEBUGCODE(mgr.setExpectedUniforms(SkSpan(expectations));)
813         mgr.write(expectations[0], kFloats);
814         SkDEBUGCODE(mgr.doneWithExpectedUniforms();)
815         const UniformDataBlock uniformData = mgr.finishUniformDataBlock();
816         REPORTER_ASSERT(r, uniformData.size() == 48,
817                         "%s layout size expected 48, got %zu",
818                         SkSLTypeString(type), uniformData.size());
819 
820         // The expected offsets of the 9 matrix elements.
821         const int kOffsets[9] = {0, 1, 2, 4, 5, 6, 8, 9, 10};
822         const float* elements = reinterpret_cast<const float*>(uniformData.data());
823         for (size_t i = 0u; i < std::size(kOffsets); ++i) {
824             float expected = kFloats[i];
825             float el = elements[kOffsets[i]];
826             REPORTER_ASSERT(r, el == expected,
827                             "Incorrect %s element %zu - expected %f, got %f",
828                             SkSLTypeString(type), i, expected, el);
829         }
830         mgr.reset();
831     }
832 }
833 
834 // This test validates that the uniform data for matrix types get written out according to the
835 // layout expectations.
DEF_GRAPHITE_TEST(UniformManagerStd430MatrixLayoutContents,r,CtsEnforcement::kNextRelease)836 DEF_GRAPHITE_TEST(UniformManagerStd430MatrixLayoutContents, r, CtsEnforcement::kNextRelease) {
837     UniformManager mgr(Layout::kStd430);
838 
839     // float2x2, half2x2
840     for (SkSLType type : {SkSLType::kFloat2x2, SkSLType::kHalf2x2}) {
841         const Uniform expectations[] = {{"m", type}};
842         SkDEBUGCODE(mgr.setExpectedUniforms(SkSpan(expectations));)
843         mgr.write(expectations[0], kFloats);
844         SkDEBUGCODE(mgr.doneWithExpectedUniforms();)
845         const UniformDataBlock uniformData = mgr.finishUniformDataBlock();
846         REPORTER_ASSERT(r, uniformData.size() == 16,
847                         "%s layout size expected 16, got %zu",
848                         SkSLTypeString(type), uniformData.size());
849 
850         // The expected offsets of the 4 matrix elements. This uses a tighter packing than std140
851         // layout.
852         const int kOffsets[4] = {0, 1, 2, 3};
853         const float* elements = reinterpret_cast<const float*>(uniformData.data());
854         for (size_t i = 0u; i < std::size(kOffsets); ++i) {
855             float expected = kFloats[i];
856             float el = elements[kOffsets[i]];
857             REPORTER_ASSERT(r, el == expected,
858                             "Incorrect %s element %zu - expected %f, got %f",
859                             SkSLTypeString(type), i, expected, el);
860         }
861         mgr.reset();
862     }
863 
864     // float3x3, half3x3
865     for (SkSLType type : {SkSLType::kFloat3x3, SkSLType::kHalf3x3}) {
866         const Uniform expectations[] = {{"m", type}};
867         SkDEBUGCODE(mgr.setExpectedUniforms(SkSpan(expectations));)
868         mgr.write(expectations[0], kFloats);
869         SkDEBUGCODE(mgr.doneWithExpectedUniforms();)
870         const UniformDataBlock uniformData = mgr.finishUniformDataBlock();
871         REPORTER_ASSERT(r, uniformData.size() == 48,
872                         "%s layout size expected 48, got %zu",
873                         SkSLTypeString(type), uniformData.size());
874 
875         // The expected offsets of the 9 matrix elements. This is the same as std140 layout.
876         const int kOffsets[9] = {0, 1, 2, 4, 5, 6, 8, 9, 10};
877         const float* elements = reinterpret_cast<const float*>(uniformData.data());
878         for (size_t i = 0u; i < std::size(kOffsets); ++i) {
879             float expected = kFloats[i];
880             float el = elements[kOffsets[i]];
881             REPORTER_ASSERT(r, el == expected,
882                             "Incorrect %s element %zu - expected %f, got %f",
883                             SkSLTypeString(type), i, expected, el);
884         }
885         mgr.reset();
886     }
887 }
888