• 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/DawnHelpers.h"
19 
20 constexpr uint32_t kRTSize = 400;
21 constexpr uint32_t kBufferElementsCount = kMinDynamicBufferOffsetAlignment / sizeof(uint32_t) + 2;
22 constexpr uint32_t kBufferSize = kBufferElementsCount * sizeof(uint32_t);
23 constexpr uint32_t kBindingSize = 8;
24 
25 class DynamicBufferOffsetTests : public DawnTest {
26   protected:
SetUp()27     void SetUp() override {
28         DawnTest::SetUp();
29 
30         std::array<uint32_t, kBufferElementsCount> uniformData = {0};
31 
32         uniformData[0] = 1;
33         uniformData[1] = 2;
34         uniformData[uniformData.size() - 2] = 5;
35         uniformData[uniformData.size() - 1] = 6;
36 
37         mUniformBuffer = utils::CreateBufferFromData(device, uniformData.data(), kBufferSize,
38                                                      dawn::BufferUsageBit::Uniform);
39 
40         dawn::BufferDescriptor storageBufferDescriptor;
41         storageBufferDescriptor.size = kBufferSize;
42         storageBufferDescriptor.usage = dawn::BufferUsageBit::Storage |
43                                         dawn::BufferUsageBit::CopyDst |
44                                         dawn::BufferUsageBit::CopySrc;
45 
46         mStorageBuffer = device.CreateBuffer(&storageBufferDescriptor);
47 
48         mBindGroupLayout = utils::MakeBindGroupLayout(
49             device, {{0, dawn::ShaderStageBit::Compute | dawn::ShaderStageBit::Fragment,
50                       dawn::BindingType::UniformBuffer, true},
51                      {1, dawn::ShaderStageBit::Compute | dawn::ShaderStageBit::Fragment,
52                       dawn::BindingType::StorageBuffer, true}});
53 
54         mBindGroup = utils::MakeBindGroup(
55             device, mBindGroupLayout,
56             {{0, mUniformBuffer, 0, kBindingSize}, {1, mStorageBuffer, 0, kBindingSize}});
57     }
58     // Create objects to use as resources inside test bind groups.
59 
60     dawn::BindGroup mBindGroup;
61     dawn::BindGroupLayout mBindGroupLayout;
62     dawn::Buffer mUniformBuffer;
63     dawn::Buffer mStorageBuffer;
64     dawn::Texture mColorAttachment;
65 
CreateRenderPipeline()66     dawn::RenderPipeline CreateRenderPipeline() {
67         dawn::ShaderModule vsModule =
68             utils::CreateShaderModule(device, utils::ShaderStage::Vertex, R"(
69                 #version 450
70                 void main() {
71                     const vec2 pos[3] = vec2[3](vec2(-1.0f, 0.0f), vec2(-1.0f, -1.0f), vec2(0.0f, -1.0f));
72                     gl_Position = vec4(pos[gl_VertexIndex], 0.0, 1.0);
73                 })");
74 
75         dawn::ShaderModule fsModule =
76             utils::CreateShaderModule(device, utils::ShaderStage::Fragment, R"(
77                 #version 450
78                 layout(std140, set = 0, binding = 0) uniform uBuffer {
79                      uvec2 value;
80                 };
81                 layout(std140, set = 0, binding = 1) buffer SBuffer {
82                      uvec2 result;
83                 } sBuffer;
84                 layout(location = 0) out vec4 fragColor;
85                 void main() {
86                     sBuffer.result.xy = value.xy;
87                     fragColor = vec4(value.x / 255.0f, value.y / 255.0f, 1.0f, 1.0f);
88                 })");
89 
90         utils::ComboRenderPipelineDescriptor pipelineDescriptor(device);
91         pipelineDescriptor.cVertexStage.module = vsModule;
92         pipelineDescriptor.cFragmentStage.module = fsModule;
93         pipelineDescriptor.cColorStates[0]->format = dawn::TextureFormat::RGBA8Unorm;
94         dawn::PipelineLayout pipelineLayout =
95             utils::MakeBasicPipelineLayout(device, &mBindGroupLayout);
96         pipelineDescriptor.layout = pipelineLayout;
97 
98         return device.CreateRenderPipeline(&pipelineDescriptor);
99     }
100 
CreateComputePipeline()101     dawn::ComputePipeline CreateComputePipeline() {
102         dawn::ShaderModule csModule =
103             utils::CreateShaderModule(device, utils::ShaderStage::Compute, R"(
104                 #version 450
105                 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
106                 layout(std140, set = 0, binding = 0) uniform UniformBuffer {
107                     uvec2 value;
108                 };
109                 layout(std140, set = 0, binding = 1) buffer SBuffer {
110                     uvec2 result;
111                 } sBuffer;
112 
113                 void main() {
114                     sBuffer.result.xy = value.xy;
115                 })");
116 
117         dawn::ComputePipelineDescriptor csDesc;
118         dawn::PipelineLayout pipelineLayout =
119             utils::MakeBasicPipelineLayout(device, &mBindGroupLayout);
120         csDesc.layout = pipelineLayout;
121 
122         dawn::PipelineStageDescriptor computeStage;
123         computeStage.module = csModule;
124         computeStage.entryPoint = "main";
125         csDesc.computeStage = &computeStage;
126 
127         return device.CreateComputePipeline(&csDesc);
128     }
129 };
130 
131 // Dynamic offsets are all zero and no effect to result.
TEST_P(DynamicBufferOffsetTests,BasicRenderPipeline)132 TEST_P(DynamicBufferOffsetTests, BasicRenderPipeline) {
133     dawn::RenderPipeline pipeline = CreateRenderPipeline();
134     utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, kRTSize, kRTSize);
135 
136     dawn::CommandEncoder commandEncoder = device.CreateCommandEncoder();
137     std::array<uint64_t, 2> offsets = {0, 0};
138     dawn::RenderPassEncoder renderPassEncoder =
139         commandEncoder.BeginRenderPass(&renderPass.renderPassInfo);
140     renderPassEncoder.SetPipeline(pipeline);
141     renderPassEncoder.SetBindGroup(0, mBindGroup, offsets.size(), offsets.data());
142     renderPassEncoder.Draw(3, 1, 0, 0);
143     renderPassEncoder.EndPass();
144     dawn::CommandBuffer commands = commandEncoder.Finish();
145     queue.Submit(1, &commands);
146 
147     std::vector<uint32_t> expectedData = {1, 2};
148     EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 2, 255, 255), renderPass.color, 0, 0);
149     EXPECT_BUFFER_U32_RANGE_EQ(expectedData.data(), mStorageBuffer, 0, expectedData.size());
150 }
151 
152 // Have non-zero dynamic offsets.
TEST_P(DynamicBufferOffsetTests,SetDynamicOffestsRenderPipeline)153 TEST_P(DynamicBufferOffsetTests, SetDynamicOffestsRenderPipeline) {
154     dawn::RenderPipeline pipeline = CreateRenderPipeline();
155     utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, kRTSize, kRTSize);
156 
157     dawn::CommandEncoder commandEncoder = device.CreateCommandEncoder();
158     std::array<uint64_t, 2> offsets = {kMinDynamicBufferOffsetAlignment,
159                                        kMinDynamicBufferOffsetAlignment};
160     dawn::RenderPassEncoder renderPassEncoder =
161         commandEncoder.BeginRenderPass(&renderPass.renderPassInfo);
162     renderPassEncoder.SetPipeline(pipeline);
163     renderPassEncoder.SetBindGroup(0, mBindGroup, offsets.size(), offsets.data());
164     renderPassEncoder.Draw(3, 1, 0, 0);
165     renderPassEncoder.EndPass();
166     dawn::CommandBuffer commands = commandEncoder.Finish();
167     queue.Submit(1, &commands);
168 
169     std::vector<uint32_t> expectedData = {5, 6};
170     EXPECT_PIXEL_RGBA8_EQ(RGBA8(5, 6, 255, 255), renderPass.color, 0, 0);
171     EXPECT_BUFFER_U32_RANGE_EQ(expectedData.data(), mStorageBuffer,
172                                kMinDynamicBufferOffsetAlignment, expectedData.size());
173 }
174 
175 // Dynamic offsets are all zero and no effect to result.
TEST_P(DynamicBufferOffsetTests,BasicComputePipeline)176 TEST_P(DynamicBufferOffsetTests, BasicComputePipeline) {
177     dawn::ComputePipeline pipeline = CreateComputePipeline();
178 
179     std::array<uint64_t, 2> offsets = {0, 0};
180 
181     dawn::CommandEncoder commandEncoder = device.CreateCommandEncoder();
182     dawn::ComputePassEncoder computePassEncoder = commandEncoder.BeginComputePass();
183     computePassEncoder.SetPipeline(pipeline);
184     computePassEncoder.SetBindGroup(0, mBindGroup, offsets.size(), offsets.data());
185     computePassEncoder.Dispatch(1, 1, 1);
186     computePassEncoder.EndPass();
187     dawn::CommandBuffer commands = commandEncoder.Finish();
188     queue.Submit(1, &commands);
189 
190     std::vector<uint32_t> expectedData = {1, 2};
191     EXPECT_BUFFER_U32_RANGE_EQ(expectedData.data(), mStorageBuffer, 0, expectedData.size());
192 }
193 
194 // Have non-zero dynamic offsets.
TEST_P(DynamicBufferOffsetTests,SetDynamicOffestsComputePipeline)195 TEST_P(DynamicBufferOffsetTests, SetDynamicOffestsComputePipeline) {
196     dawn::ComputePipeline pipeline = CreateComputePipeline();
197 
198     std::array<uint64_t, 2> offsets = {kMinDynamicBufferOffsetAlignment,
199                                        kMinDynamicBufferOffsetAlignment};
200 
201     dawn::CommandEncoder commandEncoder = device.CreateCommandEncoder();
202     dawn::ComputePassEncoder computePassEncoder = commandEncoder.BeginComputePass();
203     computePassEncoder.SetPipeline(pipeline);
204     computePassEncoder.SetBindGroup(0, mBindGroup, offsets.size(), offsets.data());
205     computePassEncoder.Dispatch(1, 1, 1);
206     computePassEncoder.EndPass();
207     dawn::CommandBuffer commands = commandEncoder.Finish();
208     queue.Submit(1, &commands);
209 
210     std::vector<uint32_t> expectedData = {5, 6};
211     EXPECT_BUFFER_U32_RANGE_EQ(expectedData.data(), mStorageBuffer,
212                                kMinDynamicBufferOffsetAlignment, expectedData.size());
213 }
214 
215 DAWN_INSTANTIATE_TEST(DynamicBufferOffsetTests, MetalBackend, VulkanBackend);
216