• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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