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 = 1;
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 // TODO(crbug.com/dawn/259): Failing because of a SPIRV-Cross issue.
53 DAWN_SUPPRESS_TEST_IF(IsMetal() && IsIntel());
54
55 renderPass = utils::CreateBasicRenderPass(device, kRTSize, kRTSize);
56 }
57
58 utils::BasicRenderPass renderPass;
59
IsNormalizedFormat(wgpu::VertexFormat format)60 bool IsNormalizedFormat(wgpu::VertexFormat format) {
61 switch (format) {
62 case wgpu::VertexFormat::Unorm8x2:
63 case wgpu::VertexFormat::Unorm8x4:
64 case wgpu::VertexFormat::Snorm8x2:
65 case wgpu::VertexFormat::Snorm8x4:
66 case wgpu::VertexFormat::Unorm16x2:
67 case wgpu::VertexFormat::Unorm16x4:
68 case wgpu::VertexFormat::Snorm16x2:
69 case wgpu::VertexFormat::Snorm16x4:
70 return true;
71 default:
72 return false;
73 }
74 }
75
IsUnsignedFormat(wgpu::VertexFormat format)76 bool IsUnsignedFormat(wgpu::VertexFormat format) {
77 switch (format) {
78 case wgpu::VertexFormat::Uint32:
79 case wgpu::VertexFormat::Uint8x2:
80 case wgpu::VertexFormat::Uint8x4:
81 case wgpu::VertexFormat::Uint16x2:
82 case wgpu::VertexFormat::Uint16x4:
83 case wgpu::VertexFormat::Uint32x2:
84 case wgpu::VertexFormat::Uint32x3:
85 case wgpu::VertexFormat::Uint32x4:
86 case wgpu::VertexFormat::Unorm8x2:
87 case wgpu::VertexFormat::Unorm8x4:
88 case wgpu::VertexFormat::Unorm16x2:
89 case wgpu::VertexFormat::Unorm16x4:
90 return true;
91 default:
92 return false;
93 }
94 }
95
IsFloatFormat(wgpu::VertexFormat format)96 bool IsFloatFormat(wgpu::VertexFormat format) {
97 switch (format) {
98 case wgpu::VertexFormat::Float16x2:
99 case wgpu::VertexFormat::Float16x4:
100 case wgpu::VertexFormat::Float32:
101 case wgpu::VertexFormat::Float32x2:
102 case wgpu::VertexFormat::Float32x3:
103 case wgpu::VertexFormat::Float32x4:
104 return true;
105 default:
106 return false;
107 }
108 }
109
IsHalfFormat(wgpu::VertexFormat format)110 bool IsHalfFormat(wgpu::VertexFormat format) {
111 switch (format) {
112 case wgpu::VertexFormat::Float16x2:
113 case wgpu::VertexFormat::Float16x4:
114 return true;
115 default:
116 return false;
117 }
118 }
119
BytesPerComponents(wgpu::VertexFormat format)120 uint32_t BytesPerComponents(wgpu::VertexFormat format) {
121 switch (format) {
122 case wgpu::VertexFormat::Uint8x2:
123 case wgpu::VertexFormat::Uint8x4:
124 case wgpu::VertexFormat::Sint8x2:
125 case wgpu::VertexFormat::Sint8x4:
126 case wgpu::VertexFormat::Unorm8x2:
127 case wgpu::VertexFormat::Unorm8x4:
128 case wgpu::VertexFormat::Snorm8x2:
129 case wgpu::VertexFormat::Snorm8x4:
130 return 1;
131 case wgpu::VertexFormat::Uint16x2:
132 case wgpu::VertexFormat::Uint16x4:
133 case wgpu::VertexFormat::Unorm16x2:
134 case wgpu::VertexFormat::Unorm16x4:
135 case wgpu::VertexFormat::Sint16x2:
136 case wgpu::VertexFormat::Sint16x4:
137 case wgpu::VertexFormat::Snorm16x2:
138 case wgpu::VertexFormat::Snorm16x4:
139 case wgpu::VertexFormat::Float16x2:
140 case wgpu::VertexFormat::Float16x4:
141 return 2;
142 case wgpu::VertexFormat::Float32:
143 case wgpu::VertexFormat::Float32x2:
144 case wgpu::VertexFormat::Float32x3:
145 case wgpu::VertexFormat::Float32x4:
146 case wgpu::VertexFormat::Uint32:
147 case wgpu::VertexFormat::Uint32x2:
148 case wgpu::VertexFormat::Uint32x3:
149 case wgpu::VertexFormat::Uint32x4:
150 case wgpu::VertexFormat::Sint32:
151 case wgpu::VertexFormat::Sint32x2:
152 case wgpu::VertexFormat::Sint32x3:
153 case wgpu::VertexFormat::Sint32x4:
154 return 4;
155 default:
156 DAWN_UNREACHABLE();
157 }
158 }
159
ComponentCount(wgpu::VertexFormat format)160 uint32_t ComponentCount(wgpu::VertexFormat format) {
161 switch (format) {
162 case wgpu::VertexFormat::Float32:
163 case wgpu::VertexFormat::Uint32:
164 case wgpu::VertexFormat::Sint32:
165 return 1;
166 case wgpu::VertexFormat::Uint8x2:
167 case wgpu::VertexFormat::Sint8x2:
168 case wgpu::VertexFormat::Unorm8x2:
169 case wgpu::VertexFormat::Snorm8x2:
170 case wgpu::VertexFormat::Uint16x2:
171 case wgpu::VertexFormat::Sint16x2:
172 case wgpu::VertexFormat::Unorm16x2:
173 case wgpu::VertexFormat::Snorm16x2:
174 case wgpu::VertexFormat::Float16x2:
175 case wgpu::VertexFormat::Float32x2:
176 case wgpu::VertexFormat::Uint32x2:
177 case wgpu::VertexFormat::Sint32x2:
178 return 2;
179 case wgpu::VertexFormat::Float32x3:
180 case wgpu::VertexFormat::Uint32x3:
181 case wgpu::VertexFormat::Sint32x3:
182 return 3;
183 case wgpu::VertexFormat::Uint8x4:
184 case wgpu::VertexFormat::Sint8x4:
185 case wgpu::VertexFormat::Unorm8x4:
186 case wgpu::VertexFormat::Snorm8x4:
187 case wgpu::VertexFormat::Uint16x4:
188 case wgpu::VertexFormat::Sint16x4:
189 case wgpu::VertexFormat::Unorm16x4:
190 case wgpu::VertexFormat::Snorm16x4:
191 case wgpu::VertexFormat::Float16x4:
192 case wgpu::VertexFormat::Float32x4:
193 case wgpu::VertexFormat::Uint32x4:
194 case wgpu::VertexFormat::Sint32x4:
195 return 4;
196 default:
197 DAWN_UNREACHABLE();
198 }
199 }
200
ShaderTypeGenerator(bool isFloat,bool isNormalized,bool isUnsigned,uint32_t componentCount)201 std::string ShaderTypeGenerator(bool isFloat,
202 bool isNormalized,
203 bool isUnsigned,
204 uint32_t componentCount) {
205 std::string base;
206 if (isFloat || isNormalized) {
207 base = "f32";
208 } else if (isUnsigned) {
209 base = "u32";
210 } else {
211 base = "i32";
212 }
213
214 if (componentCount == 1) {
215 return base;
216 }
217
218 return "vec" + std::to_string(componentCount) + "<" + base + ">";
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
237 std::ostringstream vs;
238 vs << "struct VertexIn {\n";
239 vs << " [[location(0)]] test : " << variableType << ";\n";
240 vs << " [[builtin(vertex_index)]] VertexIndex : u32;\n";
241 vs << "};\n";
242
243 // Because x86 CPU using "extended
244 // precision"(https://en.wikipedia.org/wiki/Extended_precision) during float
245 // math(https://developer.nvidia.com/sites/default/files/akamai/cuda/files/NVIDIA-CUDA-Floating-Point.pdf),
246 // move normalization and Float16ToFloat32 into shader to generate
247 // expected value.
248 vs << R"(
249 fn Float16ToFloat32(fp16 : u32) -> f32 {
250 let magic : u32 = (254u - 15u) << 23u;
251 let was_inf_nan : u32 = (127u + 16u) << 23u;
252 var fp32u : u32 = (fp16 & 0x7FFFu) << 13u;
253 let fp32 : f32 = bitcast<f32>(fp32u) * bitcast<f32>(magic);
254 fp32u = bitcast<u32>(fp32);
255 if (fp32 >= bitcast<f32>(was_inf_nan)) {
256 fp32u = fp32u | (255u << 23u);
257 }
258 fp32u = fp32u | ((fp16 & 0x8000u) << 16u);
259 return bitcast<f32>(fp32u);
260 }
261
262 struct VertexOut {
263 [[location(0)]] color : vec4<f32>;
264 [[builtin(position)]] position : vec4<f32>;
265 };
266
267 [[stage(vertex)]]
268 fn main(input : VertexIn) -> VertexOut {
269 var pos = array<vec2<f32>, 3>(
270 vec2<f32>(-1.0, -1.0),
271 vec2<f32>( 2.0, 0.0),
272 vec2<f32>( 0.0, 2.0));
273 var output : VertexOut;
274 output.position = vec4<f32>(pos[input.VertexIndex], 0.0, 1.0);
275 )";
276
277 // Declare expected values.
278 vs << "var expected : array<array<" << expectedDataType << ", "
279 << std::to_string(componentCount) << ">, " << std::to_string(kVertexNum) << ">;";
280 // Assign each elements in expected values
281 // e.g. expected[0][0] = u32(1u);
282 // expected[0][1] = u32(2u);
283 for (uint32_t i = 0; i < kVertexNum; ++i) {
284 for (uint32_t j = 0; j < componentCount; ++j) {
285 vs << " expected[" + std::to_string(i) + "][" + std::to_string(j) + "] = "
286 << expectedDataType << "(";
287 if (isInputTypeFloat &&
288 std::isnan(static_cast<float>(expectedData[i * componentCount + j]))) {
289 // Set NaN.
290 vs << "0.0 / 0.0);\n";
291 } else if (isNormalized) {
292 // Move normalize operation into shader because of CPU and GPU precision
293 // different on float math.
294 vs << "max(f32(" << std::to_string(expectedData[i * componentCount + j])
295 << ") / " << std::to_string(std::numeric_limits<T>::max())
296 << ".0 , -1.0));\n";
297 } else if (isHalf) {
298 // Becasue Vulkan and D3D12 handle -0.0f through bitcast have different
299 // result (Vulkan take -0.0f as -0.0 but D3D12 take -0.0f as 0), add workaround
300 // for -0.0f.
301 if (static_cast<uint16_t>(expectedData[i * componentCount + j]) ==
302 kNegativeZeroInHalf) {
303 vs << "-0.0);\n";
304 } else {
305 vs << "Float16ToFloat32(u32("
306 << std::to_string(expectedData[i * componentCount + j]) << ")));\n";
307 }
308 } else if (isUnsigned) {
309 vs << std::to_string(expectedData[i * componentCount + j]) << "u);\n";
310 } else {
311 vs << std::to_string(expectedData[i * componentCount + j]) << ");\n";
312 }
313 }
314 }
315
316 vs << " var success : bool = true;\n";
317 // Perform the checks by successively ANDing a boolean
318 for (uint32_t component = 0; component < componentCount; ++component) {
319 std::string suffix = componentCount == 1 ? "" : "[" + std::to_string(component) + "]";
320 std::string testVal = "testVal" + std::to_string(component);
321 std::string expectedVal = "expectedVal" + std::to_string(component);
322 vs << " var " << testVal << " : " << expectedDataType << ";\n";
323 vs << " var " << expectedVal << " : " << expectedDataType << ";\n";
324 vs << " " << testVal << " = input.test" << suffix << ";\n";
325 vs << " " << expectedVal << " = expected[input.VertexIndex]"
326 << "[" << component << "];\n";
327 if (!isInputTypeFloat) { // Integer / unsigned integer need to match exactly.
328 vs << " success = success && (" << testVal << " == " << expectedVal << ");\n";
329 } else {
330 // TODO(shaobo.yan@intel.com) : a difference of 8 ULPs is allowed in this test
331 // because it is required on MacbookPro 11.5,AMD Radeon HD 8870M(on macOS 10.13.6),
332 // but that it might be possible to tighten.
333 vs << " if (isNan(" << expectedVal << ")) {\n";
334 vs << " success = success && isNan(" << testVal << ");\n";
335 vs << " } else {\n";
336 vs << " let testValFloatToUint : u32 = bitcast<u32>(" << testVal << ");\n";
337 vs << " let expectedValFloatToUint : u32 = bitcast<u32>(" << expectedVal
338 << ");\n";
339 vs << " success = success && max(testValFloatToUint, "
340 "expectedValFloatToUint)";
341 vs << " - min(testValFloatToUint, expectedValFloatToUint) < 8u;\n";
342 vs << " }\n";
343 }
344 }
345 vs << R"(
346 if (success) {
347 output.color = vec4<f32>(0.0, 1.0, 0.0, 1.0);
348 } else {
349 output.color = vec4<f32>(1.0, 0.0, 0.0, 1.0);
350 }
351 return output;
352 })";
353
354 wgpu::ShaderModule vsModule = utils::CreateShaderModule(device, vs.str().c_str());
355 wgpu::ShaderModule fsModule = utils::CreateShaderModule(device, R"(
356 [[stage(fragment)]]
357 fn main([[location(0)]] color : vec4<f32>) -> [[location(0)]] vec4<f32> {
358 return color;
359 })");
360
361 uint32_t bytesPerComponents = BytesPerComponents(format);
362 uint32_t strideBytes = bytesPerComponents * componentCount;
363 // Stride size must be multiple of 4 bytes.
364 if (strideBytes % 4 != 0) {
365 strideBytes += (4 - strideBytes % 4);
366 }
367
368 utils::ComboRenderPipelineDescriptor descriptor;
369 descriptor.vertex.module = vsModule;
370 descriptor.cFragment.module = fsModule;
371 descriptor.vertex.bufferCount = 1;
372 descriptor.cBuffers[0].arrayStride = strideBytes;
373 descriptor.cBuffers[0].attributeCount = 1;
374 descriptor.cAttributes[0].format = format;
375 descriptor.cTargets[0].format = renderPass.colorFormat;
376
377 return device.CreateRenderPipeline(&descriptor);
378 }
379
380 template <typename VertexType, typename ExpectedType>
DoVertexFormatTest(wgpu::VertexFormat format,std::vector<VertexType> vertex,std::vector<ExpectedType> expectedData)381 void DoVertexFormatTest(wgpu::VertexFormat format,
382 std::vector<VertexType> vertex,
383 std::vector<ExpectedType> expectedData) {
384 wgpu::RenderPipeline pipeline = MakeTestPipeline(format, expectedData);
385 wgpu::Buffer vertexBuffer = utils::CreateBufferFromData(
386 device, vertex.data(), vertex.size() * sizeof(VertexType), wgpu::BufferUsage::Vertex);
387 wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
388 {
389 wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
390 pass.SetPipeline(pipeline);
391 pass.SetVertexBuffer(0, vertexBuffer);
392 pass.Draw(3);
393 pass.EndPass();
394 }
395
396 wgpu::CommandBuffer commands = encoder.Finish();
397 queue.Submit(1, &commands);
398
399 EXPECT_PIXEL_RGBA8_EQ(RGBA8::kGreen, renderPass.color, 0, 0);
400 }
401 };
402
TEST_P(VertexFormatTest,Uint8x2)403 TEST_P(VertexFormatTest, Uint8x2) {
404 std::vector<uint8_t> vertexData = {
405 std::numeric_limits<uint8_t>::max(),
406 0,
407 0, // padding two bytes for stride
408 0,
409 std::numeric_limits<uint8_t>::min(),
410 2,
411 0,
412 0, // padding two bytes for stride
413 200,
414 201,
415 0,
416 0 // padding two bytes for buffer copy
417 };
418
419 std::vector<uint8_t> expectedData = {
420 std::numeric_limits<uint8_t>::max(), 0, std::numeric_limits<uint8_t>::min(), 2, 200, 201,
421 };
422
423 DoVertexFormatTest(wgpu::VertexFormat::Uint8x2, vertexData, expectedData);
424 }
425
TEST_P(VertexFormatTest,Uint8x4)426 TEST_P(VertexFormatTest, Uint8x4) {
427 std::vector<uint8_t> vertexData = {
428 std::numeric_limits<uint8_t>::max(),
429 0,
430 1,
431 2,
432 std::numeric_limits<uint8_t>::min(),
433 2,
434 3,
435 4,
436 200,
437 201,
438 202,
439 203,
440 };
441
442 DoVertexFormatTest(wgpu::VertexFormat::Uint8x4, vertexData, vertexData);
443 }
444
TEST_P(VertexFormatTest,Sint8x2)445 TEST_P(VertexFormatTest, Sint8x2) {
446 std::vector<int8_t> vertexData = {
447 std::numeric_limits<int8_t>::max(),
448 0,
449 0, // padding two bytes for stride
450 0,
451 std::numeric_limits<int8_t>::min(),
452 -2,
453 0, // padding two bytes for stride
454 0,
455 120,
456 -121,
457 0,
458 0 // padding two bytes for buffer copy
459 };
460
461 std::vector<int8_t> expectedData = {
462 std::numeric_limits<int8_t>::max(), 0, std::numeric_limits<int8_t>::min(), -2, 120, -121,
463 };
464
465 DoVertexFormatTest(wgpu::VertexFormat::Sint8x2, vertexData, expectedData);
466 }
467
TEST_P(VertexFormatTest,Sint8x4)468 TEST_P(VertexFormatTest, Sint8x4) {
469 std::vector<int8_t> vertexData = {
470 std::numeric_limits<int8_t>::max(),
471 0,
472 -1,
473 2,
474 std::numeric_limits<int8_t>::min(),
475 -2,
476 3,
477 4,
478 120,
479 -121,
480 122,
481 -123,
482 };
483
484 DoVertexFormatTest(wgpu::VertexFormat::Sint8x4, vertexData, vertexData);
485 }
486
TEST_P(VertexFormatTest,Unorm8x2)487 TEST_P(VertexFormatTest, Unorm8x2) {
488 std::vector<uint8_t> vertexData = {
489 std::numeric_limits<uint8_t>::max(),
490 std::numeric_limits<uint8_t>::min(),
491 0, // padding two bytes for stride
492 0,
493 std::numeric_limits<uint8_t>::max() / 2u,
494 std::numeric_limits<uint8_t>::min() / 2u,
495 0, // padding two bytes for stride
496 0,
497 200,
498 201,
499 0,
500 0 // padding two bytes for buffer copy
501 };
502
503 std::vector<uint8_t> expectedData = {std::numeric_limits<uint8_t>::max(),
504 std::numeric_limits<uint8_t>::min(),
505 std::numeric_limits<uint8_t>::max() / 2u,
506 std::numeric_limits<uint8_t>::min() / 2u,
507 200,
508 201};
509
510 DoVertexFormatTest(wgpu::VertexFormat::Unorm8x2, vertexData, expectedData);
511 }
512
TEST_P(VertexFormatTest,Unorm8x4)513 TEST_P(VertexFormatTest, Unorm8x4) {
514 std::vector<uint8_t> vertexData = {std::numeric_limits<uint8_t>::max(),
515 std::numeric_limits<uint8_t>::min(),
516 0,
517 0,
518 std::numeric_limits<uint8_t>::max() / 2u,
519 std::numeric_limits<uint8_t>::min() / 2u,
520 0,
521 0,
522 200,
523 201,
524 202,
525 203};
526
527 DoVertexFormatTest(wgpu::VertexFormat::Unorm8x4, vertexData, vertexData);
528 }
529
TEST_P(VertexFormatTest,Snorm8x2)530 TEST_P(VertexFormatTest, Snorm8x2) {
531 std::vector<int8_t> vertexData = {
532 std::numeric_limits<int8_t>::max(),
533 std::numeric_limits<int8_t>::min(),
534 0, // padding two bytes for stride
535 0,
536 std::numeric_limits<int8_t>::max() / 2,
537 std::numeric_limits<int8_t>::min() / 2,
538 0, // padding two bytes for stride
539 0,
540 120,
541 -121,
542 0,
543 0 // padding two bytes for buffer copy
544 };
545
546 std::vector<int8_t> expectedData = {
547 std::numeric_limits<int8_t>::max(),
548 std::numeric_limits<int8_t>::min(),
549 std::numeric_limits<int8_t>::max() / 2,
550 std::numeric_limits<int8_t>::min() / 2,
551 120,
552 -121,
553 };
554
555 DoVertexFormatTest(wgpu::VertexFormat::Snorm8x2, vertexData, expectedData);
556 }
557
TEST_P(VertexFormatTest,Snorm8x4)558 TEST_P(VertexFormatTest, Snorm8x4) {
559 std::vector<int8_t> vertexData = {std::numeric_limits<int8_t>::max(),
560 std::numeric_limits<int8_t>::min(),
561 0,
562 0,
563 std::numeric_limits<int8_t>::max() / 2,
564 std::numeric_limits<int8_t>::min() / 2,
565 -2,
566 2,
567 120,
568 -120,
569 102,
570 -123};
571
572 DoVertexFormatTest(wgpu::VertexFormat::Snorm8x4, vertexData, vertexData);
573 }
574
TEST_P(VertexFormatTest,Uint16x2)575 TEST_P(VertexFormatTest, Uint16x2) {
576 std::vector<uint16_t> vertexData = {std::numeric_limits<uint16_t>::max(),
577 0,
578 std::numeric_limits<uint16_t>::min(),
579 2,
580 65432,
581 4890};
582
583 DoVertexFormatTest(wgpu::VertexFormat::Uint16x2, vertexData, vertexData);
584 }
585
TEST_P(VertexFormatTest,Uint16x4)586 TEST_P(VertexFormatTest, Uint16x4) {
587 std::vector<uint16_t> vertexData = {
588 std::numeric_limits<uint16_t>::max(),
589 std::numeric_limits<uint8_t>::max(),
590 1,
591 2,
592 std::numeric_limits<uint16_t>::min(),
593 2,
594 3,
595 4,
596 65520,
597 65521,
598 3435,
599 3467,
600 };
601
602 DoVertexFormatTest(wgpu::VertexFormat::Uint16x4, vertexData, vertexData);
603 }
604
TEST_P(VertexFormatTest,Sint16x2)605 TEST_P(VertexFormatTest, Sint16x2) {
606 std::vector<int16_t> vertexData = {std::numeric_limits<int16_t>::max(),
607 0,
608 std::numeric_limits<int16_t>::min(),
609 -2,
610 3876,
611 -3948};
612
613 DoVertexFormatTest(wgpu::VertexFormat::Sint16x2, vertexData, vertexData);
614 }
615
TEST_P(VertexFormatTest,Sint16x4)616 TEST_P(VertexFormatTest, Sint16x4) {
617 std::vector<int16_t> vertexData = {
618 std::numeric_limits<int16_t>::max(),
619 0,
620 -1,
621 2,
622 std::numeric_limits<int16_t>::min(),
623 -2,
624 3,
625 4,
626 24567,
627 -23545,
628 4350,
629 -2987,
630 };
631
632 DoVertexFormatTest(wgpu::VertexFormat::Sint16x4, vertexData, vertexData);
633 }
634
TEST_P(VertexFormatTest,Unorm16x2)635 TEST_P(VertexFormatTest, Unorm16x2) {
636 std::vector<uint16_t> vertexData = {std::numeric_limits<uint16_t>::max(),
637 std::numeric_limits<uint16_t>::min(),
638 std::numeric_limits<uint16_t>::max() / 2u,
639 std::numeric_limits<uint16_t>::min() / 2u,
640 3456,
641 6543};
642
643 DoVertexFormatTest(wgpu::VertexFormat::Unorm16x2, vertexData, vertexData);
644 }
645
TEST_P(VertexFormatTest,Unorm16x4)646 TEST_P(VertexFormatTest, Unorm16x4) {
647 std::vector<uint16_t> vertexData = {std::numeric_limits<uint16_t>::max(),
648 std::numeric_limits<uint16_t>::min(),
649 0,
650 0,
651 std::numeric_limits<uint16_t>::max() / 2u,
652 std::numeric_limits<uint16_t>::min() / 2u,
653 0,
654 0,
655 2987,
656 3055,
657 2987,
658 2987};
659
660 DoVertexFormatTest(wgpu::VertexFormat::Unorm16x4, vertexData, vertexData);
661 }
662
TEST_P(VertexFormatTest,Snorm16x2)663 TEST_P(VertexFormatTest, Snorm16x2) {
664 std::vector<int16_t> vertexData = {std::numeric_limits<int16_t>::max(),
665 std::numeric_limits<int16_t>::min(),
666 std::numeric_limits<int16_t>::max() / 2,
667 std::numeric_limits<int16_t>::min() / 2,
668 4987,
669 -6789};
670
671 DoVertexFormatTest(wgpu::VertexFormat::Snorm16x2, vertexData, vertexData);
672 }
673
TEST_P(VertexFormatTest,Snorm16x4)674 TEST_P(VertexFormatTest, Snorm16x4) {
675 std::vector<int16_t> vertexData = {std::numeric_limits<int16_t>::max(),
676 std::numeric_limits<int16_t>::min(),
677 0,
678 0,
679 std::numeric_limits<int16_t>::max() / 2,
680 std::numeric_limits<int16_t>::min() / 2,
681 -2,
682 2,
683 2890,
684 -29011,
685 20432,
686 -2083};
687
688 DoVertexFormatTest(wgpu::VertexFormat::Snorm16x4, vertexData, vertexData);
689 }
690
TEST_P(VertexFormatTest,Float16x2)691 TEST_P(VertexFormatTest, Float16x2) {
692 // Fails on NVIDIA's Vulkan drivers on CQ but passes locally.
693 DAWN_SUPPRESS_TEST_IF(IsVulkan() && IsNvidia());
694
695 std::vector<uint16_t> vertexData =
696 Float32ToFloat16(std::vector<float>({14.8f, -0.0f, 22.5f, 1.3f, +0.0f, -24.8f}));
697
698 DoVertexFormatTest(wgpu::VertexFormat::Float16x2, vertexData, vertexData);
699 }
700
TEST_P(VertexFormatTest,Float16x4)701 TEST_P(VertexFormatTest, Float16x4) {
702 // Fails on NVIDIA's Vulkan drivers on CQ but passes locally.
703 DAWN_SUPPRESS_TEST_IF(IsVulkan() && IsNvidia());
704
705 std::vector<uint16_t> vertexData = Float32ToFloat16(std::vector<float>(
706 {+0.0f, -16.8f, 18.2f, -0.0f, 12.5f, 1.3f, 14.8f, -12.4f, 22.5f, -48.8f, 47.4f, -24.8f}));
707
708 DoVertexFormatTest(wgpu::VertexFormat::Float16x4, vertexData, vertexData);
709 }
710
TEST_P(VertexFormatTest,Float32)711 TEST_P(VertexFormatTest, Float32) {
712 std::vector<float> vertexData = {1.3f, +0.0f, -0.0f};
713
714 DoVertexFormatTest(wgpu::VertexFormat::Float32, vertexData, vertexData);
715
716 vertexData = std::vector<float>{+1.0f, -1.0f, 18.23f};
717
718 DoVertexFormatTest(wgpu::VertexFormat::Float32, vertexData, vertexData);
719 }
720
TEST_P(VertexFormatTest,Float32x2)721 TEST_P(VertexFormatTest, Float32x2) {
722 // Fails on NVIDIA's Vulkan drivers on CQ but passes locally.
723 DAWN_SUPPRESS_TEST_IF(IsVulkan() && IsNvidia());
724
725 std::vector<float> vertexData = {18.23f, -0.0f, +0.0f, +1.0f, 1.3f, -1.0f};
726
727 DoVertexFormatTest(wgpu::VertexFormat::Float32x2, vertexData, vertexData);
728 }
729
TEST_P(VertexFormatTest,Float32x3)730 TEST_P(VertexFormatTest, Float32x3) {
731 // Fails on NVIDIA's Vulkan drivers on CQ but passes locally.
732 DAWN_SUPPRESS_TEST_IF(IsVulkan() && IsNvidia());
733
734 std::vector<float> vertexData = {
735 +0.0f, -1.0f, -0.0f, 1.0f, 1.3f, 99.45f, 23.6f, -81.2f, 55.0f,
736 };
737
738 DoVertexFormatTest(wgpu::VertexFormat::Float32x3, vertexData, vertexData);
739 }
740
TEST_P(VertexFormatTest,Float32x4)741 TEST_P(VertexFormatTest, Float32x4) {
742 std::vector<float> vertexData = {
743 19.2f, -19.3f, +0.0f, 1.0f, -0.0f, 1.0f, 1.3f, -1.0f, 13.078f, 21.1965f, -1.1f, -1.2f,
744 };
745
746 DoVertexFormatTest(wgpu::VertexFormat::Float32x4, vertexData, vertexData);
747 }
748
TEST_P(VertexFormatTest,Uint32)749 TEST_P(VertexFormatTest, Uint32) {
750 std::vector<uint32_t> vertexData = {std::numeric_limits<uint32_t>::max(),
751 std::numeric_limits<uint16_t>::max(),
752 std::numeric_limits<uint8_t>::max()};
753
754 DoVertexFormatTest(wgpu::VertexFormat::Uint32, vertexData, vertexData);
755 }
756
TEST_P(VertexFormatTest,Uint32x2)757 TEST_P(VertexFormatTest, Uint32x2) {
758 std::vector<uint32_t> vertexData = {std::numeric_limits<uint32_t>::max(), 32,
759 std::numeric_limits<uint16_t>::max(), 64,
760 std::numeric_limits<uint8_t>::max(), 128};
761
762 DoVertexFormatTest(wgpu::VertexFormat::Uint32x2, vertexData, vertexData);
763 }
764
TEST_P(VertexFormatTest,Uint32x3)765 TEST_P(VertexFormatTest, Uint32x3) {
766 std::vector<uint32_t> vertexData = {std::numeric_limits<uint32_t>::max(), 32, 64,
767 std::numeric_limits<uint16_t>::max(), 164, 128,
768 std::numeric_limits<uint8_t>::max(), 1283, 256};
769
770 DoVertexFormatTest(wgpu::VertexFormat::Uint32x3, vertexData, vertexData);
771 }
772
TEST_P(VertexFormatTest,Uint32x4)773 TEST_P(VertexFormatTest, Uint32x4) {
774 std::vector<uint32_t> vertexData = {std::numeric_limits<uint32_t>::max(), 32, 64, 5460,
775 std::numeric_limits<uint16_t>::max(), 164, 128, 0,
776 std::numeric_limits<uint8_t>::max(), 1283, 256, 4567};
777
778 DoVertexFormatTest(wgpu::VertexFormat::Uint32x4, vertexData, vertexData);
779 }
780
TEST_P(VertexFormatTest,Sint32)781 TEST_P(VertexFormatTest, Sint32) {
782 std::vector<int32_t> vertexData = {std::numeric_limits<int32_t>::max(),
783 std::numeric_limits<int32_t>::min(),
784 std::numeric_limits<int8_t>::max()};
785
786 DoVertexFormatTest(wgpu::VertexFormat::Sint32, vertexData, vertexData);
787 }
788
TEST_P(VertexFormatTest,Sint32x2)789 TEST_P(VertexFormatTest, Sint32x2) {
790 std::vector<int32_t> vertexData = {
791 std::numeric_limits<int32_t>::max(), std::numeric_limits<int32_t>::min(),
792 std::numeric_limits<int16_t>::max(), std::numeric_limits<int16_t>::min(),
793 std::numeric_limits<int8_t>::max(), std::numeric_limits<int8_t>::min()};
794
795 DoVertexFormatTest(wgpu::VertexFormat::Sint32x2, vertexData, vertexData);
796 }
797
TEST_P(VertexFormatTest,Sint32x3)798 TEST_P(VertexFormatTest, Sint32x3) {
799 std::vector<int32_t> vertexData = {
800 std::numeric_limits<int32_t>::max(), std::numeric_limits<int32_t>::min(), 64,
801 std::numeric_limits<int16_t>::max(), std::numeric_limits<int16_t>::min(), 128,
802 std::numeric_limits<int8_t>::max(), std::numeric_limits<int8_t>::min(), 256};
803
804 DoVertexFormatTest(wgpu::VertexFormat::Sint32x3, vertexData, vertexData);
805 }
806
TEST_P(VertexFormatTest,Sint32x4)807 TEST_P(VertexFormatTest, Sint32x4) {
808 std::vector<int32_t> vertexData = {
809 std::numeric_limits<int32_t>::max(), std::numeric_limits<int32_t>::min(), 64, -5460,
810 std::numeric_limits<int16_t>::max(), std::numeric_limits<int16_t>::min(), -128, 0,
811 std::numeric_limits<int8_t>::max(), std::numeric_limits<int8_t>::min(), 256, -4567};
812
813 DoVertexFormatTest(wgpu::VertexFormat::Sint32x4, vertexData, vertexData);
814 }
815
816 DAWN_INSTANTIATE_TEST(VertexFormatTest,
817 D3D12Backend(),
818 MetalBackend(),
819 OpenGLBackend(),
820 OpenGLESBackend(),
821 VulkanBackend());
822