1 // Copyright 2018 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 "utils/ComboRenderPipelineDescriptor.h"
18 #include "utils/WGPUHelpers.h"
19
20 constexpr uint32_t kRTSize = 4;
21
22 class DrawIndexedTest : public DawnTest {
23 protected:
SetUp()24 void SetUp() override {
25 DawnTest::SetUp();
26
27 renderPass = utils::CreateBasicRenderPass(device, kRTSize, kRTSize);
28
29 wgpu::ShaderModule vsModule = utils::CreateShaderModule(device, R"(
30 [[stage(vertex)]]
31 fn main([[location(0)]] pos : vec4<f32>) -> [[builtin(position)]] vec4<f32> {
32 return pos;
33 })");
34
35 wgpu::ShaderModule fsModule = utils::CreateShaderModule(device, R"(
36 [[stage(fragment)]] fn main() -> [[location(0)]] vec4<f32> {
37 return vec4<f32>(0.0, 1.0, 0.0, 1.0);
38 })");
39
40 utils::ComboRenderPipelineDescriptor descriptor;
41 descriptor.vertex.module = vsModule;
42 descriptor.cFragment.module = fsModule;
43 descriptor.primitive.topology = wgpu::PrimitiveTopology::TriangleStrip;
44 descriptor.primitive.stripIndexFormat = wgpu::IndexFormat::Uint32;
45 descriptor.vertex.bufferCount = 1;
46 descriptor.cBuffers[0].arrayStride = 4 * sizeof(float);
47 descriptor.cBuffers[0].attributeCount = 1;
48 descriptor.cAttributes[0].format = wgpu::VertexFormat::Float32x4;
49 descriptor.cTargets[0].format = renderPass.colorFormat;
50
51 pipeline = device.CreateRenderPipeline(&descriptor);
52
53 vertexBuffer = utils::CreateBufferFromData<float>(
54 device, wgpu::BufferUsage::Vertex,
55 {// First quad: the first 3 vertices represent the bottom left triangle
56 -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, -1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 1.0f,
57 0.0f, 1.0f,
58
59 // Second quad: the first 3 vertices represent the top right triangle
60 -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, -1.0f, -1.0f,
61 0.0f, 1.0f});
62 indexBuffer = utils::CreateBufferFromData<uint32_t>(
63 device, wgpu::BufferUsage::Index,
64 {0, 1, 2, 0, 3, 1,
65 // The indices below are added to test negatve baseVertex
66 0 + 4, 1 + 4, 2 + 4, 0 + 4, 3 + 4, 1 + 4});
67 zeroSizedIndexBuffer =
68 utils::CreateBufferFromData<uint32_t>(device, wgpu::BufferUsage::Index, {});
69 }
70
71 utils::BasicRenderPass renderPass;
72 wgpu::RenderPipeline pipeline;
73 wgpu::Buffer vertexBuffer;
74 wgpu::Buffer indexBuffer;
75 wgpu::Buffer zeroSizedIndexBuffer;
76
Test(uint32_t indexCount,uint32_t instanceCount,uint32_t firstIndex,int32_t baseVertex,uint32_t firstInstance,uint64_t bufferOffset,RGBA8 bottomLeftExpected,RGBA8 topRightExpected)77 void Test(uint32_t indexCount,
78 uint32_t instanceCount,
79 uint32_t firstIndex,
80 int32_t baseVertex,
81 uint32_t firstInstance,
82 uint64_t bufferOffset,
83 RGBA8 bottomLeftExpected,
84 RGBA8 topRightExpected) {
85 // Regular draw with a reasonable index buffer
86 TestImplementation(indexCount, instanceCount, firstIndex, baseVertex, firstInstance,
87 bufferOffset, indexBuffer, bottomLeftExpected, topRightExpected);
88 }
89
TestZeroSizedIndexBufferDraw(uint32_t indexCount,uint32_t firstIndex,RGBA8 bottomLeftExpected,RGBA8 topRightExpected)90 void TestZeroSizedIndexBufferDraw(uint32_t indexCount,
91 uint32_t firstIndex,
92 RGBA8 bottomLeftExpected,
93 RGBA8 topRightExpected) {
94 TestImplementation(indexCount, 1, firstIndex, 0, 0, 0, zeroSizedIndexBuffer,
95 bottomLeftExpected, topRightExpected);
96 }
97
TestImplementation(uint32_t indexCount,uint32_t instanceCount,uint32_t firstIndex,int32_t baseVertex,uint32_t firstInstance,uint64_t bufferOffset,const wgpu::Buffer & curIndexBuffer,RGBA8 bottomLeftExpected,RGBA8 topRightExpected)98 void TestImplementation(uint32_t indexCount,
99 uint32_t instanceCount,
100 uint32_t firstIndex,
101 int32_t baseVertex,
102 uint32_t firstInstance,
103 uint64_t bufferOffset,
104 const wgpu::Buffer& curIndexBuffer,
105 RGBA8 bottomLeftExpected,
106 RGBA8 topRightExpected) {
107 wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
108 {
109 wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
110 pass.SetPipeline(pipeline);
111 pass.SetVertexBuffer(0, vertexBuffer);
112 pass.SetIndexBuffer(curIndexBuffer, wgpu::IndexFormat::Uint32, bufferOffset);
113 pass.DrawIndexed(indexCount, instanceCount, firstIndex, baseVertex, firstInstance);
114 pass.EndPass();
115 }
116
117 wgpu::CommandBuffer commands = encoder.Finish();
118 queue.Submit(1, &commands);
119
120 EXPECT_PIXEL_RGBA8_EQ(bottomLeftExpected, renderPass.color, 1, 3);
121 EXPECT_PIXEL_RGBA8_EQ(topRightExpected, renderPass.color, 3, 1);
122 }
123 };
124
125 // The most basic DrawIndexed triangle draw.
TEST_P(DrawIndexedTest,Uint32)126 TEST_P(DrawIndexedTest, Uint32) {
127 RGBA8 filled(0, 255, 0, 255);
128 RGBA8 notFilled(0, 0, 0, 0);
129
130 // Test a draw with no indices.
131 Test(0, 0, 0, 0, 0, 0, notFilled, notFilled);
132 // Test a draw with only the first 3 indices of the first quad (bottom left triangle)
133 Test(3, 1, 0, 0, 0, 0, filled, notFilled);
134 // Test a draw with only the last 3 indices of the first quad (top right triangle)
135 Test(3, 1, 3, 0, 0, 0, notFilled, filled);
136 // Test a draw with all 6 indices (both triangles).
137 Test(6, 1, 0, 0, 0, 0, filled, filled);
138 }
139
140 // Test the parameter 'baseVertex' of DrawIndexed() works.
TEST_P(DrawIndexedTest,BaseVertex)141 TEST_P(DrawIndexedTest, BaseVertex) {
142 DAWN_TEST_UNSUPPORTED_IF(HasToggleEnabled("disable_base_vertex"));
143 RGBA8 filled(0, 255, 0, 255);
144 RGBA8 notFilled(0, 0, 0, 0);
145
146 // Test a draw with only the first 3 indices of the second quad (top right triangle)
147 Test(3, 1, 0, 4, 0, 0, notFilled, filled);
148 // Test a draw with only the last 3 indices of the second quad (bottom left triangle)
149 Test(3, 1, 3, 4, 0, 0, filled, notFilled);
150
151 // Test negative baseVertex
152 // Test a draw with only the first 3 indices of the first quad (bottom left triangle)
153 Test(3, 1, 0, -4, 0, 6 * sizeof(uint32_t), filled, notFilled);
154 // Test a draw with only the last 3 indices of the first quad (top right triangle)
155 Test(3, 1, 3, -4, 0, 6 * sizeof(uint32_t), notFilled, filled);
156 }
157
158 DAWN_INSTANTIATE_TEST(DrawIndexedTest,
159 D3D12Backend(),
160 MetalBackend(),
161 OpenGLBackend(),
162 OpenGLESBackend(),
163 VulkanBackend());
164