1 // Copyright 2019 The Dawn Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "tests/DawnTest.h"
16 
17 #include "common/Assert.h"
18 #include "common/Math.h"
19 #include "utils/ComboRenderPipelineDescriptor.h"
20 #include "utils/WGPUHelpers.h"
21 
22 // Vertex format tests all work the same way: the test will render a triangle.
23 // Each test will set up a vertex buffer, and the vertex shader will check that
24 // the vertex content is the same as what we expected. On success it outputs green,
25 // otherwise red.
26 
27 constexpr uint32_t kRTSize = 400;
28 constexpr uint32_t kVertexNum = 3;
29 
Float32ToFloat16(std::vector<float> data)30 std::vector<uint16_t> Float32ToFloat16(std::vector<float> data) {
31     std::vector<uint16_t> expectedData;
32     for (auto& element : data) {
33         expectedData.push_back(Float32ToFloat16(element));
34     }
35     return expectedData;
36 }
37 
38 template <typename destType, typename srcType>
BitCast(std::vector<srcType> data)39 std::vector<destType> BitCast(std::vector<srcType> data) {
40     std::vector<destType> expectedData;
41     for (auto& element : data) {
42         expectedData.push_back(BitCast(element));
43     }
44     return expectedData;
45 }
46 
47 class VertexFormatTest : public DawnTest {
48   protected:
SetUp()49     void SetUp() override {
50         DawnTest::SetUp();
51 
52         renderPass = utils::CreateBasicRenderPass(device, kRTSize, kRTSize);
53     }
54 
55     utils::BasicRenderPass renderPass;
56 
IsNormalizedFormat(wgpu::VertexFormat format)57     bool IsNormalizedFormat(wgpu::VertexFormat format) {
58         switch (format) {
59             case wgpu::VertexFormat::UChar2Norm:
60             case wgpu::VertexFormat::UChar4Norm:
61             case wgpu::VertexFormat::Char2Norm:
62             case wgpu::VertexFormat::Char4Norm:
63             case wgpu::VertexFormat::UShort2Norm:
64             case wgpu::VertexFormat::UShort4Norm:
65             case wgpu::VertexFormat::Short2Norm:
66             case wgpu::VertexFormat::Short4Norm:
67                 return true;
68             default:
69                 return false;
70         }
71     }
72 
IsUnsignedFormat(wgpu::VertexFormat format)73     bool IsUnsignedFormat(wgpu::VertexFormat format) {
74         switch (format) {
75             case wgpu::VertexFormat::UInt:
76             case wgpu::VertexFormat::UChar2:
77             case wgpu::VertexFormat::UChar4:
78             case wgpu::VertexFormat::UShort2:
79             case wgpu::VertexFormat::UShort4:
80             case wgpu::VertexFormat::UInt2:
81             case wgpu::VertexFormat::UInt3:
82             case wgpu::VertexFormat::UInt4:
83             case wgpu::VertexFormat::UChar2Norm:
84             case wgpu::VertexFormat::UChar4Norm:
85             case wgpu::VertexFormat::UShort2Norm:
86             case wgpu::VertexFormat::UShort4Norm:
87                 return true;
88             default:
89                 return false;
90         }
91     }
92 
IsFloatFormat(wgpu::VertexFormat format)93     bool IsFloatFormat(wgpu::VertexFormat format) {
94         switch (format) {
95             case wgpu::VertexFormat::Half2:
96             case wgpu::VertexFormat::Half4:
97             case wgpu::VertexFormat::Float:
98             case wgpu::VertexFormat::Float2:
99             case wgpu::VertexFormat::Float3:
100             case wgpu::VertexFormat::Float4:
101                 return true;
102             default:
103                 return false;
104         }
105     }
106 
IsHalfFormat(wgpu::VertexFormat format)107     bool IsHalfFormat(wgpu::VertexFormat format) {
108         switch (format) {
109             case wgpu::VertexFormat::Half2:
110             case wgpu::VertexFormat::Half4:
111                 return true;
112             default:
113                 return false;
114         }
115     }
116 
BytesPerComponents(wgpu::VertexFormat format)117     uint32_t BytesPerComponents(wgpu::VertexFormat format) {
118         switch (format) {
119             case wgpu::VertexFormat::Char2:
120             case wgpu::VertexFormat::Char4:
121             case wgpu::VertexFormat::UChar2:
122             case wgpu::VertexFormat::UChar4:
123             case wgpu::VertexFormat::UChar2Norm:
124             case wgpu::VertexFormat::UChar4Norm:
125             case wgpu::VertexFormat::Char2Norm:
126             case wgpu::VertexFormat::Char4Norm:
127                 return 1;
128             case wgpu::VertexFormat::UShort2:
129             case wgpu::VertexFormat::UShort4:
130             case wgpu::VertexFormat::Short2:
131             case wgpu::VertexFormat::Short4:
132             case wgpu::VertexFormat::UShort2Norm:
133             case wgpu::VertexFormat::UShort4Norm:
134             case wgpu::VertexFormat::Short2Norm:
135             case wgpu::VertexFormat::Short4Norm:
136             case wgpu::VertexFormat::Half2:
137             case wgpu::VertexFormat::Half4:
138                 return 2;
139             case wgpu::VertexFormat::UInt:
140             case wgpu::VertexFormat::Int:
141             case wgpu::VertexFormat::Float:
142             case wgpu::VertexFormat::UInt2:
143             case wgpu::VertexFormat::UInt3:
144             case wgpu::VertexFormat::UInt4:
145             case wgpu::VertexFormat::Int2:
146             case wgpu::VertexFormat::Int3:
147             case wgpu::VertexFormat::Int4:
148             case wgpu::VertexFormat::Float2:
149             case wgpu::VertexFormat::Float3:
150             case wgpu::VertexFormat::Float4:
151                 return 4;
152             default:
153                 DAWN_UNREACHABLE();
154         }
155     }
156 
ComponentCount(wgpu::VertexFormat format)157     uint32_t ComponentCount(wgpu::VertexFormat format) {
158         switch (format) {
159             case wgpu::VertexFormat::UInt:
160             case wgpu::VertexFormat::Int:
161             case wgpu::VertexFormat::Float:
162                 return 1;
163             case wgpu::VertexFormat::UChar2:
164             case wgpu::VertexFormat::UShort2:
165             case wgpu::VertexFormat::UInt2:
166             case wgpu::VertexFormat::Char2:
167             case wgpu::VertexFormat::Short2:
168             case wgpu::VertexFormat::Int2:
169             case wgpu::VertexFormat::UChar2Norm:
170             case wgpu::VertexFormat::Char2Norm:
171             case wgpu::VertexFormat::UShort2Norm:
172             case wgpu::VertexFormat::Short2Norm:
173             case wgpu::VertexFormat::Half2:
174             case wgpu::VertexFormat::Float2:
175                 return 2;
176             case wgpu::VertexFormat::Int3:
177             case wgpu::VertexFormat::UInt3:
178             case wgpu::VertexFormat::Float3:
179                 return 3;
180             case wgpu::VertexFormat::UChar4:
181             case wgpu::VertexFormat::UShort4:
182             case wgpu::VertexFormat::UInt4:
183             case wgpu::VertexFormat::Char4:
184             case wgpu::VertexFormat::Short4:
185             case wgpu::VertexFormat::Int4:
186             case wgpu::VertexFormat::UChar4Norm:
187             case wgpu::VertexFormat::Char4Norm:
188             case wgpu::VertexFormat::UShort4Norm:
189             case wgpu::VertexFormat::Short4Norm:
190             case wgpu::VertexFormat::Half4:
191             case wgpu::VertexFormat::Float4:
192                 return 4;
193             default:
194                 DAWN_UNREACHABLE();
195         }
196     }
197 
ShaderTypeGenerator(bool isFloat,bool isNormalized,bool isUnsigned,uint32_t componentCount)198     std::string ShaderTypeGenerator(bool isFloat,
199                                     bool isNormalized,
200                                     bool isUnsigned,
201                                     uint32_t componentCount) {
202         if (componentCount == 1) {
203             if (isFloat || isNormalized) {
204                 return "float";
205             } else if (isUnsigned) {
206                 return "uint";
207             } else {
208                 return "int";
209             }
210         } else {
211             if (isNormalized || isFloat) {
212                 return "vec" + std::to_string(componentCount);
213             } else if (isUnsigned) {
214                 return "uvec" + std::to_string(componentCount);
215             } else {
216                 return "ivec" + std::to_string(componentCount);
217             }
218         }
219     }
220 
221     // The length of vertexData is fixed to 3, it aligns to triangle vertex number
222     template <typename T>
MakeTestPipeline(wgpu::VertexFormat format,std::vector<T> & expectedData)223     wgpu::RenderPipeline MakeTestPipeline(wgpu::VertexFormat format, std::vector<T>& expectedData) {
224         bool isFloat = IsFloatFormat(format);
225         bool isNormalized = IsNormalizedFormat(format);
226         bool isUnsigned = IsUnsignedFormat(format);
227         bool isInputTypeFloat = isFloat || isNormalized;
228         bool isHalf = IsHalfFormat(format);
229         const uint16_t kNegativeZeroInHalf = 0x8000;
230 
231         uint32_t componentCount = ComponentCount(format);
232 
233         std::string variableType =
234             ShaderTypeGenerator(isFloat, isNormalized, isUnsigned, componentCount);
235         std::string expectedDataType = ShaderTypeGenerator(isFloat, isNormalized, isUnsigned, 1);
236         std::ostringstream vs;
237         vs << "#version 450\n";
238 
239         // layout(location = 0) in float/uint/int/ivecn/vecn/uvecn test;
240         vs << "layout(location = 0) in " << variableType << " test;\n";
241         vs << "layout(location = 0) out vec4 color;\n";
242         // Because x86 CPU using "extended
243         // precision"(https://en.wikipedia.org/wiki/Extended_precision) during float
244         // math(https://developer.nvidia.com/sites/default/files/akamai/cuda/files/NVIDIA-CUDA-Floating-Point.pdf),
245         // move normalization and Float16ToFloat32 into shader to generate
246         // expected value.
247         vs << "float Float16ToFloat32(uint fp16) {\n";
248         vs << "  uint magic = (uint(254) - uint(15)) << 23;\n";
249         vs << "  uint was_inf_nan = (uint(127) + uint(16)) << 23;\n";
250         vs << "  uint fp32u;\n";
251         vs << "  float fp32;\n";
252         vs << "  fp32u = (fp16 & 0x7FFF) << 13;\n";
253         vs << "  fp32 = uintBitsToFloat(fp32u) * uintBitsToFloat(magic);\n";
254         vs << "  fp32u = floatBitsToUint(fp32);\n";
255         vs << "  if (fp32 >= uintBitsToFloat(was_inf_nan)) {\n";
256         vs << "    fp32u |= uint(255) << 23;\n";
257         vs << "  }\n";
258         vs << "  fp32u |= (fp16 & 0x8000) << 16;\n";
259         vs << "  fp32 = uintBitsToFloat(fp32u);\n";
260         vs << "  return fp32;\n";
261         vs << "}\n";
262 
263         vs << "void main() {\n";
264 
265         // Hard code the triangle in the shader so that we don't have to add a vertex input for it.
266         vs << "    const vec2 pos[3] = vec2[3](vec2(-1.0f, 0.0f), vec2(-1.0f, 1.0f), vec2(0.0f, "
267               "1.0f));\n";
268         vs << "    gl_Position = vec4(pos[gl_VertexIndex], 0.0, 1.0);\n";
269 
270         // Declare expected values.
271         vs << "    " << expectedDataType << " expected[" + std::to_string(kVertexNum) + "]";
272         vs << "[" + std::to_string(componentCount) + "];\n";
273         // Assign each elements in expected values
274         // e.g. expected[0][0] = uint(1);
275         //      expected[0][1] = uint(2);
276         for (uint32_t i = 0; i < kVertexNum; ++i) {
277             for (uint32_t j = 0; j < componentCount; ++j) {
278                 vs << "    expected[" + std::to_string(i) + "][" + std::to_string(j) + "] = "
279                    << expectedDataType << "(";
280                 if (isInputTypeFloat &&
281                     std::isnan(static_cast<float>(expectedData[i * componentCount + j]))) {
282                     // Set NaN.
283                     vs << "0.0 / 0.0);\n";
284                 } else if (isNormalized) {
285                     // Move normalize operation into shader because of CPU and GPU precision
286                     // different on float math.
287                     vs << "max(float(" << std::to_string(expectedData[i * componentCount + j])
288                        << ") / " << std::to_string(std::numeric_limits<T>::max()) << ", -1.0));\n";
289                 } else if (isHalf) {
290                     // Becasue Vulkan and D3D12 handle -0.0f through uintBitsToFloat have different
291                     // result (Vulkan take -0.0f as -0.0 but D3D12 take -0.0f as 0), add workaround
292                     // for -0.0f.
293                     if (static_cast<uint16_t>(expectedData[i * componentCount + j]) ==
294                         kNegativeZeroInHalf) {
295                         vs << "-0.0f);\n";
296                     } else {
297                         vs << "Float16ToFloat32("
298                            << std::to_string(expectedData[i * componentCount + j]);
299                         vs << "));\n";
300                     }
301                 } else {
302                     vs << std::to_string(expectedData[i * componentCount + j]) << ");\n";
303                 }
304             }
305         }
306 
307         vs << "    bool success = true;\n";
308         // Perform the checks by successively ANDing a boolean
309         for (uint32_t component = 0; component < componentCount; ++component) {
310             std::string suffix = componentCount == 1 ? "" : "[" + std::to_string(component) + "]";
311             std::string testVal = "testVal" + std::to_string(component);
312             std::string expectedVal = "expectedVal" + std::to_string(component);
313             vs << "    " << expectedDataType << " " << testVal << ";\n";
314             vs << "    " << expectedDataType << " " << expectedVal << ";\n";
315             vs << "    " << testVal << " = test" << suffix << ";\n";
316             vs << "    " << expectedVal << " = expected[gl_VertexIndex]"
317                << "[" << component << "];\n";
318             if (!isInputTypeFloat) {  // Integer / unsigned integer need to match exactly.
319                 vs << "    success = success && (" << testVal << " == " << expectedVal << ");\n";
320             } else {
321                 // TODO(shaobo.yan@intel.com) : a difference of 8 ULPs is allowed in this test
322                 // because it is required on MacbookPro 11.5,AMD Radeon HD 8870M(on macOS 10.13.6),
323                 // but that it might be possible to tighten.
324                 vs << "    if (isnan(" << expectedVal << ")) {\n";
325                 vs << "        success = success && isnan(" << testVal << ");\n";
326                 vs << "    } else {\n";
327                 vs << "        uint testValFloatToUint = floatBitsToUint(" << testVal << ");\n";
328                 vs << "        uint expectedValFloatToUint = floatBitsToUint(" << expectedVal
329                    << ");\n";
330                 vs << "        success = success && max(testValFloatToUint, "
331                       "expectedValFloatToUint)";
332                 vs << "        - min(testValFloatToUint, expectedValFloatToUint) < uint(8);\n";
333                 vs << "    }\n";
334             }
335         }
336         vs << "    if (success) {\n";
337         vs << "        color = vec4(0.0f, 1.0f, 0.0f, 1.0f);\n";
338         vs << "    } else {\n";
339         vs << "        color = vec4(1.0f, 0.0f, 0.0f, 1.0f);\n";
340         vs << "    }\n";
341         vs << "}\n";
342 
343         wgpu::ShaderModule vsModule =
344             utils::CreateShaderModule(device, utils::SingleShaderStage::Vertex, vs.str().c_str());
345 
346         wgpu::ShaderModule fsModule =
347             utils::CreateShaderModule(device, utils::SingleShaderStage::Fragment, R"(
348                 #version 450
349                 layout(location = 0) in vec4 color;
350                 layout(location = 0) out vec4 fragColor;
351                 void main() {
352                     fragColor = color;
353                 })");
354 
355         uint32_t bytesPerComponents = BytesPerComponents(format);
356         uint32_t strideBytes = bytesPerComponents * componentCount;
357         // Stride size must be multiple of 4 bytes.
358         if (strideBytes % 4 != 0) {
359             strideBytes += (4 - strideBytes % 4);
360         }
361 
362         utils::ComboRenderPipelineDescriptor descriptor(device);
363         descriptor.vertexStage.module = vsModule;
364         descriptor.cFragmentStage.module = fsModule;
365         descriptor.cVertexState.vertexBufferCount = 1;
366         descriptor.cVertexState.cVertexBuffers[0].arrayStride = strideBytes;
367         descriptor.cVertexState.cVertexBuffers[0].attributeCount = 1;
368         descriptor.cVertexState.cAttributes[0].format = format;
369         descriptor.cColorStates[0].format = renderPass.colorFormat;
370 
371         return device.CreateRenderPipeline(&descriptor);
372     }
373 
374     template <typename VertexType, typename ExpectedType>
DoVertexFormatTest(wgpu::VertexFormat format,std::vector<VertexType> vertex,std::vector<ExpectedType> expectedData)375     void DoVertexFormatTest(wgpu::VertexFormat format,
376                             std::vector<VertexType> vertex,
377                             std::vector<ExpectedType> expectedData) {
378         wgpu::RenderPipeline pipeline = MakeTestPipeline(format, expectedData);
379         wgpu::Buffer vertexBuffer = utils::CreateBufferFromData(
380             device, vertex.data(), vertex.size() * sizeof(VertexType), wgpu::BufferUsage::Vertex);
381         wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
382         {
383             wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
384             pass.SetPipeline(pipeline);
385             pass.SetVertexBuffer(0, vertexBuffer);
386             pass.Draw(3);
387             pass.EndPass();
388         }
389 
390         wgpu::CommandBuffer commands = encoder.Finish();
391         queue.Submit(1, &commands);
392 
393         EXPECT_PIXEL_RGBA8_EQ(RGBA8::kGreen, renderPass.color, 0, 0);
394     }
395 };
396 
TEST_P(VertexFormatTest,UChar2)397 TEST_P(VertexFormatTest, UChar2) {
398     // TODO(cwallez@chromium.org): Failing because of a SPIRV-Cross issue.
399     // See http://crbug.com/dawn/259
400     DAWN_SKIP_TEST_IF(IsMetal() && IsIntel());
401 
402     std::vector<uint8_t> vertexData = {
403         std::numeric_limits<uint8_t>::max(),
404         0,
405         0,  // padding two bytes for stride
406         0,
407         std::numeric_limits<uint8_t>::min(),
408         2,
409         0,
410         0,  // padding two bytes for stride
411         200,
412         201,
413         0,
414         0  // padding two bytes for buffer copy
415     };
416 
417     std::vector<uint8_t> expectedData = {
418         std::numeric_limits<uint8_t>::max(), 0, std::numeric_limits<uint8_t>::min(), 2, 200, 201,
419     };
420 
421     DoVertexFormatTest(wgpu::VertexFormat::UChar2, vertexData, expectedData);
422 }
423 
TEST_P(VertexFormatTest,UChar4)424 TEST_P(VertexFormatTest, UChar4) {
425     // TODO(cwallez@chromium.org): Failing because of a SPIRV-Cross issue.
426     // See http://crbug.com/dawn/259
427     DAWN_SKIP_TEST_IF(IsMetal() && IsIntel());
428 
429     std::vector<uint8_t> vertexData = {
430         std::numeric_limits<uint8_t>::max(),
431         0,
432         1,
433         2,
434         std::numeric_limits<uint8_t>::min(),
435         2,
436         3,
437         4,
438         200,
439         201,
440         202,
441         203,
442     };
443 
444     DoVertexFormatTest(wgpu::VertexFormat::UChar4, vertexData, vertexData);
445 }
446 
TEST_P(VertexFormatTest,Char2)447 TEST_P(VertexFormatTest, Char2) {
448     // TODO(cwallez@chromium.org): Failing because of a SPIRV-Cross issue.
449     // See http://crbug.com/dawn/259
450     DAWN_SKIP_TEST_IF(IsMetal() && IsIntel());
451 
452     std::vector<int8_t> vertexData = {
453         std::numeric_limits<int8_t>::max(),
454         0,
455         0,  // padding two bytes for stride
456         0,
457         std::numeric_limits<int8_t>::min(),
458         -2,
459         0,  // padding two bytes for stride
460         0,
461         120,
462         -121,
463         0,
464         0  // padding two bytes for buffer copy
465     };
466 
467     std::vector<int8_t> expectedData = {
468         std::numeric_limits<int8_t>::max(), 0, std::numeric_limits<int8_t>::min(), -2, 120, -121,
469     };
470 
471     DoVertexFormatTest(wgpu::VertexFormat::Char2, vertexData, expectedData);
472 }
473 
TEST_P(VertexFormatTest,Char4)474 TEST_P(VertexFormatTest, Char4) {
475     // TODO(cwallez@chromium.org): Failing because of a SPIRV-Cross issue.
476     // See http://crbug.com/dawn/259
477     DAWN_SKIP_TEST_IF(IsMetal() && IsIntel());
478 
479     std::vector<int8_t> vertexData = {
480         std::numeric_limits<int8_t>::max(),
481         0,
482         -1,
483         2,
484         std::numeric_limits<int8_t>::min(),
485         -2,
486         3,
487         4,
488         120,
489         -121,
490         122,
491         -123,
492     };
493 
494     DoVertexFormatTest(wgpu::VertexFormat::Char4, vertexData, vertexData);
495 }
496 
TEST_P(VertexFormatTest,UChar2Norm)497 TEST_P(VertexFormatTest, UChar2Norm) {
498     // TODO(cwallez@chromium.org): Failing because of a SPIRV-Cross issue.
499     // See http://crbug.com/dawn/259
500     DAWN_SKIP_TEST_IF(IsMetal() && IsIntel());
501 
502     std::vector<uint8_t> vertexData = {
503         std::numeric_limits<uint8_t>::max(),
504         std::numeric_limits<uint8_t>::min(),
505         0,  // padding two bytes for stride
506         0,
507         std::numeric_limits<uint8_t>::max() / 2u,
508         std::numeric_limits<uint8_t>::min() / 2u,
509         0,  // padding two bytes for stride
510         0,
511         200,
512         201,
513         0,
514         0  // padding two bytes for buffer copy
515     };
516 
517     std::vector<uint8_t> expectedData = {std::numeric_limits<uint8_t>::max(),
518                                          std::numeric_limits<uint8_t>::min(),
519                                          std::numeric_limits<uint8_t>::max() / 2u,
520                                          std::numeric_limits<uint8_t>::min() / 2u,
521                                          200,
522                                          201};
523 
524     DoVertexFormatTest(wgpu::VertexFormat::UChar2Norm, vertexData, expectedData);
525 }
526 
TEST_P(VertexFormatTest,UChar4Norm)527 TEST_P(VertexFormatTest, UChar4Norm) {
528     // TODO(cwallez@chromium.org): Failing because of a SPIRV-Cross issue.
529     // See http://crbug.com/dawn/259
530     DAWN_SKIP_TEST_IF(IsMetal() && IsIntel());
531 
532     std::vector<uint8_t> vertexData = {std::numeric_limits<uint8_t>::max(),
533                                        std::numeric_limits<uint8_t>::min(),
534                                        0,
535                                        0,
536                                        std::numeric_limits<uint8_t>::max() / 2u,
537                                        std::numeric_limits<uint8_t>::min() / 2u,
538                                        0,
539                                        0,
540                                        200,
541                                        201,
542                                        202,
543                                        203};
544 
545     DoVertexFormatTest(wgpu::VertexFormat::UChar4Norm, vertexData, vertexData);
546 }
547 
TEST_P(VertexFormatTest,Char2Norm)548 TEST_P(VertexFormatTest, Char2Norm) {
549     // TODO(cwallez@chromium.org): Failing because of a SPIRV-Cross issue.
550     // See http://crbug.com/dawn/259
551     DAWN_SKIP_TEST_IF(IsMetal() && IsIntel());
552 
553     std::vector<int8_t> vertexData = {
554         std::numeric_limits<int8_t>::max(),
555         std::numeric_limits<int8_t>::min(),
556         0,  // padding two bytes for stride
557         0,
558         std::numeric_limits<int8_t>::max() / 2,
559         std::numeric_limits<int8_t>::min() / 2,
560         0,  // padding two bytes for stride
561         0,
562         120,
563         -121,
564         0,
565         0  // padding two bytes for buffer copy
566     };
567 
568     std::vector<int8_t> expectedData = {
569         std::numeric_limits<int8_t>::max(),
570         std::numeric_limits<int8_t>::min(),
571         std::numeric_limits<int8_t>::max() / 2,
572         std::numeric_limits<int8_t>::min() / 2,
573         120,
574         -121,
575     };
576 
577     DoVertexFormatTest(wgpu::VertexFormat::Char2Norm, vertexData, expectedData);
578 }
579 
TEST_P(VertexFormatTest,Char4Norm)580 TEST_P(VertexFormatTest, Char4Norm) {
581     // TODO(cwallez@chromium.org): Failing because of a SPIRV-Cross issue.
582     // See http://crbug.com/dawn/259
583     DAWN_SKIP_TEST_IF(IsMetal() && IsIntel());
584 
585     std::vector<int8_t> vertexData = {std::numeric_limits<int8_t>::max(),
586                                       std::numeric_limits<int8_t>::min(),
587                                       0,
588                                       0,
589                                       std::numeric_limits<int8_t>::max() / 2,
590                                       std::numeric_limits<int8_t>::min() / 2,
591                                       -2,
592                                       2,
593                                       120,
594                                       -120,
595                                       102,
596                                       -123};
597 
598     DoVertexFormatTest(wgpu::VertexFormat::Char4Norm, vertexData, vertexData);
599 }
600 
TEST_P(VertexFormatTest,UShort2)601 TEST_P(VertexFormatTest, UShort2) {
602     // TODO(cwallez@chromium.org): Failing because of a SPIRV-Cross issue.
603     // See http://crbug.com/dawn/259
604     DAWN_SKIP_TEST_IF(IsMetal() && IsIntel());
605 
606     std::vector<uint16_t> vertexData = {std::numeric_limits<uint16_t>::max(),
607                                         0,
608                                         std::numeric_limits<uint16_t>::min(),
609                                         2,
610                                         65432,
611                                         4890};
612 
613     DoVertexFormatTest(wgpu::VertexFormat::UShort2, vertexData, vertexData);
614 }
615 
TEST_P(VertexFormatTest,UShort4)616 TEST_P(VertexFormatTest, UShort4) {
617     // TODO(cwallez@chromium.org): Failing because of a SPIRV-Cross issue.
618     // See http://crbug.com/dawn/259
619     DAWN_SKIP_TEST_IF(IsMetal() && IsIntel());
620 
621     std::vector<uint16_t> vertexData = {
622         std::numeric_limits<uint16_t>::max(),
623         std::numeric_limits<uint8_t>::max(),
624         1,
625         2,
626         std::numeric_limits<uint16_t>::min(),
627         2,
628         3,
629         4,
630         65520,
631         65521,
632         3435,
633         3467,
634     };
635 
636     DoVertexFormatTest(wgpu::VertexFormat::UShort4, vertexData, vertexData);
637 }
638 
TEST_P(VertexFormatTest,Short2)639 TEST_P(VertexFormatTest, Short2) {
640     // TODO(cwallez@chromium.org): Failing because of a SPIRV-Cross issue.
641     // See http://crbug.com/dawn/259
642     DAWN_SKIP_TEST_IF(IsMetal() && IsIntel());
643 
644     std::vector<int16_t> vertexData = {std::numeric_limits<int16_t>::max(),
645                                        0,
646                                        std::numeric_limits<int16_t>::min(),
647                                        -2,
648                                        3876,
649                                        -3948};
650 
651     DoVertexFormatTest(wgpu::VertexFormat::Short2, vertexData, vertexData);
652 }
653 
TEST_P(VertexFormatTest,Short4)654 TEST_P(VertexFormatTest, Short4) {
655     // TODO(cwallez@chromium.org): Failing because of a SPIRV-Cross issue.
656     // See http://crbug.com/dawn/259
657     DAWN_SKIP_TEST_IF(IsMetal() && IsIntel());
658 
659     std::vector<int16_t> vertexData = {
660         std::numeric_limits<int16_t>::max(),
661         0,
662         -1,
663         2,
664         std::numeric_limits<int16_t>::min(),
665         -2,
666         3,
667         4,
668         24567,
669         -23545,
670         4350,
671         -2987,
672     };
673 
674     DoVertexFormatTest(wgpu::VertexFormat::Short4, vertexData, vertexData);
675 }
676 
TEST_P(VertexFormatTest,UShort2Norm)677 TEST_P(VertexFormatTest, UShort2Norm) {
678     // TODO(cwallez@chromium.org): Failing because of a SPIRV-Cross issue.
679     // See http://crbug.com/dawn/259
680     DAWN_SKIP_TEST_IF(IsMetal() && IsIntel());
681 
682     std::vector<uint16_t> vertexData = {std::numeric_limits<uint16_t>::max(),
683                                         std::numeric_limits<uint16_t>::min(),
684                                         std::numeric_limits<uint16_t>::max() / 2u,
685                                         std::numeric_limits<uint16_t>::min() / 2u,
686                                         3456,
687                                         6543};
688 
689     DoVertexFormatTest(wgpu::VertexFormat::UShort2Norm, vertexData, vertexData);
690 }
691 
TEST_P(VertexFormatTest,UShort4Norm)692 TEST_P(VertexFormatTest, UShort4Norm) {
693     // TODO(cwallez@chromium.org): Failing because of a SPIRV-Cross issue.
694     // See http://crbug.com/dawn/259
695     DAWN_SKIP_TEST_IF(IsMetal() && IsIntel());
696 
697     std::vector<uint16_t> vertexData = {std::numeric_limits<uint16_t>::max(),
698                                         std::numeric_limits<uint16_t>::min(),
699                                         0,
700                                         0,
701                                         std::numeric_limits<uint16_t>::max() / 2u,
702                                         std::numeric_limits<uint16_t>::min() / 2u,
703                                         0,
704                                         0,
705                                         2987,
706                                         3055,
707                                         2987,
708                                         2987};
709 
710     DoVertexFormatTest(wgpu::VertexFormat::UShort4Norm, vertexData, vertexData);
711 }
712 
TEST_P(VertexFormatTest,Short2Norm)713 TEST_P(VertexFormatTest, Short2Norm) {
714     // TODO(cwallez@chromium.org): Failing because of a SPIRV-Cross issue.
715     // See http://crbug.com/dawn/259
716     DAWN_SKIP_TEST_IF(IsMetal() && IsIntel());
717 
718     std::vector<int16_t> vertexData = {std::numeric_limits<int16_t>::max(),
719                                        std::numeric_limits<int16_t>::min(),
720                                        std::numeric_limits<int16_t>::max() / 2,
721                                        std::numeric_limits<int16_t>::min() / 2,
722                                        4987,
723                                        -6789};
724 
725     DoVertexFormatTest(wgpu::VertexFormat::Short2Norm, vertexData, vertexData);
726 }
727 
TEST_P(VertexFormatTest,Short4Norm)728 TEST_P(VertexFormatTest, Short4Norm) {
729     // TODO(cwallez@chromium.org): Failing because of a SPIRV-Cross issue.
730     // See http://crbug.com/dawn/259
731     DAWN_SKIP_TEST_IF(IsMetal() && IsIntel());
732 
733     std::vector<int16_t> vertexData = {std::numeric_limits<int16_t>::max(),
734                                        std::numeric_limits<int16_t>::min(),
735                                        0,
736                                        0,
737                                        std::numeric_limits<int16_t>::max() / 2,
738                                        std::numeric_limits<int16_t>::min() / 2,
739                                        -2,
740                                        2,
741                                        2890,
742                                        -29011,
743                                        20432,
744                                        -2083};
745 
746     DoVertexFormatTest(wgpu::VertexFormat::Short4Norm, vertexData, vertexData);
747 }
748 
TEST_P(VertexFormatTest,Half2)749 TEST_P(VertexFormatTest, Half2) {
750     // TODO(cwallez@chromium.org): Failing because of a SPIRV-Cross issue.
751     // See http://crbug.com/dawn/259
752     DAWN_SKIP_TEST_IF(IsMetal() && IsIntel());
753 
754     std::vector<uint16_t> vertexData =
755         Float32ToFloat16(std::vector<float>({14.8f, -0.0f, 22.5f, 1.3f, +0.0f, -24.8f}));
756 
757     DoVertexFormatTest(wgpu::VertexFormat::Half2, vertexData, vertexData);
758 }
759 
TEST_P(VertexFormatTest,Half4)760 TEST_P(VertexFormatTest, Half4) {
761     // TODO(cwallez@chromium.org): Failing because of a SPIRV-Cross issue.
762     // See http://crbug.com/dawn/259
763     DAWN_SKIP_TEST_IF(IsMetal() && IsIntel());
764 
765     std::vector<uint16_t> vertexData = Float32ToFloat16(std::vector<float>(
766         {+0.0f, -16.8f, 18.2f, -0.0f, 12.5f, 1.3f, 14.8f, -12.4f, 22.5f, -48.8f, 47.4f, -24.8f}));
767 
768     DoVertexFormatTest(wgpu::VertexFormat::Half4, vertexData, vertexData);
769 }
770 
TEST_P(VertexFormatTest,Float)771 TEST_P(VertexFormatTest, Float) {
772     // TODO(cwallez@chromium.org): Failing because of a SPIRV-Cross issue.
773     // See http://crbug.com/dawn/259
774     DAWN_SKIP_TEST_IF(IsMetal() && IsIntel());
775 
776     std::vector<float> vertexData = {1.3f, +0.0f, -0.0f};
777 
778     DoVertexFormatTest(wgpu::VertexFormat::Float, vertexData, vertexData);
779 
780     vertexData = std::vector<float>{+1.0f, -1.0f, 18.23f};
781 
782     DoVertexFormatTest(wgpu::VertexFormat::Float, vertexData, vertexData);
783 }
784 
TEST_P(VertexFormatTest,Float2)785 TEST_P(VertexFormatTest, Float2) {
786     // TODO(cwallez@chromium.org): Failing because of a SPIRV-Cross issue.
787     // See http://crbug.com/dawn/259
788     DAWN_SKIP_TEST_IF(IsMetal() && IsIntel());
789 
790     std::vector<float> vertexData = {18.23f, -0.0f, +0.0f, +1.0f, 1.3f, -1.0f};
791 
792     DoVertexFormatTest(wgpu::VertexFormat::Float2, vertexData, vertexData);
793 }
794 
TEST_P(VertexFormatTest,Float3)795 TEST_P(VertexFormatTest, Float3) {
796     // TODO(cwallez@chromium.org): Failing because of a SPIRV-Cross issue.
797     // See http://crbug.com/dawn/259
798     DAWN_SKIP_TEST_IF(IsMetal() && IsIntel());
799 
800     std::vector<float> vertexData = {
801         +0.0f, -1.0f, -0.0f, 1.0f, 1.3f, 99.45f, 23.6f, -81.2f, 55.0f,
802     };
803 
804     DoVertexFormatTest(wgpu::VertexFormat::Float3, vertexData, vertexData);
805 }
806 
TEST_P(VertexFormatTest,Float4)807 TEST_P(VertexFormatTest, Float4) {
808     // TODO(cwallez@chromium.org): Failing because of a SPIRV-Cross issue.
809     // See http://crbug.com/dawn/259
810     DAWN_SKIP_TEST_IF(IsMetal() && IsIntel());
811 
812     std::vector<float> vertexData = {
813         19.2f, -19.3f, +0.0f, 1.0f, -0.0f, 1.0f, 1.3f, -1.0f, 13.078f, 21.1965f, -1.1f, -1.2f,
814     };
815 
816     DoVertexFormatTest(wgpu::VertexFormat::Float4, vertexData, vertexData);
817 }
818 
TEST_P(VertexFormatTest,UInt)819 TEST_P(VertexFormatTest, UInt) {
820     // TODO(cwallez@chromium.org): Failing because of a SPIRV-Cross issue.
821     // See http://crbug.com/dawn/259
822     DAWN_SKIP_TEST_IF(IsMetal() && IsIntel());
823 
824     std::vector<uint32_t> vertexData = {std::numeric_limits<uint32_t>::max(),
825                                         std::numeric_limits<uint16_t>::max(),
826                                         std::numeric_limits<uint8_t>::max()};
827 
828     DoVertexFormatTest(wgpu::VertexFormat::UInt, vertexData, vertexData);
829 }
830 
TEST_P(VertexFormatTest,UInt2)831 TEST_P(VertexFormatTest, UInt2) {
832     // TODO(cwallez@chromium.org): Failing because of a SPIRV-Cross issue.
833     // See http://crbug.com/dawn/259
834     DAWN_SKIP_TEST_IF(IsMetal() && IsIntel());
835 
836     std::vector<uint32_t> vertexData = {std::numeric_limits<uint32_t>::max(), 32,
837                                         std::numeric_limits<uint16_t>::max(), 64,
838                                         std::numeric_limits<uint8_t>::max(),  128};
839 
840     DoVertexFormatTest(wgpu::VertexFormat::UInt2, vertexData, vertexData);
841 }
842 
TEST_P(VertexFormatTest,UInt3)843 TEST_P(VertexFormatTest, UInt3) {
844     // TODO(cwallez@chromium.org): Failing because of a SPIRV-Cross issue.
845     // See http://crbug.com/dawn/259
846     DAWN_SKIP_TEST_IF(IsMetal() && IsIntel());
847 
848     std::vector<uint32_t> vertexData = {std::numeric_limits<uint32_t>::max(), 32,   64,
849                                         std::numeric_limits<uint16_t>::max(), 164,  128,
850                                         std::numeric_limits<uint8_t>::max(),  1283, 256};
851 
852     DoVertexFormatTest(wgpu::VertexFormat::UInt3, vertexData, vertexData);
853 }
854 
TEST_P(VertexFormatTest,UInt4)855 TEST_P(VertexFormatTest, UInt4) {
856     // TODO(cwallez@chromium.org): Failing because of a SPIRV-Cross issue.
857     // See http://crbug.com/dawn/259
858     DAWN_SKIP_TEST_IF(IsMetal() && IsIntel());
859 
860     std::vector<uint32_t> vertexData = {std::numeric_limits<uint32_t>::max(), 32,   64,  5460,
861                                         std::numeric_limits<uint16_t>::max(), 164,  128, 0,
862                                         std::numeric_limits<uint8_t>::max(),  1283, 256, 4567};
863 
864     DoVertexFormatTest(wgpu::VertexFormat::UInt4, vertexData, vertexData);
865 }
866 
TEST_P(VertexFormatTest,Int)867 TEST_P(VertexFormatTest, Int) {
868     // TODO(cwallez@chromium.org): Failing because of a SPIRV-Cross issue.
869     // See http://crbug.com/dawn/259
870     DAWN_SKIP_TEST_IF(IsMetal() && IsIntel());
871 
872     std::vector<int32_t> vertexData = {std::numeric_limits<int32_t>::max(),
873                                        std::numeric_limits<int32_t>::min(),
874                                        std::numeric_limits<int8_t>::max()};
875 
876     DoVertexFormatTest(wgpu::VertexFormat::Int, vertexData, vertexData);
877 }
878 
TEST_P(VertexFormatTest,Int2)879 TEST_P(VertexFormatTest, Int2) {
880     // TODO(cwallez@chromium.org): Failing because of a SPIRV-Cross issue.
881     // See http://crbug.com/dawn/259
882     DAWN_SKIP_TEST_IF(IsMetal() && IsIntel());
883 
884     std::vector<int32_t> vertexData = {
885         std::numeric_limits<int32_t>::max(), std::numeric_limits<int32_t>::min(),
886         std::numeric_limits<int16_t>::max(), std::numeric_limits<int16_t>::min(),
887         std::numeric_limits<int8_t>::max(),  std::numeric_limits<int8_t>::min()};
888 
889     DoVertexFormatTest(wgpu::VertexFormat::Int2, vertexData, vertexData);
890 }
891 
TEST_P(VertexFormatTest,Int3)892 TEST_P(VertexFormatTest, Int3) {
893     // TODO(cwallez@chromium.org): Failing because of a SPIRV-Cross issue.
894     // See http://crbug.com/dawn/259
895     DAWN_SKIP_TEST_IF(IsMetal() && IsIntel());
896 
897     std::vector<int32_t> vertexData = {
898         std::numeric_limits<int32_t>::max(), std::numeric_limits<int32_t>::min(), 64,
899         std::numeric_limits<int16_t>::max(), std::numeric_limits<int16_t>::min(), 128,
900         std::numeric_limits<int8_t>::max(),  std::numeric_limits<int8_t>::min(),  256};
901 
902     DoVertexFormatTest(wgpu::VertexFormat::Int3, vertexData, vertexData);
903 }
904 
TEST_P(VertexFormatTest,Int4)905 TEST_P(VertexFormatTest, Int4) {
906     // TODO(cwallez@chromium.org): Failing because of a SPIRV-Cross issue.
907     // See http://crbug.com/dawn/259
908     DAWN_SKIP_TEST_IF(IsMetal() && IsIntel());
909 
910     std::vector<int32_t> vertexData = {
911         std::numeric_limits<int32_t>::max(), std::numeric_limits<int32_t>::min(), 64,   -5460,
912         std::numeric_limits<int16_t>::max(), std::numeric_limits<int16_t>::min(), -128, 0,
913         std::numeric_limits<int8_t>::max(),  std::numeric_limits<int8_t>::min(),  256,  -4567};
914 
915     DoVertexFormatTest(wgpu::VertexFormat::Int4, vertexData, vertexData);
916 }
917 
918 DAWN_INSTANTIATE_TEST(VertexFormatTest,
919                       D3D12Backend(),
920                       MetalBackend(),
921                       OpenGLBackend(),
922                       VulkanBackend());
923