• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "utils/ComboRenderPipelineDescriptor.h"
18 #include "utils/WGPUHelpers.h"
19 
20 constexpr uint32_t kRTSize = 4;
21 
22 class DrawIndirectTest : 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             {// 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,
57 
58              // The top right triangle
59              -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f});
60     }
61 
62     utils::BasicRenderPass renderPass;
63     wgpu::RenderPipeline pipeline;
64     wgpu::Buffer vertexBuffer;
65 
Test(std::initializer_list<uint32_t> bufferList,uint64_t indirectOffset,RGBA8 bottomLeftExpected,RGBA8 topRightExpected)66     void Test(std::initializer_list<uint32_t> bufferList,
67               uint64_t indirectOffset,
68               RGBA8 bottomLeftExpected,
69               RGBA8 topRightExpected) {
70         wgpu::Buffer indirectBuffer =
71             utils::CreateBufferFromData<uint32_t>(device, wgpu::BufferUsage::Indirect, bufferList);
72 
73         wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
74         {
75             wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
76             pass.SetPipeline(pipeline);
77             pass.SetVertexBuffer(0, vertexBuffer);
78             pass.DrawIndirect(indirectBuffer, indirectOffset);
79             pass.EndPass();
80         }
81 
82         wgpu::CommandBuffer commands = encoder.Finish();
83         queue.Submit(1, &commands);
84 
85         EXPECT_PIXEL_RGBA8_EQ(bottomLeftExpected, renderPass.color, 1, 3);
86         EXPECT_PIXEL_RGBA8_EQ(topRightExpected, renderPass.color, 3, 1);
87     }
88 };
89 
90 // The basic triangle draw.
TEST_P(DrawIndirectTest,Uint32)91 TEST_P(DrawIndirectTest, Uint32) {
92     RGBA8 filled(0, 255, 0, 255);
93     RGBA8 notFilled(0, 0, 0, 0);
94 
95     // Test a draw with no indices.
96     Test({0, 0, 0, 0}, 0, notFilled, notFilled);
97 
98     // Test a draw with only the first 3 indices (bottom left triangle)
99     Test({3, 1, 0, 0}, 0, filled, notFilled);
100 
101     // Test a draw with only the last 3 indices (top right triangle)
102     Test({3, 1, 3, 0}, 0, notFilled, filled);
103 
104     // Test a draw with all 6 indices (both triangles).
105     Test({6, 1, 0, 0}, 0, filled, filled);
106 }
107 
TEST_P(DrawIndirectTest,IndirectOffset)108 TEST_P(DrawIndirectTest, IndirectOffset) {
109     RGBA8 filled(0, 255, 0, 255);
110     RGBA8 notFilled(0, 0, 0, 0);
111 
112     // Test an offset draw call, with indirect buffer containing 2 calls:
113     // 1) only the first 3 indices (bottom left triangle)
114     // 2) only the last 3 indices (top right triangle)
115 
116     // Test #1 (no offset)
117     Test({3, 1, 0, 0, 3, 1, 3, 0}, 0, filled, notFilled);
118 
119     // Offset to draw #2
120     Test({3, 1, 0, 0, 3, 1, 3, 0}, 4 * sizeof(uint32_t), notFilled, filled);
121 }
122 
123 DAWN_INSTANTIATE_TEST(DrawIndirectTest,
124                       D3D12Backend(),
125                       MetalBackend(),
126                       OpenGLBackend(),
127                       OpenGLESBackend(),
128                       VulkanBackend());
129