23 void init(WGPUDevice device)
26 initBindGroups(device);
35 template <
typename Camera>
36 void update(WGPUDevice device, WGPUCommandEncoder encoder,
37 WGPUTextureView render_texture, WGPUTextureView depth_texture,
41 uniform_.projection = camera.projection();
43 uniform_.color = color_;
44 wgpuQueueWriteBuffer(compute::queue(device), uniform_buffer_, 0, &uniform_,
48 auto render_pass_desc = renderPassDesc(render_texture, depth_texture);
49 WGPURenderPassEncoder render_pass =
50 wgpuCommandEncoderBeginRenderPass(encoder, &render_pass_desc);
53 wgpuRenderPassEncoderSetPipeline(render_pass, pipeline_);
56 wgpuRenderPassEncoderSetBindGroup(render_pass, 0, bind_group_, 0,
nullptr);
59 wgpuRenderPassEncoderSetVertexBuffer(render_pass, 0, vertex_buffer_, 0,
63 wgpuRenderPassEncoderSetIndexBuffer(render_pass, index_buffer_,
64 WGPUIndexFormat_Uint32, 0, WGPU_WHOLE_SIZE);
66 wgpuRenderPassEncoderDrawIndexed(render_pass, triangles_.indices.size(), 1, 0, 0, 0);
68 wgpuRenderPassEncoderEnd(render_pass);
69 wgpuRenderPassEncoderRelease(render_pass);
98 virtual WGPUBindGroupLayout bindGroupLayout(WGPUDevice device)
100 std::array<WGPUBindGroupLayoutEntry, 1> binding_layout{};
103 compute::setDefault(binding_layout[0]);
104 binding_layout[0].binding = 0;
105 binding_layout[0].visibility = WGPUShaderStage_Vertex | WGPUShaderStage_Fragment;
106 binding_layout[0].buffer.type = WGPUBufferBindingType_Uniform;
107 binding_layout[0].buffer.minBindingSize =
sizeof(uniform_);
110 bind_group_layout_desc = {};
111 bind_group_layout_desc.label =
"Compute Bind Group Layout";
112 bind_group_layout_desc.nextInChain =
nullptr;
113 bind_group_layout_desc.entryCount = binding_layout.size();
114 bind_group_layout_desc.entries = binding_layout.data();
116 return wgpuDeviceCreateBindGroupLayout(device, &bind_group_layout_desc);
119 virtual void initBindGroups(WGPUDevice device)
121 std::array<WGPUBindGroupEntry, 1> binding{};
124 binding[0].nextInChain =
nullptr;
125 binding[0].binding = 0;
126 binding[0].buffer = uniform_buffer_;
127 binding[0].offset = 0;
128 binding[0].size =
sizeof(uniform_);
131 bind_group_desc = {};
132 bind_group_desc.nextInChain =
nullptr;
133 bind_group_layout_ = bindGroupLayout(device);
134 bind_group_desc.layout = bind_group_layout_;
136 bind_group_desc.entryCount = binding.size();
137 bind_group_desc.entries = binding.data();
139 bind_group_ = wgpuDeviceCreateBindGroup(device, &bind_group_desc);
142 virtual WGPURenderPassColorAttachment renderPassColorAttachment(
143 WGPUTextureView render_texture)
145 WGPURenderPassColorAttachment color_attachment = {};
147 color_attachment.view = render_texture;
148 color_attachment.resolveTarget =
nullptr;
149 color_attachment.loadOp = WGPULoadOp_Load;
150 color_attachment.storeOp = WGPUStoreOp_Store;
151 color_attachment.clearValue = WGPUColor{0.5, 0.5, 0.5, 1.0};
153 return color_attachment;
156 virtual WGPURenderPassDepthStencilAttachment depthAttachment(
157 WGPUTextureView depth_texture)
159 WGPURenderPassDepthStencilAttachment depth_attachment = {};
161 depth_attachment.view = depth_texture;
162 depth_attachment.depthClearValue = 1.0;
163 depth_attachment.depthLoadOp = WGPULoadOp_Load;
164 depth_attachment.depthStoreOp = WGPUStoreOp_Store;
166 depth_attachment.depthReadOnly =
false;
168 depth_attachment.stencilClearValue = 0.0;
169 depth_attachment.stencilLoadOp = WGPULoadOp_Clear;
170 depth_attachment.stencilStoreOp = WGPUStoreOp_Store;
171 depth_attachment.stencilReadOnly =
true;
173 return depth_attachment;
176 virtual WGPURenderPassDescriptor renderPassDesc(WGPUTextureView render_texture,
177 WGPUTextureView depth_texture)
179 WGPURenderPassDescriptor render_pass_desc = {};
181 render_pass_desc.nextInChain =
nullptr;
182 render_pass_desc.depthStencilAttachment =
nullptr;
183 render_pass_desc.colorAttachmentCount = 1;
184 color_attachment = renderPassColorAttachment(render_texture);
185 render_pass_desc.colorAttachments = &color_attachment;
186 render_pass_desc.timestampWrites =
nullptr;
187 depth_attachment = depthAttachment(depth_texture);
188 render_pass_desc.depthStencilAttachment = &depth_attachment;
190 return render_pass_desc;
193 virtual WGPUPipelineLayout pipelineLayout(WGPUDevice device)
195 pipeline_layout_desc = {};
197 pipeline_layout_desc.nextInChain =
nullptr;
198 pipeline_layout_desc.bindGroupLayoutCount = 1;
199 pipeline_layout_desc.bindGroupLayouts = &bind_group_layout_;
201 return wgpuDeviceCreatePipelineLayout(device, &pipeline_layout_desc);
204 virtual WGPURenderPipelineDescriptor pipelineDesc(WGPUDevice device)
206 WGPURenderPipelineDescriptor pipeline_desc;
207 pipeline_desc.layout = pipelineLayout(device);
211 pipeline_desc.primitive.frontFace = WGPUFrontFace_CCW;
216 pipeline_desc.primitive.cullMode = WGPUCullMode_None;
218 pipeline_desc.multisample.count = 1;
221 pipeline_desc.multisample.mask = ~0u;
224 pipeline_desc.multisample.alphaToCoverageEnabled =
false;
227 depth_stencil_state = {};
228 depth_stencil_state.format = WGPUTextureFormat_Depth32Float;
229 depth_stencil_state.depthWriteEnabled =
true;
230 depth_stencil_state.depthCompare = WGPUCompareFunction_Less;
231 depth_stencil_state.stencilFront.compare = WGPUCompareFunction_Always;
232 depth_stencil_state.stencilBack.compare = WGPUCompareFunction_Always;
233 depth_stencil_state.stencilReadMask = 0xFFFFFFFF;
234 depth_stencil_state.stencilWriteMask = 0xFFFFFFFF;
236 pipeline_desc.depthStencil = &depth_stencil_state;
239 WGPUVertexState vertexState = {};
240 vertexState.module = shader_module_;
241 vertexState.entryPoint =
"vertMain";
242 vertexState.bufferCount = 1;
243 vertexState.buffers = &vertex_buffer_layout;
245 pipeline_desc.vertex = vertexState;
249 color_target.format =
250 WGPUTextureFormat_BGRA8UnormSrgb;
251 color_target.writeMask = WGPUColorWriteMask_All;
254 fragment_state.module = shader_module_;
255 fragment_state.entryPoint =
"fragMain";
256 fragment_state.constantCount = 0;
257 fragment_state.constants =
nullptr;
258 fragment_state.targetCount = 1;
259 fragment_state.targets = &color_target;
261 pipeline_desc.fragment = &fragment_state;
262 pipeline_desc.primitive.topology = WGPUPrimitiveTopology_TriangleList;
263 pipeline_desc.multisample.count = 1;
264 pipeline_desc.multisample.mask = ~0u;
265 pipeline_desc.multisample.alphaToCoverageEnabled =
false;
267 return pipeline_desc;
270 virtual void initPipeline(WGPUDevice device)
275 pipeline_desc = pipelineDesc(device);
276 pipeline_ = wgpuDeviceCreateRenderPipeline(device, &pipeline_desc);
279 virtual void initBuffers(WGPUDevice device)
281 initVertexBuffer(device);
282 initIndexBuffer(device);
283 initUniformBuffer(device);
286 virtual void initVertexBuffer(WGPUDevice device)
288 vertex_buffer_desc = {};
289 vertex_buffer_desc.usage = WGPUBufferUsage_Vertex | WGPUBufferUsage_CopyDst;
290 vertex_buffer_desc.size = triangles_.vertices.size() *
sizeof(
Vertex);
291 vertex_buffer_desc.mappedAtCreation =
true;
293 vertex_buffer_ = wgpuDeviceCreateBuffer(device, &vertex_buffer_desc);
297 wgpuBufferGetMappedRange(vertex_buffer_, 0, vertex_buffer_desc.size);
298 memcpy(mapped_data, triangles_.vertices.data(), vertex_buffer_desc.size);
299 wgpuBufferUnmap(vertex_buffer_);
303 WGPUVertexAttribute position_attr = {};
304 position_attr.shaderLocation = 0;
305 position_attr.format = WGPUVertexFormat_Float32x3;
306 position_attr.offset = offsetof(
Vertex, pos);
309 WGPUVertexAttribute normal_attr = {};
310 normal_attr.shaderLocation = 1;
311 normal_attr.format = WGPUVertexFormat_Float32x3;
312 normal_attr.offset = offsetof(
Vertex, normal);
314 vertex_buffer_layout = {};
315 vertex_buffer_layout.arrayStride =
sizeof(
Vertex);
316 vertex_buffer_layout.attributeCount = 2;
317 vertex_attributes = {position_attr, normal_attr};
318 vertex_buffer_layout.attributes = vertex_attributes.data();
321 virtual void initIndexBuffer(WGPUDevice device)
323 index_buffer_desc = {};
324 index_buffer_desc.usage = WGPUBufferUsage_Index | WGPUBufferUsage_CopyDst;
325 index_buffer_desc.size = triangles_.indices.size() *
sizeof(uint32_t);
326 index_buffer_desc.mappedAtCreation =
true;
328 index_buffer_ = wgpuDeviceCreateBuffer(device, &index_buffer_desc);
332 wgpuBufferGetMappedRange(index_buffer_, 0, index_buffer_desc.size);
333 memcpy(mapped_data, triangles_.indices.data(), index_buffer_desc.size);
334 wgpuBufferUnmap(index_buffer_);
337 virtual void initUniformBuffer(WGPUDevice device)
339 uniform_buffer_desc = {};
340 uniform_buffer_desc.mappedAtCreation =
false;
341 uniform_buffer_desc.size =
sizeof(uniform_);
342 uniform_buffer_desc.usage = WGPUBufferUsage_CopyDst | WGPUBufferUsage_Uniform;
343 uniform_buffer_desc.mappedAtCreation =
false;
344 uniform_buffer_ = wgpuDeviceCreateBuffer(device, &uniform_buffer_desc);
354 static_assert(
sizeof(
UBO) % 16 == 0);
358 WGPURenderPipeline pipeline_ =
nullptr;
359 WGPURenderPipelineDescriptor pipeline_desc = {};
362 WGPUBuffer vertex_buffer_ =
nullptr;
363 WGPUBufferDescriptor vertex_buffer_desc = {};
364 WGPUBuffer index_buffer_ =
nullptr;
365 WGPUBufferDescriptor index_buffer_desc{};
366 WGPUBuffer uniform_buffer_ =
nullptr;
367 WGPUBufferDescriptor uniform_buffer_desc{};
369 WGPUBindGroupLayout bind_group_layout_ =
nullptr;
370 WGPUBindGroup bind_group_ =
nullptr;
373 WGPURenderPassColorAttachment color_attachment;
374 WGPURenderPassDepthStencilAttachment depth_attachment;
375 WGPUDepthStencilState depth_stencil_state;
376 WGPUVertexBufferLayout vertex_buffer_layout;
377 WGPUFragmentState fragment_state{};
378 std::vector<WGPUVertexAttribute> vertex_attributes;
379 WGPUColorTargetState color_target;
380 WGPUBindGroupLayoutDescriptor bind_group_layout_desc{};
381 WGPUBindGroupDescriptor bind_group_desc{};
382 WGPUPipelineLayoutDescriptor pipeline_layout_desc = {};
385 WGPUShaderModule shader_module_ =
nullptr;