• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 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 "utils/ComboRenderPipelineDescriptor.h"
19 #include "utils/WGPUHelpers.h"
20 
21 constexpr uint32_t kRTSize = 400;
22 
23 class IndexFormatTest : public DawnTest {
24   protected:
SetUp()25     void SetUp() override {
26         DawnTest::SetUp();
27 
28         renderPass = utils::CreateBasicRenderPass(device, kRTSize, kRTSize);
29     }
30 
31     utils::BasicRenderPass renderPass;
32 
MakeTestPipeline(wgpu::IndexFormat format,wgpu::PrimitiveTopology primitiveTopology=wgpu::PrimitiveTopology::TriangleStrip)33     wgpu::RenderPipeline MakeTestPipeline(wgpu::IndexFormat format,
34         wgpu::PrimitiveTopology primitiveTopology = wgpu::PrimitiveTopology::TriangleStrip) {
35         wgpu::ShaderModule vsModule = utils::CreateShaderModule(device, R"(
36             struct VertexIn {
37                 [[location(0)]] pos : vec4<f32>;
38                 [[builtin(vertex_index)]] idx : u32;
39             };
40 
41             [[stage(vertex)]] fn main(input : VertexIn) -> [[builtin(position)]] vec4<f32> {
42                 // 0xFFFFFFFE is a designated invalid index used by some tests.
43                 if (input.idx == 0xFFFFFFFEu) {
44                     return vec4<f32>(0.0, 0.0, 0.0, 1.0);
45                 }
46                 return input.pos;
47             })");
48 
49         wgpu::ShaderModule fsModule = utils::CreateShaderModule(device, R"(
50             [[stage(fragment)]] fn main() -> [[location(0)]] vec4<f32> {
51                 return vec4<f32>(0.0, 1.0, 0.0, 1.0);
52             })");
53 
54         utils::ComboRenderPipelineDescriptor descriptor;
55         descriptor.vertex.module = vsModule;
56         descriptor.cFragment.module = fsModule;
57         descriptor.primitive.topology = primitiveTopology;
58         descriptor.primitive.stripIndexFormat = format;
59         descriptor.vertex.bufferCount = 1;
60         descriptor.cBuffers[0].arrayStride = 4 * sizeof(float);
61         descriptor.cBuffers[0].attributeCount = 1;
62         descriptor.cAttributes[0].format = wgpu::VertexFormat::Float32x4;
63         descriptor.cTargets[0].format = renderPass.colorFormat;
64 
65         return device.CreateRenderPipeline(&descriptor);
66     }
67 };
68 
69 // Test that the Uint32 index format is correctly interpreted
TEST_P(IndexFormatTest,Uint32)70 TEST_P(IndexFormatTest, Uint32) {
71     wgpu::RenderPipeline pipeline = MakeTestPipeline(wgpu::IndexFormat::Uint32);
72 
73     wgpu::Buffer vertexBuffer = utils::CreateBufferFromData<float>(
74         device, wgpu::BufferUsage::Vertex,
75         {-1.0f, -1.0f, 0.0f, 1.0f,  // Note Vertices[0] = Vertices[1]
76          -1.0f, -1.0f, 0.0f, 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f});
77     // If this is interpreted as Uint16, then it would be 0, 1, 0, ... and would draw nothing.
78     wgpu::Buffer indexBuffer =
79         utils::CreateBufferFromData<uint32_t>(device, wgpu::BufferUsage::Index, {1, 2, 3});
80 
81     wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
82     {
83         wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
84         pass.SetPipeline(pipeline);
85         pass.SetVertexBuffer(0, vertexBuffer);
86         pass.SetIndexBuffer(indexBuffer, wgpu::IndexFormat::Uint32);
87         pass.DrawIndexed(3);
88         pass.EndPass();
89     }
90 
91     wgpu::CommandBuffer commands = encoder.Finish();
92     queue.Submit(1, &commands);
93 
94     EXPECT_PIXEL_RGBA8_EQ(RGBA8::kGreen, renderPass.color, 100, 300);
95 }
96 
97 // Test that the Uint16 index format is correctly interpreted
TEST_P(IndexFormatTest,Uint16)98 TEST_P(IndexFormatTest, Uint16) {
99     wgpu::RenderPipeline pipeline = MakeTestPipeline(wgpu::IndexFormat::Uint16);
100 
101     wgpu::Buffer vertexBuffer = utils::CreateBufferFromData<float>(
102         device, wgpu::BufferUsage::Vertex,
103         {-1.0f, -1.0f, 0.0f, 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f});
104     // If this is interpreted as uint32, it will have index 1 and 2 be both 0 and render nothing
105     wgpu::Buffer indexBuffer =
106         utils::CreateBufferFromData<uint16_t>(device, wgpu::BufferUsage::Index, {1, 2, 0, 0, 0, 0});
107 
108     wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
109     {
110         wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
111         pass.SetPipeline(pipeline);
112         pass.SetVertexBuffer(0, vertexBuffer);
113         pass.SetIndexBuffer(indexBuffer, wgpu::IndexFormat::Uint16);
114         pass.DrawIndexed(3);
115         pass.EndPass();
116     }
117 
118     wgpu::CommandBuffer commands = encoder.Finish();
119     queue.Submit(1, &commands);
120 
121     EXPECT_PIXEL_RGBA8_EQ(RGBA8::kGreen, renderPass.color, 100, 300);
122 }
123 
124 // Test that the index format used is the format of the last set pipeline. This is to
125 // prevent a case in D3D12 where the index format would be captured from the last
126 // pipeline on SetIndexBuffer.
TEST_P(IndexFormatTest,ChangePipelineAfterSetIndexBuffer)127 TEST_P(IndexFormatTest, ChangePipelineAfterSetIndexBuffer) {
128     wgpu::RenderPipeline pipeline32 = MakeTestPipeline(wgpu::IndexFormat::Uint32);
129     wgpu::RenderPipeline pipeline16 = MakeTestPipeline(wgpu::IndexFormat::Uint16);
130 
131     wgpu::Buffer vertexBuffer = utils::CreateBufferFromData<float>(
132         device, wgpu::BufferUsage::Vertex,
133         {-1.0f, -1.0f, 0.0f, 1.0f,  // Note Vertices[0] = Vertices[1]
134          -1.0f, -1.0f, 0.0f, 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f});
135     // If this is interpreted as Uint16, then it would be 0, 1, 0, ... and would draw nothing.
136     wgpu::Buffer indexBuffer =
137         utils::CreateBufferFromData<uint32_t>(device, wgpu::BufferUsage::Index, {1, 2, 3});
138 
139     wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
140     {
141         wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
142         pass.SetPipeline(pipeline16);
143         pass.SetVertexBuffer(0, vertexBuffer);
144         pass.SetIndexBuffer(indexBuffer, wgpu::IndexFormat::Uint32);
145         pass.SetPipeline(pipeline32);
146         pass.DrawIndexed(3);
147         pass.EndPass();
148     }
149 
150     wgpu::CommandBuffer commands = encoder.Finish();
151     queue.Submit(1, &commands);
152 
153     EXPECT_PIXEL_RGBA8_EQ(RGBA8::kGreen, renderPass.color, 100, 300);
154 }
155 
156 // Test that setting the index buffer before the pipeline works, this is important
157 // for backends where the index format is passed inside the call to SetIndexBuffer
158 // because it needs to be done lazily (to query the format from the last pipeline).
TEST_P(IndexFormatTest,SetIndexBufferBeforeSetPipeline)159 TEST_P(IndexFormatTest, SetIndexBufferBeforeSetPipeline) {
160     wgpu::RenderPipeline pipeline = MakeTestPipeline(wgpu::IndexFormat::Uint32);
161 
162     wgpu::Buffer vertexBuffer = utils::CreateBufferFromData<float>(
163         device, wgpu::BufferUsage::Vertex,
164         {-1.0f, -1.0f, 0.0f, 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f});
165     wgpu::Buffer indexBuffer =
166         utils::CreateBufferFromData<uint32_t>(device, wgpu::BufferUsage::Index, {0, 1, 2});
167 
168     wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
169     {
170         wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
171         pass.SetIndexBuffer(indexBuffer, wgpu::IndexFormat::Uint32);
172         pass.SetPipeline(pipeline);
173         pass.SetVertexBuffer(0, vertexBuffer);
174         pass.DrawIndexed(3);
175         pass.EndPass();
176     }
177 
178     wgpu::CommandBuffer commands = encoder.Finish();
179     queue.Submit(1, &commands);
180 
181     EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), renderPass.color, 100, 300);
182 }
183 
184 // Test that index buffers of multiple formats can be used with a pipeline that
185 // doesn't use strip primitive topology.
TEST_P(IndexFormatTest,SetIndexBufferDifferentFormats)186 TEST_P(IndexFormatTest, SetIndexBufferDifferentFormats) {
187     wgpu::RenderPipeline pipeline =
188         MakeTestPipeline(wgpu::IndexFormat::Undefined, wgpu::PrimitiveTopology::TriangleList);
189 
190     wgpu::Buffer vertexBuffer = utils::CreateBufferFromData<float>(
191         device, wgpu::BufferUsage::Vertex,
192         {-1.0f, -1.0f, 0.0f, 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f});
193     wgpu::Buffer indexBuffer32 =
194         utils::CreateBufferFromData<uint32_t>(device, wgpu::BufferUsage::Index, {0, 1, 2});
195     wgpu::Buffer indexBuffer16 =
196         utils::CreateBufferFromData<uint16_t>(device, wgpu::BufferUsage::Index, {0, 1, 2, 0});
197 
198     wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
199     {
200         wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
201         pass.SetIndexBuffer(indexBuffer32, wgpu::IndexFormat::Uint32);
202         pass.SetPipeline(pipeline);
203         pass.SetVertexBuffer(0, vertexBuffer);
204         pass.DrawIndexed(3);
205         pass.EndPass();
206     }
207 
208     wgpu::CommandBuffer commands = encoder.Finish();
209     queue.Submit(1, &commands);
210 
211     EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), renderPass.color, 100, 300);
212 
213     encoder = device.CreateCommandEncoder();
214     {
215         wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
216         pass.SetIndexBuffer(indexBuffer16, wgpu::IndexFormat::Uint16);
217         pass.SetPipeline(pipeline);
218         pass.SetVertexBuffer(0, vertexBuffer);
219         pass.DrawIndexed(3);
220         pass.EndPass();
221     }
222 
223     commands = encoder.Finish();
224     queue.Submit(1, &commands);
225 
226     EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 255, 0, 255), renderPass.color, 100, 300);
227 }
228 
229 // Tests for primitive restart use vertices like in the drawing and draw the following
230 // indices: 0 1 2 PRIM_RESTART 3 4 5. Then A and B should be written but not C.
231 //      |--------------|
232 //      |      0---1   |
233 //      |       \ B|   |
234 //      |         \|   |
235 //      |  3   C   2   |
236 //      |  |\          |
237 //      |  |A \        |
238 //      |  4---5       |
239 //      |--------------|
240 
241 class TriangleStripPrimitiveRestartTests : public IndexFormatTest {
242   protected:
243     wgpu::Buffer mVertexBuffer;
244 
SetUp()245     void SetUp() override {
246         IndexFormatTest::SetUp();
247         mVertexBuffer = utils::CreateBufferFromData<float>(device, wgpu::BufferUsage::Vertex,
248                                                            {
249                                                                0.0f,  1.0f,  0.0f, 1.0f,  // 0
250                                                                1.0f,  1.0f,  0.0f, 1.0f,  // 1
251                                                                1.0f,  0.0f,  0.0f, 1.0f,  // 2
252                                                                -1.0f, 0.0f,  0.0f, 1.0f,  // 3
253                                                                -1.0f, -1.0f, 0.0f, 1.0f,  // 4
254                                                                0.0f,  -1.0f, 0.0f, 1.0f,  // 5
255                                                            });
256     }
257 };
258 
259 // Test use of primitive restart with an Uint32 index format
TEST_P(TriangleStripPrimitiveRestartTests,Uint32PrimitiveRestart)260 TEST_P(TriangleStripPrimitiveRestartTests, Uint32PrimitiveRestart) {
261     wgpu::RenderPipeline pipeline = MakeTestPipeline(wgpu::IndexFormat::Uint32);
262 
263     wgpu::Buffer indexBuffer =
264         utils::CreateBufferFromData<uint32_t>(device, wgpu::BufferUsage::Index,
265                                               {
266                                                   0,
267                                                   1,
268                                                   2,
269                                                   0xFFFFFFFFu,
270                                                   3,
271                                                   4,
272                                                   5,
273                                               });
274 
275     wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
276     {
277         wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
278         pass.SetPipeline(pipeline);
279         pass.SetVertexBuffer(0, mVertexBuffer);
280         pass.SetIndexBuffer(indexBuffer, wgpu::IndexFormat::Uint32);
281         pass.DrawIndexed(7);
282         pass.EndPass();
283     }
284 
285     wgpu::CommandBuffer commands = encoder.Finish();
286     queue.Submit(1, &commands);
287 
288     EXPECT_PIXEL_RGBA8_EQ(RGBA8::kGreen, renderPass.color, 50, 350);  // A
289     EXPECT_PIXEL_RGBA8_EQ(RGBA8::kGreen, renderPass.color, 350, 50);  // B
290     EXPECT_PIXEL_RGBA8_EQ(RGBA8::kZero, renderPass.color, 198, 200);  // C
291 }
292 
293 // Same as the above test, but uses an OOB index to emulate primitive restart being disabled,
294 // causing point C to be written to.
TEST_P(TriangleStripPrimitiveRestartTests,Uint32WithoutPrimitiveRestart)295 TEST_P(TriangleStripPrimitiveRestartTests, Uint32WithoutPrimitiveRestart) {
296     wgpu::RenderPipeline pipeline = MakeTestPipeline(wgpu::IndexFormat::Uint32);
297     wgpu::Buffer indexBuffer =
298         utils::CreateBufferFromData<uint32_t>(device, wgpu::BufferUsage::Index,
299                                               {
300                                                   0,
301                                                   1,
302                                                   2,
303                                                   // Not a valid index.
304                                                   0xFFFFFFFEu,
305                                                   3,
306                                                   4,
307                                                   5,
308                                               });
309 
310     wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
311     {
312         wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
313         pass.SetPipeline(pipeline);
314         pass.SetVertexBuffer(0, mVertexBuffer);
315         pass.SetIndexBuffer(indexBuffer, wgpu::IndexFormat::Uint32);
316         pass.DrawIndexed(7);
317         pass.EndPass();
318     }
319 
320     wgpu::CommandBuffer commands = encoder.Finish();
321     queue.Submit(1, &commands);
322 
323     EXPECT_PIXEL_RGBA8_EQ(RGBA8::kGreen, renderPass.color, 50, 350);   // A
324     EXPECT_PIXEL_RGBA8_EQ(RGBA8::kGreen, renderPass.color, 350, 50);   // B
325     EXPECT_PIXEL_RGBA8_EQ(RGBA8::kGreen, renderPass.color, 198, 200);  // C
326 }
327 
328 // Test use of primitive restart with an Uint16 index format
TEST_P(TriangleStripPrimitiveRestartTests,Uint16PrimitiveRestart)329 TEST_P(TriangleStripPrimitiveRestartTests, Uint16PrimitiveRestart) {
330     wgpu::RenderPipeline pipeline = MakeTestPipeline(wgpu::IndexFormat::Uint16);
331 
332     wgpu::Buffer indexBuffer =
333         utils::CreateBufferFromData<uint16_t>(device, wgpu::BufferUsage::Index,
334                                               {
335                                                   0,
336                                                   1,
337                                                   2,
338                                                   0xFFFFu,
339                                                   3,
340                                                   4,
341                                                   5,
342                                                   // This value is for padding.
343                                                   0xFFFFu,
344                                               });
345 
346     wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
347     {
348         wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
349         pass.SetPipeline(pipeline);
350         pass.SetVertexBuffer(0, mVertexBuffer);
351         pass.SetIndexBuffer(indexBuffer, wgpu::IndexFormat::Uint16);
352         pass.DrawIndexed(7);
353         pass.EndPass();
354     }
355 
356     wgpu::CommandBuffer commands = encoder.Finish();
357     queue.Submit(1, &commands);
358 
359     EXPECT_PIXEL_RGBA8_EQ(RGBA8::kGreen, renderPass.color, 50, 350);  // A
360     EXPECT_PIXEL_RGBA8_EQ(RGBA8::kGreen, renderPass.color, 350, 50);  // B
361     EXPECT_PIXEL_RGBA8_EQ(RGBA8::kZero, renderPass.color, 198, 200);  // C
362 }
363 
364 // Tests for primitive restart use vertices like in the drawing and draw the following
365 // indices: 0 1 PRIM_RESTART 2 3. Then 1 and 2 should be written but not A.
366 //      |--------------|
367 //      |      3      0|
368 //      |      |      ||
369 //      |      |      ||
370 //      |      2  A   1|
371 //      |              |
372 //      |              |
373 //      |              |
374 //      |--------------|
375 
376 class LineStripPrimitiveRestartTests : public IndexFormatTest {
377   protected:
378   protected:
379     wgpu::Buffer mVertexBuffer;
380 
SetUp()381     void SetUp() override {
382         IndexFormatTest::SetUp();
383         mVertexBuffer = utils::CreateBufferFromData<float>(device, wgpu::BufferUsage::Vertex,
384                                                            {
385                                                                1.0f, 1.0f, 0.0f, 1.0f,  // 0
386                                                                1.0f, 0.0f, 0.0f, 1.0f,  // 1
387                                                                0.0f, 0.0f, 0.0f, 1.0f,  // 2
388                                                                0.0f, 1.0f, 0.0f, 1.0f   // 3
389                                                            });
390     }
391 };
392 
TEST_P(LineStripPrimitiveRestartTests,Uint32PrimitiveRestart)393 TEST_P(LineStripPrimitiveRestartTests, Uint32PrimitiveRestart) {
394     wgpu::RenderPipeline pipeline =
395         MakeTestPipeline(wgpu::IndexFormat::Uint32, wgpu::PrimitiveTopology::LineStrip);
396 
397     wgpu::Buffer indexBuffer = utils::CreateBufferFromData<uint32_t>(
398         device, wgpu::BufferUsage::Index, {0, 1, 0xFFFFFFFFu, 2, 3});
399 
400     wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
401     {
402         wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
403         pass.SetPipeline(pipeline);
404         pass.SetVertexBuffer(0, mVertexBuffer);
405         pass.SetIndexBuffer(indexBuffer, wgpu::IndexFormat::Uint32);
406         pass.DrawIndexed(5);
407         pass.EndPass();
408     }
409 
410     wgpu::CommandBuffer commands = encoder.Finish();
411     queue.Submit(1, &commands);
412 
413     EXPECT_PIXEL_RGBA8_EQ(RGBA8::kGreen, renderPass.color, 399, 199);  // 1
414     EXPECT_PIXEL_RGBA8_EQ(RGBA8::kGreen, renderPass.color, 199, 199);  // 2
415     EXPECT_PIXEL_RGBA8_EQ(RGBA8::kZero, renderPass.color, 300, 199);   // A
416 }
417 
418 // Same as the above test, but uses an OOB index to emulate primitive restart being disabled,
419 // causing point A to be written to.
TEST_P(LineStripPrimitiveRestartTests,Uint32WithoutPrimitiveRestart)420 TEST_P(LineStripPrimitiveRestartTests, Uint32WithoutPrimitiveRestart) {
421     wgpu::RenderPipeline pipeline =
422         MakeTestPipeline(wgpu::IndexFormat::Uint32, wgpu::PrimitiveTopology::LineStrip);
423 
424     wgpu::Buffer indexBuffer =
425         utils::CreateBufferFromData<uint32_t>(device, wgpu::BufferUsage::Index,
426                                               {0, 1,  // Not a valid index
427                                                0xFFFFFFFEu, 2, 3});
428 
429     wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
430     {
431         wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
432         pass.SetPipeline(pipeline);
433         pass.SetVertexBuffer(0, mVertexBuffer);
434         pass.SetIndexBuffer(indexBuffer, wgpu::IndexFormat::Uint32);
435         pass.DrawIndexed(5);
436         pass.EndPass();
437     }
438 
439     wgpu::CommandBuffer commands = encoder.Finish();
440     queue.Submit(1, &commands);
441 
442     EXPECT_PIXEL_RGBA8_EQ(RGBA8::kGreen, renderPass.color, 399, 199);  // 1
443     EXPECT_PIXEL_RGBA8_EQ(RGBA8::kGreen, renderPass.color, 199, 199);  // 2
444     EXPECT_PIXEL_RGBA8_EQ(RGBA8::kGreen, renderPass.color, 300, 199);  // A
445 }
446 
TEST_P(LineStripPrimitiveRestartTests,Uint16PrimitiveRestart)447 TEST_P(LineStripPrimitiveRestartTests, Uint16PrimitiveRestart) {
448     wgpu::RenderPipeline pipeline =
449         MakeTestPipeline(wgpu::IndexFormat::Uint16, wgpu::PrimitiveTopology::LineStrip);
450 
451     wgpu::Buffer indexBuffer =
452         utils::CreateBufferFromData<uint16_t>(device, wgpu::BufferUsage::Index,
453                                               {0, 1, 0xFFFFu, 2, 3,  // This value is for padding.
454                                                0xFFFFu});
455 
456     wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
457     {
458         wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
459         pass.SetPipeline(pipeline);
460         pass.SetVertexBuffer(0, mVertexBuffer);
461         pass.SetIndexBuffer(indexBuffer, wgpu::IndexFormat::Uint16);
462         pass.DrawIndexed(5);
463         pass.EndPass();
464     }
465 
466     wgpu::CommandBuffer commands = encoder.Finish();
467     queue.Submit(1, &commands);
468 
469     EXPECT_PIXEL_RGBA8_EQ(RGBA8::kGreen, renderPass.color, 399, 199);  // 1
470     EXPECT_PIXEL_RGBA8_EQ(RGBA8::kGreen, renderPass.color, 199, 199);  // 2
471     EXPECT_PIXEL_RGBA8_EQ(RGBA8::kZero, renderPass.color, 300, 199);   // A
472 }
473 
474 DAWN_INSTANTIATE_TEST(IndexFormatTest,
475                       D3D12Backend(),
476                       MetalBackend(),
477                       OpenGLBackend(),
478                       OpenGLESBackend(),
479                       VulkanBackend());
480 DAWN_INSTANTIATE_TEST(TriangleStripPrimitiveRestartTests,
481                       D3D12Backend(),
482                       MetalBackend(),
483                       OpenGLBackend(),
484                       OpenGLESBackend(),
485                       VulkanBackend());
486 DAWN_INSTANTIATE_TEST(LineStripPrimitiveRestartTests,
487                       D3D12Backend(),
488                       MetalBackend(),
489                       OpenGLBackend(),
490                       OpenGLESBackend(),
491                       VulkanBackend());
492