• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 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 "SampleUtils.h"
16 
17 #include "utils/ComboRenderPipelineDescriptor.h"
18 #include "utils/ScopedAutoreleasePool.h"
19 #include "utils/SystemUtils.h"
20 #include "utils/WGPUHelpers.h"
21 
22 #include <glm/glm.hpp>
23 #include <glm/gtc/matrix_transform.hpp>
24 #include <glm/gtc/type_ptr.hpp>
25 #include <vector>
26 
27 wgpu::Device device;
28 
29 wgpu::Buffer indexBuffer;
30 wgpu::Buffer vertexBuffer;
31 wgpu::Buffer planeBuffer;
32 wgpu::Buffer cameraBuffer;
33 wgpu::Buffer transformBuffer[2];
34 
35 wgpu::BindGroup cameraBindGroup;
36 wgpu::BindGroup bindGroup[2];
37 wgpu::BindGroup cubeTransformBindGroup[2];
38 
39 wgpu::Queue queue;
40 wgpu::SwapChain swapchain;
41 wgpu::TextureView depthStencilView;
42 wgpu::RenderPipeline pipeline;
43 wgpu::RenderPipeline planePipeline;
44 wgpu::RenderPipeline reflectionPipeline;
45 
initBuffers()46 void initBuffers() {
47     static const uint32_t indexData[6 * 6] = {0,  1,  2,  0,  2,  3,
48 
49                                               4,  5,  6,  4,  6,  7,
50 
51                                               8,  9,  10, 8,  10, 11,
52 
53                                               12, 13, 14, 12, 14, 15,
54 
55                                               16, 17, 18, 16, 18, 19,
56 
57                                               20, 21, 22, 20, 22, 23};
58     indexBuffer =
59         utils::CreateBufferFromData(device, indexData, sizeof(indexData), wgpu::BufferUsage::Index);
60 
61     static const float vertexData[6 * 4 * 6] = {
62         -1.0, -1.0, 1.0,  1.0, 0.0, 0.0, 1.0,  -1.0, 1.0,  1.0, 0.0, 0.0,
63         1.0,  1.0,  1.0,  1.0, 0.0, 0.0, -1.0, 1.0,  1.0,  1.0, 0.0, 0.0,
64 
65         -1.0, -1.0, -1.0, 1.0, 1.0, 0.0, -1.0, 1.0,  -1.0, 1.0, 1.0, 0.0,
66         1.0,  1.0,  -1.0, 1.0, 1.0, 0.0, 1.0,  -1.0, -1.0, 1.0, 1.0, 0.0,
67 
68         -1.0, 1.0,  -1.0, 1.0, 0.0, 1.0, -1.0, 1.0,  1.0,  1.0, 0.0, 1.0,
69         1.0,  1.0,  1.0,  1.0, 0.0, 1.0, 1.0,  1.0,  -1.0, 1.0, 0.0, 1.0,
70 
71         -1.0, -1.0, -1.0, 0.0, 1.0, 0.0, 1.0,  -1.0, -1.0, 0.0, 1.0, 0.0,
72         1.0,  -1.0, 1.0,  0.0, 1.0, 0.0, -1.0, -1.0, 1.0,  0.0, 1.0, 0.0,
73 
74         1.0,  -1.0, -1.0, 0.0, 1.0, 1.0, 1.0,  1.0,  -1.0, 0.0, 1.0, 1.0,
75         1.0,  1.0,  1.0,  0.0, 1.0, 1.0, 1.0,  -1.0, 1.0,  0.0, 1.0, 1.0,
76 
77         -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0,  1.0, 1.0, 1.0,
78         -1.0, 1.0,  1.0,  1.0, 1.0, 1.0, -1.0, 1.0,  -1.0, 1.0, 1.0, 1.0};
79     vertexBuffer = utils::CreateBufferFromData(device, vertexData, sizeof(vertexData),
80                                                wgpu::BufferUsage::Vertex);
81 
82     static const float planeData[6 * 4] = {
83         -2.0, -1.0, -2.0, 0.5, 0.5, 0.5, 2.0,  -1.0, -2.0, 0.5, 0.5, 0.5,
84         2.0,  -1.0, 2.0,  0.5, 0.5, 0.5, -2.0, -1.0, 2.0,  0.5, 0.5, 0.5,
85     };
86     planeBuffer = utils::CreateBufferFromData(device, planeData, sizeof(planeData),
87                                               wgpu::BufferUsage::Vertex);
88 }
89 
90 struct CameraData {
91     glm::mat4 view;
92     glm::mat4 proj;
93 } cameraData;
94 
init()95 void init() {
96     device = CreateCppDawnDevice();
97 
98     queue = device.GetQueue();
99     swapchain = GetSwapChain(device);
100     swapchain.Configure(GetPreferredSwapChainTextureFormat(), wgpu::TextureUsage::RenderAttachment,
101                         640, 480);
102 
103     initBuffers();
104 
105     wgpu::ShaderModule vsModule = utils::CreateShaderModule(device, R"(
106         [[block]] struct Camera {
107             view : mat4x4<f32>;
108             proj : mat4x4<f32>;
109         };
110         [[group(0), binding(0)]] var<uniform> camera : Camera;
111 
112         [[block]] struct Model {
113             matrix : mat4x4<f32>;
114         };
115         [[group(0), binding(1)]] var<uniform> model : Model;
116 
117         struct VertexOut {
118             [[location(2)]] f_col : vec3<f32>;
119             [[builtin(position)]] Position : vec4<f32>;
120         };
121 
122         [[stage(vertex)]] fn main(
123             [[location(0)]] pos : vec3<f32>,
124             [[location(1)]] col : vec3<f32>) -> VertexOut {
125             var output : VertexOut;
126             output.f_col = col;
127             output.Position = camera.proj * camera.view * model.matrix * vec4<f32>(pos, 1.0);
128             return output;
129         })");
130 
131     wgpu::ShaderModule fsModule = utils::CreateShaderModule(device, R"(
132         [[stage(fragment)]] fn main(
133             [[location(2)]] f_col : vec3<f32>) -> [[location(0)]] vec4<f32> {
134             return vec4<f32>(f_col, 1.0);
135         })");
136 
137     wgpu::ShaderModule fsReflectionModule = utils::CreateShaderModule(device, R"(
138         [[stage(fragment)]] fn main(
139             [[location(2)]] f_col : vec3<f32>) -> [[location(0)]] vec4<f32> {
140             return vec4<f32>(mix(f_col, vec3<f32>(0.5, 0.5, 0.5), vec3<f32>(0.5, 0.5, 0.5)), 1.0);
141         })");
142 
143     wgpu::VertexAttribute attributes[2];
144     attributes[0].shaderLocation = 0;
145     attributes[0].offset = 0;
146     attributes[0].format = wgpu::VertexFormat::Float32x3;
147     attributes[1].shaderLocation = 1;
148     attributes[1].offset = 3 * sizeof(float);
149     attributes[1].format = wgpu::VertexFormat::Float32x3;
150 
151     wgpu::VertexBufferLayout vertexBufferLayout;
152     vertexBufferLayout.attributeCount = 2;
153     vertexBufferLayout.attributes = attributes;
154     vertexBufferLayout.arrayStride = 6 * sizeof(float);
155 
156     auto bgl = utils::MakeBindGroupLayout(
157         device, {
158                     {0, wgpu::ShaderStage::Vertex, wgpu::BufferBindingType::Uniform},
159                     {1, wgpu::ShaderStage::Vertex, wgpu::BufferBindingType::Uniform},
160                 });
161 
162     wgpu::PipelineLayout pl = utils::MakeBasicPipelineLayout(device, &bgl);
163 
164     wgpu::BufferDescriptor cameraBufDesc;
165     cameraBufDesc.size = sizeof(CameraData);
166     cameraBufDesc.usage = wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::Uniform;
167     cameraBuffer = device.CreateBuffer(&cameraBufDesc);
168 
169     glm::mat4 transform(1.0);
170     transformBuffer[0] = utils::CreateBufferFromData(device, &transform, sizeof(glm::mat4),
171                                                      wgpu::BufferUsage::Uniform);
172 
173     transform = glm::translate(transform, glm::vec3(0.f, -2.f, 0.f));
174     transformBuffer[1] = utils::CreateBufferFromData(device, &transform, sizeof(glm::mat4),
175                                                      wgpu::BufferUsage::Uniform);
176 
177     bindGroup[0] = utils::MakeBindGroup(
178         device, bgl,
179         {{0, cameraBuffer, 0, sizeof(CameraData)}, {1, transformBuffer[0], 0, sizeof(glm::mat4)}});
180 
181     bindGroup[1] = utils::MakeBindGroup(
182         device, bgl,
183         {{0, cameraBuffer, 0, sizeof(CameraData)}, {1, transformBuffer[1], 0, sizeof(glm::mat4)}});
184 
185     depthStencilView = CreateDefaultDepthStencilView(device);
186 
187     {
188         utils::ComboRenderPipelineDescriptor descriptor;
189         descriptor.vertex.module = vsModule;
190         descriptor.vertex.bufferCount = 1;
191         descriptor.vertex.buffers = &vertexBufferLayout;
192 
193         descriptor.layout = pl;
194         descriptor.cFragment.module = fsModule;
195         descriptor.cTargets[0].format = GetPreferredSwapChainTextureFormat();
196 
197         wgpu::DepthStencilState* depthStencil =
198             descriptor.EnableDepthStencil(wgpu::TextureFormat::Depth24PlusStencil8);
199         depthStencil->depthWriteEnabled = true;
200         depthStencil->depthCompare = wgpu::CompareFunction::Less;
201 
202         pipeline = device.CreateRenderPipeline(&descriptor);
203     }
204 
205     {
206         utils::ComboRenderPipelineDescriptor descriptor;
207         descriptor.vertex.module = vsModule;
208         descriptor.vertex.bufferCount = 1;
209         descriptor.vertex.buffers = &vertexBufferLayout;
210 
211         descriptor.layout = pl;
212         descriptor.cFragment.module = fsModule;
213         descriptor.cTargets[0].format = GetPreferredSwapChainTextureFormat();
214 
215         wgpu::DepthStencilState* depthStencil =
216             descriptor.EnableDepthStencil(wgpu::TextureFormat::Depth24PlusStencil8);
217         depthStencil->stencilFront.passOp = wgpu::StencilOperation::Replace;
218         depthStencil->stencilBack.passOp = wgpu::StencilOperation::Replace;
219         depthStencil->depthCompare = wgpu::CompareFunction::Less;
220 
221         planePipeline = device.CreateRenderPipeline(&descriptor);
222     }
223 
224     {
225         utils::ComboRenderPipelineDescriptor descriptor;
226         descriptor.vertex.module = vsModule;
227         descriptor.vertex.bufferCount = 1;
228         descriptor.vertex.buffers = &vertexBufferLayout;
229 
230         descriptor.layout = pl;
231         descriptor.cFragment.module = fsReflectionModule;
232         descriptor.cTargets[0].format = GetPreferredSwapChainTextureFormat();
233 
234         wgpu::DepthStencilState* depthStencil =
235             descriptor.EnableDepthStencil(wgpu::TextureFormat::Depth24PlusStencil8);
236         depthStencil->stencilFront.compare = wgpu::CompareFunction::Equal;
237         depthStencil->stencilBack.compare = wgpu::CompareFunction::Equal;
238         depthStencil->stencilFront.passOp = wgpu::StencilOperation::Replace;
239         depthStencil->stencilBack.passOp = wgpu::StencilOperation::Replace;
240         depthStencil->depthWriteEnabled = true;
241         depthStencil->depthCompare = wgpu::CompareFunction::Less;
242 
243         reflectionPipeline = device.CreateRenderPipeline(&descriptor);
244     }
245 
246     cameraData.proj = glm::perspective(glm::radians(45.0f), 1.f, 1.0f, 100.0f);
247 }
248 
249 struct {
250     uint32_t a;
251     float b;
252 } s;
frame()253 void frame() {
254     s.a = (s.a + 1) % 256;
255     s.b += 0.01f;
256     if (s.b >= 1.0f) {
257         s.b = 0.0f;
258     }
259 
260     cameraData.view = glm::lookAt(glm::vec3(8.f * std::sin(glm::radians(s.b * 360.f)), 2.f,
261                                             8.f * std::cos(glm::radians(s.b * 360.f))),
262                                   glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
263 
264     queue.WriteBuffer(cameraBuffer, 0, &cameraData, sizeof(CameraData));
265 
266     wgpu::TextureView backbufferView = swapchain.GetCurrentTextureView();
267     utils::ComboRenderPassDescriptor renderPass({backbufferView}, depthStencilView);
268 
269     wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
270     {
271         wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
272         pass.SetPipeline(pipeline);
273         pass.SetBindGroup(0, bindGroup[0]);
274         pass.SetVertexBuffer(0, vertexBuffer);
275         pass.SetIndexBuffer(indexBuffer, wgpu::IndexFormat::Uint32);
276         pass.DrawIndexed(36);
277 
278         pass.SetStencilReference(0x1);
279         pass.SetPipeline(planePipeline);
280         pass.SetBindGroup(0, bindGroup[0]);
281         pass.SetVertexBuffer(0, planeBuffer);
282         pass.DrawIndexed(6);
283 
284         pass.SetPipeline(reflectionPipeline);
285         pass.SetVertexBuffer(0, vertexBuffer);
286         pass.SetBindGroup(0, bindGroup[1]);
287         pass.DrawIndexed(36);
288 
289         pass.EndPass();
290     }
291 
292     wgpu::CommandBuffer commands = encoder.Finish();
293     queue.Submit(1, &commands);
294     swapchain.Present();
295     DoFlush();
296 }
297 
main(int argc,const char * argv[])298 int main(int argc, const char* argv[]) {
299     if (!InitSample(argc, argv)) {
300         return 1;
301     }
302     init();
303 
304     while (!ShouldQuit()) {
305         utils::ScopedAutoreleasePool pool;
306         frame();
307         utils::USleep(16000);
308     }
309 
310     // TODO release stuff
311 }
312