• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 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 class EntryPointTests : public DawnTest {};
21 
22 // Test creating a render pipeline from two entryPoints in the same module.
TEST_P(EntryPointTests,FragAndVertexSameModule)23 TEST_P(EntryPointTests, FragAndVertexSameModule) {
24     // TODO(crbug.com/dawn/658): Crashes on bots
25     DAWN_SUPPRESS_TEST_IF(IsOpenGL() || IsOpenGLES());
26     wgpu::ShaderModule module = utils::CreateShaderModule(device, R"(
27         [[stage(vertex)]] fn vertex_main() -> [[builtin(position)]] vec4<f32> {
28             return vec4<f32>(0.0, 0.0, 0.0, 1.0);
29         }
30 
31         [[stage(fragment)]] fn fragment_main() -> [[location(0)]] vec4<f32> {
32           return vec4<f32>(1.0, 0.0, 0.0, 1.0);
33         }
34     )");
35 
36     // Create a point pipeline from the module.
37     utils::ComboRenderPipelineDescriptor desc;
38     desc.vertex.module = module;
39     desc.vertex.entryPoint = "vertex_main";
40     desc.cFragment.module = module;
41     desc.cFragment.entryPoint = "fragment_main";
42     desc.cTargets[0].format = wgpu::TextureFormat::RGBA8Unorm;
43     desc.primitive.topology = wgpu::PrimitiveTopology::PointList;
44     wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&desc);
45 
46     // Render the point and check that it was rendered.
47     utils::BasicRenderPass renderPass = utils::CreateBasicRenderPass(device, 1, 1);
48     wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
49     {
50         wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass.renderPassInfo);
51         pass.SetPipeline(pipeline);
52         pass.Draw(1);
53         pass.EndPass();
54     }
55     wgpu::CommandBuffer commands = encoder.Finish();
56     queue.Submit(1, &commands);
57 
58     EXPECT_PIXEL_RGBA8_EQ(RGBA8::kRed, renderPass.color, 0, 0);
59 }
60 
61 // Test creating two compute pipelines from the same module.
TEST_P(EntryPointTests,TwoComputeInModule)62 TEST_P(EntryPointTests, TwoComputeInModule) {
63     wgpu::BindGroupLayoutEntry binding = {};
64     binding.binding = 0;
65     binding.buffer.type = wgpu::BufferBindingType::Storage;
66     binding.visibility = wgpu::ShaderStage::Compute;
67 
68     wgpu::BindGroupLayoutDescriptor desc = {};
69     desc.entryCount = 1;
70     desc.entries = &binding;
71 
72     wgpu::BindGroupLayout bindGroupLayout = device.CreateBindGroupLayout(&desc);
73 
74     wgpu::PipelineLayoutDescriptor pipelineLayoutDesc = {};
75     pipelineLayoutDesc.bindGroupLayoutCount = 1;
76     pipelineLayoutDesc.bindGroupLayouts = &bindGroupLayout;
77 
78     wgpu::PipelineLayout pipelineLayout = device.CreatePipelineLayout(&pipelineLayoutDesc);
79 
80     wgpu::ShaderModule module = utils::CreateShaderModule(device, R"(
81         [[block]] struct Data {
82             data : u32;
83         };
84         [[binding(0), group(0)]] var<storage, read_write> data : Data;
85 
86         [[stage(compute), workgroup_size(1)]] fn write1() {
87             data.data = 1u;
88             return;
89         }
90 
91         [[stage(compute), workgroup_size(1)]] fn write42() {
92             data.data = 42u;
93             return;
94         }
95     )");
96 
97     // Create both pipelines from the module.
98     wgpu::ComputePipelineDescriptor pipelineDesc;
99     pipelineDesc.layout = pipelineLayout;
100     pipelineDesc.compute.module = module;
101 
102     pipelineDesc.compute.entryPoint = "write1";
103     wgpu::ComputePipeline write1 = device.CreateComputePipeline(&pipelineDesc);
104 
105     pipelineDesc.compute.entryPoint = "write42";
106     wgpu::ComputePipeline write42 = device.CreateComputePipeline(&pipelineDesc);
107 
108     // Create the bindGroup.
109     wgpu::BufferDescriptor bufferDesc;
110     bufferDesc.size = 4;
111     bufferDesc.usage = wgpu::BufferUsage::Storage | wgpu::BufferUsage::CopySrc;
112     wgpu::Buffer buffer = device.CreateBuffer(&bufferDesc);
113 
114     wgpu::BindGroup group = utils::MakeBindGroup(device, bindGroupLayout, {{0, buffer}});
115 
116     // Use the first pipeline and check it wrote 1.
117     {
118         wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
119         wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
120         pass.SetPipeline(write1);
121         pass.SetBindGroup(0, group);
122         pass.Dispatch(1);
123         pass.EndPass();
124         wgpu::CommandBuffer commands = encoder.Finish();
125         queue.Submit(1, &commands);
126 
127         EXPECT_BUFFER_U32_EQ(1, buffer, 0);
128     }
129 
130     // Use the second pipeline and check it wrote 42.
131     {
132         wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
133         wgpu::ComputePassEncoder pass = encoder.BeginComputePass();
134         pass.SetPipeline(write42);
135         pass.SetBindGroup(0, group);
136         pass.Dispatch(42);
137         pass.EndPass();
138         wgpu::CommandBuffer commands = encoder.Finish();
139         queue.Submit(1, &commands);
140 
141         EXPECT_BUFFER_U32_EQ(42, buffer, 0);
142     }
143 }
144 
145 DAWN_INSTANTIATE_TEST(EntryPointTests,
146                       D3D12Backend(),
147                       MetalBackend(),
148                       OpenGLBackend(),
149                       OpenGLESBackend(),
150                       VulkanBackend());
151