• 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 <cstdio>
23 #include <cstdlib>
24 #include <vector>
25 
26 wgpu::Device device;
27 wgpu::Queue queue;
28 wgpu::SwapChain swapchain;
29 wgpu::RenderPipeline pipeline;
30 wgpu::BindGroup bindGroup;
31 wgpu::Buffer ubo;
32 
RandomFloat(float min,float max)33 float RandomFloat(float min, float max) {
34     float zeroOne = rand() / float(RAND_MAX);
35     return zeroOne * (max - min) + min;
36 }
37 
38 constexpr size_t kNumTriangles = 10000;
39 
40 // Aligned as minUniformBufferOffsetAlignment
41 struct alignas(256) ShaderData {
42     float scale;
43     float time;
44     float offsetX;
45     float offsetY;
46     float scalar;
47     float scalarOffset;
48 };
49 
50 static std::vector<ShaderData> shaderData;
51 
init()52 void init() {
53     device = CreateCppDawnDevice();
54 
55     queue = device.GetQueue();
56     swapchain = GetSwapChain(device);
57     swapchain.Configure(GetPreferredSwapChainTextureFormat(), wgpu::TextureUsage::RenderAttachment,
58                         640, 480);
59 
60     wgpu::ShaderModule vsModule = utils::CreateShaderModule(device, R"(
61         [[block]] struct Constants {
62             scale : f32;
63             time : f32;
64             offsetX : f32;
65             offsetY : f32;
66             scalar : f32;
67             scalarOffset : f32;
68         };
69         [[group(0), binding(0)]] var<uniform> c : Constants;
70 
71         struct VertexOut {
72             [[location(0)]] v_color : vec4<f32>;
73             [[builtin(position)]] Position : vec4<f32>;
74         };
75 
76         [[stage(vertex)]] fn main([[builtin(vertex_index)]] VertexIndex : u32) -> VertexOut {
77             var positions : array<vec4<f32>, 3> = array<vec4<f32>, 3>(
78                 vec4<f32>( 0.0,  0.1, 0.0, 1.0),
79                 vec4<f32>(-0.1, -0.1, 0.0, 1.0),
80                 vec4<f32>( 0.1, -0.1, 0.0, 1.0)
81             );
82 
83             var colors : array<vec4<f32>, 3> = array<vec4<f32>, 3>(
84                 vec4<f32>(1.0, 0.0, 0.0, 1.0),
85                 vec4<f32>(0.0, 1.0, 0.0, 1.0),
86                 vec4<f32>(0.0, 0.0, 1.0, 1.0)
87             );
88 
89             var position : vec4<f32> = positions[VertexIndex];
90             var color : vec4<f32> = colors[VertexIndex];
91 
92             // TODO(dawn:572): Revisit once modf has been reworked in WGSL.
93             var fade : f32 = c.scalarOffset + c.time * c.scalar / 10.0;
94             fade = fade - floor(fade);
95             if (fade < 0.5) {
96                 fade = fade * 2.0;
97             } else {
98                 fade = (1.0 - fade) * 2.0;
99             }
100 
101             var xpos : f32 = position.x * c.scale;
102             var ypos : f32 = position.y * c.scale;
103             let angle : f32 = 3.14159 * 2.0 * fade;
104             let xrot : f32 = xpos * cos(angle) - ypos * sin(angle);
105             let yrot : f32 = xpos * sin(angle) + ypos * cos(angle);
106             xpos = xrot + c.offsetX;
107             ypos = yrot + c.offsetY;
108 
109             var output : VertexOut;
110             output.v_color = vec4<f32>(fade, 1.0 - fade, 0.0, 1.0) + color;
111             output.Position = vec4<f32>(xpos, ypos, 0.0, 1.0);
112             return output;
113         })");
114 
115     wgpu::ShaderModule fsModule = utils::CreateShaderModule(device, R"(
116         [[stage(fragment)]] fn main([[location(0)]] v_color : vec4<f32>)
117                                  -> [[location(0)]] vec4<f32> {
118             return v_color;
119         })");
120 
121     wgpu::BindGroupLayout bgl = utils::MakeBindGroupLayout(
122         device, {{0, wgpu::ShaderStage::Vertex, wgpu::BufferBindingType::Uniform, true}});
123 
124     utils::ComboRenderPipelineDescriptor descriptor;
125     descriptor.layout = utils::MakeBasicPipelineLayout(device, &bgl);
126     descriptor.vertex.module = vsModule;
127     descriptor.cFragment.module = fsModule;
128     descriptor.cTargets[0].format = GetPreferredSwapChainTextureFormat();
129 
130     pipeline = device.CreateRenderPipeline(&descriptor);
131 
132     shaderData.resize(kNumTriangles);
133     for (auto& data : shaderData) {
134         data.scale = RandomFloat(0.2f, 0.4f);
135         data.time = 0.0;
136         data.offsetX = RandomFloat(-0.9f, 0.9f);
137         data.offsetY = RandomFloat(-0.9f, 0.9f);
138         data.scalar = RandomFloat(0.5f, 2.0f);
139         data.scalarOffset = RandomFloat(0.0f, 10.0f);
140     }
141 
142     wgpu::BufferDescriptor bufferDesc;
143     bufferDesc.size = kNumTriangles * sizeof(ShaderData);
144     bufferDesc.usage = wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::Uniform;
145     ubo = device.CreateBuffer(&bufferDesc);
146 
147     bindGroup = utils::MakeBindGroup(device, bgl, {{0, ubo, 0, sizeof(ShaderData)}});
148 }
149 
frame()150 void frame() {
151     wgpu::TextureView backbufferView = swapchain.GetCurrentTextureView();
152 
153     static int f = 0;
154     f++;
155     for (auto& data : shaderData) {
156         data.time = f / 60.0f;
157     }
158     queue.WriteBuffer(ubo, 0, shaderData.data(), kNumTriangles * sizeof(ShaderData));
159 
160     utils::ComboRenderPassDescriptor renderPass({backbufferView});
161     wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
162     {
163         wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPass);
164         pass.SetPipeline(pipeline);
165 
166         for (size_t i = 0; i < kNumTriangles; i++) {
167             uint32_t offset = i * sizeof(ShaderData);
168             pass.SetBindGroup(0, bindGroup, 1, &offset);
169             pass.Draw(3);
170         }
171 
172         pass.EndPass();
173     }
174 
175     wgpu::CommandBuffer commands = encoder.Finish();
176     queue.Submit(1, &commands);
177     swapchain.Present();
178     DoFlush();
179     fprintf(stderr, "frame %i\n", f);
180 }
181 
main(int argc,const char * argv[])182 int main(int argc, const char* argv[]) {
183     if (!InitSample(argc, argv)) {
184         return 1;
185     }
186     init();
187 
188     while (!ShouldQuit()) {
189         utils::ScopedAutoreleasePool pool;
190         frame();
191         utils::USleep(16000);
192     }
193 
194     // TODO release stuff
195 }
196