Cogs.Core
ContextWebGPU.cpp
1#include "ContextWebGPU.h"
2
3#include "GraphicsDeviceWebGPU.h"
4#include "PipelineStatesWebGPU.h"
5#include "Foundation/Logging/Logger.h"
6
7namespace {
8 Cogs::Logging::Log logger = Cogs::Logging::getLogger("ContextWebGPU");
9
10 WGPULoadOp ConvWebGPULoadOp(Cogs::LoadOp load_op)
11 {
12 switch(load_op){
13 case Cogs::LoadOp::Undefined: return WGPULoadOp_Undefined;
14 case Cogs::LoadOp::Clear: return WGPULoadOp_Clear;
15 case Cogs::LoadOp::Load: return WGPULoadOp_Load;
16 }
17 return WGPULoadOp_Undefined;
18 }
19 WGPUStoreOp ConvWebGPUStoreOp(Cogs::StoreOp store_op)
20 {
21 switch(store_op){
22 case Cogs::StoreOp::Undefined: return WGPUStoreOp_Undefined;
23 case Cogs::StoreOp::Store: return WGPUStoreOp_Store;
24 case Cogs::StoreOp::Discard: return WGPUStoreOp_Discard;
25 }
26 return WGPUStoreOp_Undefined;
27 }
28}
29
30namespace Cogs{
31
32 void ContextWebGPU::initialize(GraphicsDeviceWebGPU *graphicsDeviceIn)
33 {
34 graphicsDevice = graphicsDeviceIn;
35 }
36
37 void ContextWebGPU::frameStatisticsConfigure(bool /*enable*/)
38 {
39 //assert(false); // TODO
40 }
41
42 void ContextWebGPU::signal(FenceHandle /*fenceHandle*/)
43 {
44 // assert(false); // TODO
45 }
46
47 void ContextWebGPU::clearRenderTarget(const float* value)
48 {
49 assert(!inRenderPass);
50 for(size_t i=0; i<sizeof(clearColor)/sizeof(clearColor[0]); i++){
51 clearColor[i].r = value[0];
52 clearColor[i].g = value[1];
53 clearColor[i].b = value[2];
54 clearColor[i].a = value[3];
55 }
56 do_clear_render_target = true;
57 update_render_target = true;
58 }
59
60 void ContextWebGPU::clearRenderTarget(const float** values, const int numvalues)
61 {
62 assert(!inRenderPass);
63 for(int i=0; i<numvalues; i++){
64 clearColor[i].r = values[i][0];
65 clearColor[i].g = values[i][1];
66 clearColor[i].b = values[i][2];
67 clearColor[i].a = values[i][3];
68 }
69 for(size_t i=numvalues; i<sizeof(clearColor)/sizeof(clearColor[0]); i++){
70 clearColor[i] = {};
71 }
72 do_clear_render_target = true;
73 update_render_target = true;
74 }
75
76 void ContextWebGPU::clearDepth(const float depth)
77 {
78 assert(!inRenderPass);
79 clearDepthVal = depth;
80 do_clear_depth = true;
81 update_render_target = true;
82 }
83
85 {
86 assert(renderPassEncoder == 0);
87 assert(computePassEncoder == 0);
88 assert(!inRenderPass);
89 inRenderPass = true;
90 update_render_target = false;
91
92 renderTargetHandle = info.renderTargetHandle;
93 depthStencilHandle = info.depthStencilHandle;
94
95 WGPURenderPassColorAttachment color_attachment[8] = {};
96 WGPURenderPassDepthStencilAttachment ds_attachment = {};
97 uint32_t color_attachment_count = 0;
98 uint32_t ds_attachment_count = 0;
99
100 const char *name = nullptr;
101 if (HandleIsValid(info.renderTargetHandle) || HandleIsValid(info.depthStencilHandle)) {
102 name = "Custom Render Pass";
103 if(HandleIsValid(info.renderTargetHandle)){
104 RenderTargetWebGPU &target = graphicsDevice->renderTargets.render_targets[info.renderTargetHandle];
105 for(size_t i=0; i<target.count; i++){
106 WGPURenderPassColorAttachment &att = color_attachment[i];
107 att.view = target.view[i];
108#ifndef EMSCRIPTEN
109 att.depthSlice = WGPU_DEPTH_SLICE_UNDEFINED;
110#endif
111 if(info.resolveHandle[i]){
112 att.resolveTarget = graphicsDevice->textures.textureViews[info.resolveHandle[i]].texture_view;
113 }
114 else{
115 att.resolveTarget = nullptr;
116 }
117 att.loadOp = ConvWebGPULoadOp(info.loadOp[i]);
118 att.storeOp = ConvWebGPUStoreOp(info.storeOp[i]);
119 att.clearValue.r = info.clearValue[i][0];
120 att.clearValue.g = info.clearValue[i][1];
121 att.clearValue.b = info.clearValue[i][2];
122 att.clearValue.a = info.clearValue[i][3];
123 }
124 color_attachment_count = target.count;
125 }
126 if(HandleIsValid(info.depthStencilHandle)){
127 DepthStencilTargetWebGPU &target = graphicsDevice->renderTargets.depth_stencil_targets[info.depthStencilHandle];
128 WGPURenderPassDepthStencilAttachment &att = ds_attachment;
129 att.view = target.view;
130 att.depthLoadOp = ConvWebGPULoadOp(info.depthLoadOp);
131 att.depthStoreOp = ConvWebGPUStoreOp(info.depthStoreOp);
132 att.depthClearValue = info.depthClearValue;
133 att.depthReadOnly = info.depthReadOnly;
134 att.stencilLoadOp = WGPULoadOp_Undefined;
135 att.stencilStoreOp = WGPUStoreOp_Undefined;
136 att.stencilClearValue = 0;
137 att.stencilReadOnly = false;
138 ds_attachment_count = 1;
139 }
140 }
141 else{
142 name = "Default Render Pass";
143 SwapChainWebGPU &defaultSwapChain = graphicsDevice->defaultSwapChain;
144 if(defaultSwapChain.samples > 1){
145 color_attachment[0].view = defaultSwapChain.colorBufferView;
146 color_attachment[0].resolveTarget = defaultSwapChain.resolveView;
147 }
148 else{
149 color_attachment[0].view = defaultSwapChain.resolveView;
150 }
151#ifndef EMSCRIPTEN
152 color_attachment[0].depthSlice = WGPU_DEPTH_SLICE_UNDEFINED;
153#endif
154 color_attachment[0].loadOp = ConvWebGPULoadOp(info.loadOp[0]);
155 color_attachment[0].storeOp = ConvWebGPUStoreOp(info.storeOp[0]);
156 color_attachment[0].clearValue.r = info.clearValue[0][0];
157 color_attachment[0].clearValue.g = info.clearValue[0][1];
158 color_attachment[0].clearValue.b = info.clearValue[0][2];
159 color_attachment[0].clearValue.a = info.clearValue[0][3];
160 color_attachment_count = 1;
161
162 ds_attachment.view = defaultSwapChain.depthBufferView;
163 ds_attachment.depthLoadOp = ConvWebGPULoadOp(info.depthLoadOp);
164 ds_attachment.depthStoreOp = ConvWebGPUStoreOp(info.depthStoreOp);
165 ds_attachment.depthClearValue = info.depthClearValue;
166 ds_attachment.depthReadOnly = info.depthReadOnly;
167 ds_attachment.stencilLoadOp = WGPULoadOp_Undefined;
168 ds_attachment.stencilStoreOp = WGPUStoreOp_Undefined;
169 ds_attachment.stencilClearValue = 0;
170 ds_attachment.stencilReadOnly = false;
171 ds_attachment_count = 1;
172 }
173
174 WGPURenderPassDescriptor render_pass_desc = {};
175 render_pass_desc.label = name;
176 if(color_attachment_count){
177 render_pass_desc.colorAttachmentCount = color_attachment_count;
178 render_pass_desc.colorAttachments = color_attachment;
179 }
180 if(ds_attachment_count){
181 render_pass_desc.depthStencilAttachment = &ds_attachment;
182 }
183 render_pass_desc.occlusionQuerySet = nullptr;
184 // render_pass_desc.timestampWriteCount = 0;
185 render_pass_desc.timestampWrites = nullptr;
186 renderPassEncoder = wgpuCommandEncoderBeginRenderPass(graphicsDevice->commandEncoder, &render_pass_desc);
187 }
189 {
190 assert(renderPassEncoder);
191 assert(inRenderPass);
192 inRenderPass = false;
193 wgpuRenderPassEncoderEnd(renderPassEncoder);
194 renderPassEncoder = 0;
195 update_render_target = true;
196 }
197
199 {
200 if(HandleIsValid(rt_handle))
201 renderTargetHandle = rt_handle;
202 else
203 renderTargetHandle = {};
204 if(HandleIsValid(ds_handle))
205 depthStencilHandle = ds_handle;
206 else
207 depthStencilHandle = {};
208 rasterizeStateHandle = {};
209 blendStateHandle = {};
210 assert(do_clear_render_target == false); // Maybe do update render pass to force clear?
211 assert(do_clear_depth == false); // Maybe do update render pass to force clear?
212 do_clear_render_target = false;
213 do_clear_depth = false;
214 update_render_target = true;
215 }
216
217 void ContextWebGPU::setViewport(const float x, const float y, const float width, const float height)
218 {
219 updateRenderPass();
220 float minDepth = 0.0f; // TODO
221 float maxDepth = 1.0f; // TODO
222 wgpuRenderPassEncoderSetViewport(renderPassEncoder, x, y, width, height, minDepth, maxDepth);
223 }
224
225 void ContextWebGPU::setScissor(const int x, const int y, const int width, const int height)
226 {
227 updateRenderPass();
228 int w, h;
229 graphicsDevice->getSize(w, h); // TODO
230 int xx = glm::clamp(x, 0, w);
231 int yy = glm::clamp(y, 0, h);
232 int ww = glm::clamp(width, 0, w-xx);
233 int hh = glm::clamp(height, 0, h-yy);
234 wgpuRenderPassEncoderSetScissorRect(renderPassEncoder, xx, yy, ww, hh);
235 }
236
238 {
239 if(HandleIsValid(handle))
240 depthStencilStateHandle = handle;
241 else
242 depthStencilStateHandle = {};
243 }
244
245 void ContextWebGPU::setBlendState(const BlendStateHandle handle, const float *constants)
246 {
247 updateRenderPass();
248 if(HandleIsValid(handle))
249 blendStateHandle = handle;
250 else
251 blendStateHandle = {};
252 WGPUColor color; // Emulate dx11 with 1.0f constants if not set
253 if(constants){
254 color.r = constants[0];
255 color.g = constants[1];
256 color.b = constants[2];
257 color.a = constants[3];
258 }
259 else{
260 color.r = 1.0f;
261 color.g = 1.0f;
262 color.b = 1.0f;
263 color.a = 1.0f;
264 }
265 wgpuRenderPassEncoderSetBlendConstant(renderPassEncoder, &color);
266 }
267
269 {
270 if(HandleIsValid(handle))
271 rasterizeStateHandle = handle;
272 else
273 rasterizeStateHandle = {};
274 }
275
276 void ContextWebGPU::setDefaults() {
277 rasterizeStateHandle = {};
278 depthStencilStateHandle = {};
279 blendStateHandle = {};
280 }
281
283 {
284 if(HandleIsValid(handle))
285 effect = handle;
286 else
287 effect = {};
288 inputLayoutHandle = {};
289 descriptors.clear();
290 update_descriptors = true;
291 }
292
293 // TODO remove these:
294 void ContextWebGPU::setVariable(const EffectVariableHandle /*index*/, const uint8_t* /*data*/, size_t /*size*/) { assert(false); }
295 void ContextWebGPU::setScalarVariable(const StringView& /*name*/, const float /*value*/) { assert(false); }
296 void ContextWebGPU::setScalarVariable(const StringView& /*name*/, int /*value*/) { assert(false); }
297 void ContextWebGPU::setScalarVariable(const EffectVariableHandle /*variableHandle*/, const float /*value*/) { assert(false); }
298 void ContextWebGPU::setScalarVariable(const EffectVariableHandle /*variableHandle*/, const float* /*value*/, size_t /*count*/) { assert(false); }
299 void ContextWebGPU::setScalarVariable(const EffectVariableHandle /*variableHandle*/, int /*value*/) { assert(false); }
300 void ContextWebGPU::setScalarVariable(const EffectVariableHandle /*variableHandle*/, const int* /*value*/, size_t /*count*/) { assert(false); }
301 void ContextWebGPU::setVector2Variable(const StringView& /*name*/, const float* /*value*/) { assert(false); }
302 void ContextWebGPU::setVector2Variable(const EffectVariableHandle /*variableHandle*/, const float* /*value*/, size_t /*count*/) { assert(false); }
303 void ContextWebGPU::setVector3Variable(const StringView& /*name*/, const float* /*value*/) { assert(false); }
304 void ContextWebGPU::setVector3Variable(const EffectVariableHandle /*variableHandle*/, const float* /*value*/, size_t /*count*/) { assert(false); }
305 void ContextWebGPU::setVector4Variable(const StringView& /*name*/, const float* /*value*/) { assert(false); }
306 void ContextWebGPU::setVector4Variable(const EffectVariableHandle /*variableHandle*/, const float* /*value*/, size_t /*count*/) { assert(false); }
307 void ContextWebGPU::setVector4Variable(const EffectVariableHandle /*variableHandle*/, const int* /*value*/, size_t /*count*/) { assert(false); }
308 void ContextWebGPU::setMatrixVariable(const StringView& /*name*/, const float* /*value*/) { assert(false); }
309 void ContextWebGPU::setMatrixVariable(const EffectVariableHandle /*variableHandle*/, const float* /*value*/) { assert(false); }
310 void ContextWebGPU::setMatrixVariable(const EffectVariableHandle /*variableHandle*/, const float* /*value*/, size_t /*count*/) { assert(false); }
311
312 void ContextWebGPU::setTexture(const StringView& name, unsigned int unit, TextureHandle textureHandle)
313 {
314 setTexture(getEffects()->getTextureBinding(getCurrentEffect(), name, unit), textureHandle);
315 }
316
318 {
319 // WebGPU does not support setting invalid textures, so we remove the binding from the descriptor.
320 // If it is needed we will detect the issue when creatng the bindgroup if the texture is required
321 if (!HandleIsValid(handle)) {
322 descriptors.erase((uint32_t)binding.handle);
323 return;
324 }
325 TextureWebGPU texture = graphicsDevice->textures.textures[handle];
326 WGPUBindGroupEntry bg_ent = {};
327 bg_ent.binding = (uint32_t)binding.handle;
328 bg_ent.buffer = nullptr;
329 bg_ent.offset = 0;
330 bg_ent.size = 0;
331 bg_ent.sampler = nullptr;
332 bg_ent.textureView = texture.texture_view;
333 descriptors[bg_ent.binding] = bg_ent;
334 update_descriptors = true;
335 }
336
337 void ContextWebGPU::setTexture(const StringView& name, TextureViewHandle textureViewHandle)
338 {
339 setTexture(getEffects()->getTextureBinding(getCurrentEffect(), name, 1), textureViewHandle);
340 }
341
342 void ContextWebGPU::setTexture(const TextureBindingHandle binding, TextureViewHandle handle)
343 {
344 // WebGPU does not support setting invalid textures, so we remove the binding from the descriptor.
345 // If it is needed we will detect the issue when creatng the bindgroup if the texture is required
346 if (!HandleIsValid(handle)) {
347 descriptors.erase((uint32_t)binding.handle);
348 return;
349 }
350 TextureViewWebGPU texture_view = graphicsDevice->textures.textureViews[handle];
351 WGPUBindGroupEntry bg_ent = {};
352 bg_ent.binding = (uint32_t)binding.handle;
353 bg_ent.buffer = nullptr;
354 bg_ent.offset = 0;
355 bg_ent.size = 0;
356 bg_ent.sampler = nullptr;
357 bg_ent.textureView = texture_view.texture_view;
358 descriptors[bg_ent.binding] = bg_ent;
359 update_descriptors = true;
360 }
361
362 void ContextWebGPU::setSamplerState(const StringView& name, unsigned int unit, SamplerStateHandle handle)
363 {
364 setSamplerState(getEffects()->getSamplerStateBinding(getCurrentEffect(), name, unit), handle);
365 }
366
368 {
369 // WebGPU does not support setting invalid samplers, so we remove the binding from the descriptor.
370 // If it is needed we will detect the issue when creatng the bindgroup if the sampler is required
371 if (!HandleIsValid(handle)) {
372 descriptors.erase((uint32_t)binding.handle);
373 return;
374 }
375 if (!HandleIsValid(binding)) {
376 return;
377 }
378 SamplerStateWebGPU sampler = graphicsDevice->textures.samplerStates[handle];
379 WGPUBindGroupEntry bg_ent = {};
380 bg_ent.binding = (uint32_t)binding.handle;
381 bg_ent.buffer = nullptr;
382 bg_ent.offset = 0;
383 bg_ent.size = 0;
384 bg_ent.sampler = sampler.sampler;
385 bg_ent.textureView = nullptr;
386 descriptors[bg_ent.binding] = bg_ent;
387 //WGPUBindGroupLayoutEntry bg_le{
388 // .binding = (uint32_t)binding.handle,
389 // .sampler = {
390 // .type = WGPUSamplerBindingType_Filtering,
391 // }
392 //};
393 update_descriptors = true;
394 }
395
397 {
398 if(HandleIsValid(handle))
399 inputLayoutHandle = handle;
400 else
401 inputLayoutHandle = {};
402 }
403
404 void ContextWebGPU::setVertexBuffers(const VertexBufferHandle* vertexBufferHandles, const size_t count, const uint32_t* /*strides*/, const uint32_t* offsets)
405 {
406 updateRenderPass();
407 for(size_t i=0; i<count; i++){
408 BufferWebGPU buffer = graphicsDevice->buffers.buffers[(BufferHandle)vertexBufferHandles[i].handle];
409 uint32_t slot = (uint32_t)i;
410 // uint32_t stride = strides ? strides[i] : 0;
411 uint32_t offset = offsets ? offsets[i] : 0;
412 wgpuRenderPassEncoderSetVertexBuffer(renderPassEncoder, slot, buffer.buffer, offset, buffer.size-offset);
413 }
414 }
415
416 void ContextWebGPU::setVertexBuffers(const VertexBufferHandle * handles, const size_t count)
417 {
418 setVertexBuffers(handles, count, nullptr, nullptr);
419 }
420
421 void ContextWebGPU::setIndexBuffer(IndexBufferHandle bufferHandle, uint32_t stride, uint32_t offset_in)
422 {
423 if (bufferHandle == IndexBufferHandle::NoHandle) {
424 return;
425 }
426 updateRenderPass();
427 WGPUIndexFormat format = (stride == 2) ? WGPUIndexFormat_Uint16 : WGPUIndexFormat_Uint32;
428 uint64_t offset = offset_in;
429 BufferWebGPU buffer = graphicsDevice->buffers.buffers[(BufferHandle)bufferHandle.handle];
430 wgpuRenderPassEncoderSetIndexBuffer(renderPassEncoder, buffer.buffer, format, offset, buffer.size);
431 }
432
434 {
435 assert(false); // TODO
436 }
437
438 void ContextWebGPU::setConstantBuffer(const StringView& name, const BufferHandle bufferHandle, const uint32_t offset, const uint32_t size)
439 {
440 setConstantBuffer(getEffects()->getConstantBufferBinding(getCurrentEffect(), name), bufferHandle, offset, size);
441 }
442
443 void ContextWebGPU::setConstantBuffer(const ConstantBufferBindingHandle binding, const BufferHandle handle, const uint32_t offset, const uint32_t size)
444 {
445 // WebGPU does not support setting invalid buffers, so we remove the binding from the descriptor.
446 // If it is needed we will detect the issue when creatng the bindgroup if the buffer is required
447 if (!HandleIsValid(handle)) {
448 descriptors.erase((uint32_t)binding.handle);
449 return;
450 }
451 if (!HandleIsValid(binding)) {
452 return;
453 }
454
455 BufferWebGPU &buffer = graphicsDevice->buffers.buffers[handle];
456 WGPUBindGroupEntry bg_ent = {};
457 bg_ent.binding = (uint32_t)binding.handle;
458 bg_ent.buffer = buffer.buffer;
459 bg_ent.offset = offset;
460 bg_ent.size = (size == ~0u) ? WGPU_WHOLE_SIZE : size;
461 bg_ent.sampler = nullptr;
462 bg_ent.textureView = nullptr;
463 descriptors[bg_ent.binding] = bg_ent;
464 update_descriptors = true;
465 }
466
467 void ContextWebGPU::setBuffer(const StringView& name, BufferHandle bufferHandle)
468 {
469 auto binding = getEffects()->getBufferBinding(getCurrentEffect(), name);
470 setBuffer(binding, bufferHandle);
471 getEffects()->releaseBufferBinding(binding);
472 }
473
474 void ContextWebGPU::setBuffer(const BufferBindingHandle /*bufferBindingHandle*/, BufferHandle /*bufferHandle*/)
475 {
476 assert(false); // TODO
477 }
478
479 void ContextWebGPU::setBufferCounter(BufferHandle /*bufferHandle*/, uint32_t /*value*/)
480 {
481 assert(false); // TODO
482 }
483
484 void ContextWebGPU::setBufferCounter(BufferHandle /*bufferHandle*/, BufferHandle /*sourceBufferHandle*/)
485 {
486 assert(false); // TODO
487 }
488
489 void ContextWebGPU::getBufferCounter(BufferHandle /*bufferHandle*/, BufferHandle /*destinationBufferHandle*/)
490 {
491 assert(false); // TODO
492 }
493
494 void ContextWebGPU::draw(PrimitiveType::EPrimitiveType primitiveType, const size_t startVertex, const size_t numVertexes)
495 {
496 updateRenderPass();
497 if (updateRenderPipeline(primitiveType)) {
498 drawInstanced(primitiveType, startVertex, numVertexes, 0, 1);
499 }
500 }
501
502 void ContextWebGPU::drawIndexed(PrimitiveType::EPrimitiveType primitiveType, const size_t startIndex, const size_t numIndexes, const size_t startVertex)
503 {
504 updateRenderPass();
505 if (updateRenderPipeline(primitiveType)) {
506 wgpuRenderPassEncoderDrawIndexed(renderPassEncoder, (uint32_t)numIndexes, 1, (uint32_t)startIndex, (int32_t)startVertex, 0);
507 }
508 }
509
510 void ContextWebGPU::drawInstanced(PrimitiveType::EPrimitiveType primitiveType, const size_t startVertex, const size_t numVertexes, const size_t startInstance, const size_t numInstances)
511 {
512 updateRenderPass();
513 if (updateRenderPipeline(primitiveType)) {
514 wgpuRenderPassEncoderDraw(renderPassEncoder, (uint32_t)numVertexes, (uint32_t)numInstances, (uint32_t)startVertex, (uint32_t)startInstance);
515 }
516 }
517
518 void ContextWebGPU::drawInstancedIndexed(PrimitiveType::EPrimitiveType primitiveType, const size_t startInstance, const size_t numInstances, const size_t startIndex, const size_t numIndexes)
519 {
520 updateRenderPass();
521 if (updateRenderPipeline(primitiveType)) {
522 wgpuRenderPassEncoderDrawIndexed(renderPassEncoder, (uint32_t)numIndexes, (uint32_t)numInstances, (uint32_t)startIndex, 0, (uint32_t)startInstance);
523 }
524 }
525
526 void ContextWebGPU::beginRenderPassInt()
527 {
528 assert(renderPassEncoder == 0);
529 assert(computePassEncoder == 0);
530 WGPURenderPassColorAttachment color_attachment[8] = {};
531 WGPURenderPassDepthStencilAttachment ds_attachment = {};
532 uint32_t color_attachment_count = 0;
533 uint32_t ds_attachment_count = 0;
534
535 WGPULoadOp loadOp = do_clear_render_target ? WGPULoadOp_Clear : WGPULoadOp_Load;
536 do_clear_render_target = false;
537 WGPULoadOp depthLoadOp = do_clear_depth ? WGPULoadOp_Clear : WGPULoadOp_Load;
538 do_clear_depth = false;
539 const char *name = nullptr;
540 if (HandleIsValid(renderTargetHandle) || HandleIsValid(depthStencilHandle)) {
541 name = "Custom Render Pass";
542 if(HandleIsValid(renderTargetHandle)){
543 RenderTargetWebGPU &target = graphicsDevice->renderTargets.render_targets[renderTargetHandle];
544 for(size_t i=0; i<target.count; i++){
545 WGPURenderPassColorAttachment &att = color_attachment[i];
546 att.view = target.view[i];
547#ifndef EMSCRIPTEN
548 att.depthSlice = WGPU_DEPTH_SLICE_UNDEFINED;
549#endif
550 att.resolveTarget = nullptr;
551 att.loadOp = loadOp;
552 att.storeOp = WGPUStoreOp_Store;
553 att.clearValue = clearColor[i];
554 }
555 color_attachment_count = target.count;
556 }
557 if(HandleIsValid(depthStencilHandle)){
558 DepthStencilTargetWebGPU &target = graphicsDevice->renderTargets.depth_stencil_targets[depthStencilHandle];
559 WGPURenderPassDepthStencilAttachment &att = ds_attachment;
560 att.view = target.view;
561 att.depthLoadOp = depthLoadOp;
562 att.depthStoreOp = WGPUStoreOp_Store;
563 att.depthClearValue = clearDepthVal;
564 att.depthReadOnly = false;
565 att.stencilLoadOp = WGPULoadOp_Undefined;
566 att.stencilStoreOp = WGPUStoreOp_Undefined;
567 att.stencilClearValue = 0;
568 att.stencilReadOnly = false;
569 ds_attachment_count = 1;
570 }
571 }
572 else{
573 name = "Default Render Pass";
574 SwapChainWebGPU &defaultSwapChain = graphicsDevice->defaultSwapChain;
575 if(defaultSwapChain.samples > 1){
576 color_attachment[0].view = defaultSwapChain.colorBufferView;
577 color_attachment[0].resolveTarget = defaultSwapChain.resolveView;
578 }
579 else{
580 color_attachment[0].view = defaultSwapChain.resolveView;
581 }
582#ifndef EMSCRIPTEN
583 color_attachment[0].depthSlice = WGPU_DEPTH_SLICE_UNDEFINED;
584#endif
585 color_attachment[0].loadOp = loadOp;
586 color_attachment[0].storeOp = WGPUStoreOp_Store;
587 color_attachment[0].clearValue = clearColor[0];
588 color_attachment_count = 1;
589
590 ds_attachment.view = defaultSwapChain.depthBufferView;
591 ds_attachment.depthLoadOp = depthLoadOp;
592 ds_attachment.depthStoreOp = WGPUStoreOp_Store;
593 ds_attachment.depthClearValue = clearDepthVal;
594 ds_attachment.depthReadOnly = false;
595 ds_attachment.stencilLoadOp = WGPULoadOp_Undefined;
596 ds_attachment.stencilStoreOp = WGPUStoreOp_Undefined;
597 ds_attachment.stencilClearValue = 0;
598 ds_attachment.stencilReadOnly = false;
599 ds_attachment_count = 1;
600 }
601
602 WGPURenderPassDescriptor render_pass_desc = {};
603 render_pass_desc.label = name;
604 if(color_attachment_count){
605 render_pass_desc.colorAttachmentCount = color_attachment_count;
606 render_pass_desc.colorAttachments = color_attachment;
607 }
608 if(ds_attachment_count){
609 render_pass_desc.depthStencilAttachment = &ds_attachment;
610 }
611 render_pass_desc.occlusionQuerySet = nullptr;
612 // render_pass_desc.timestampWriteCount = 0;
613 render_pass_desc.timestampWrites = nullptr;
614 renderPassEncoder = wgpuCommandEncoderBeginRenderPass(graphicsDevice->commandEncoder, &render_pass_desc);
615 }
616
617 void ContextWebGPU::endRenderPassInt()
618 {
619 assert(!inRenderPass);
620 if(!renderPassEncoder) return;
621 wgpuRenderPassEncoderEnd(renderPassEncoder);
622 renderPassEncoder = 0;
623 update_render_target = true;
624 }
625
626 void ContextWebGPU::updateRenderPass()
627 {
628 if(update_render_target){
629 endComputePass();
630 endRenderPassInt();
631 beginRenderPassInt();
632 update_render_target = false;
633 }
634 }
635
636 bool ContextWebGPU::updateRenderPipeline(PrimitiveType::EPrimitiveType primitiveType)
637 {
638 assert(renderPassEncoder);
639 PipelineStatesWebGPU &pipeline_states = graphicsDevice->pipeline_states;
640 bool reload = false;
641 if(HandleIsValid(currentRenderPipeline)){
642 RenderPipelineWebGPU pipelineState = pipeline_states.renderPipeline[currentRenderPipeline];
643 if(pipelineState.effect != effect) reload = true;
644 if(pipelineState.inputLayoutHandle != inputLayoutHandle) reload = true;
645 if(pipelineState.primitiveType != primitiveType) reload = true;
646 if(pipelineState.rasterizeStateHandle != rasterizeStateHandle) reload = true;
647 if(pipelineState.depthStencilStateHandle != depthStencilStateHandle) reload = true;
648 if(pipelineState.blendStateHandle != blendStateHandle) reload = true;
649 if(pipelineState.renderTargetHandle != renderTargetHandle) reload = true;
650 if(pipelineState.depthStencilHandle != depthStencilHandle) reload = true;
651 }
652 else{
653 reload = true;
654 }
655 if(reload){
656 RenderPipelineHandle pipelineStateHandle = pipeline_states.loadRenderPipeline
657 (
658 effect,
659 inputLayoutHandle,
660 primitiveType,
661 rasterizeStateHandle,
662 depthStencilStateHandle,
663 blendStateHandle,
664 renderTargetHandle,
665 depthStencilHandle
666 );
667 RenderPipelineWebGPU pipelineState = pipeline_states.renderPipeline[pipelineStateHandle];
668 currentRenderPipeline = pipelineStateHandle;
669 }
670 if(HandleIsValid(currentRenderPipeline)){
671 RenderPipelineWebGPU &pipelineState = pipeline_states.renderPipeline[currentRenderPipeline];
672 wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelineState.pipeline);
673 }
674 if(update_descriptors){
675 RenderPipelineWebGPU &pipelineState = pipeline_states.renderPipeline[currentRenderPipeline];
676
677 std::vector<WGPUBindGroupEntry> entries;
678 entries.resize(descriptors.size());
679 uint32_t i=0;
680 for(auto &tmp : descriptors){
681 entries[i++] = tmp.second;
682 }
684 size_t num_bindings;
685 auto bindings = getEffects()->getConstantBufferBindings(effect, num_bindings);
686
687 for (size_t ii = 0; ii < num_bindings; ii++) {
688 bool found = false;
689 for (size_t j = 0; j < entries.size(); j++) {
690 if (bindings[ii].bg_ent.binding == entries[j].binding) {
691 found = true;
692 }
693 }
694 if (!found) {
695 LOG_ERROR_ONCE(logger, "binding %d in layout but not set", bindings[ii].bg_ent.binding);
696 return false;
697 }
698 }
700 WGPUBindGroupDescriptor bg_desc = {};
701 // char const * label;
702 bg_desc.layout = pipelineState.layout;
703 bg_desc.entryCount = (uint32_t)entries.size();
704 bg_desc.entries = entries.data();
705 current_bind_group = wgpuDeviceCreateBindGroup(graphicsDevice->device, &bg_desc);
706 }
707 if(current_bind_group){
708 uint32_t groupIndex = 0;
709 wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, groupIndex, current_bind_group, 0, nullptr);
710 }
711 return true;
712 }
713
714 void ContextWebGPU::dispatchCompute(const unsigned int threadGroupsX, const unsigned int threadGroupsY, const unsigned int threadGroupsZ)
715 {
716 updateComputePass();
717 updateComputePipeline();
718 wgpuComputePassEncoderDispatchWorkgroups(computePassEncoder, threadGroupsX, threadGroupsY, threadGroupsZ);
719 }
720
721 void ContextWebGPU::beginComputePass()
722 {
723 assert(renderPassEncoder == 0);
724 assert(computePassEncoder == 0);
725 WGPUComputePassDescriptor compute_pass_desc = {};
726 compute_pass_desc.label = "Compute Pass";
727 // compute_pass_desc.timestampWriteCount = 0;
728 compute_pass_desc.timestampWrites = nullptr;
729 computePassEncoder = wgpuCommandEncoderBeginComputePass(graphicsDevice->commandEncoder, &compute_pass_desc);
730 }
731
732 void ContextWebGPU::endComputePass()
733 {
734 if(!computePassEncoder) return;
735 wgpuComputePassEncoderEnd(computePassEncoder);
736 computePassEncoder = 0;
737 }
738
739 void ContextWebGPU::updateComputePass()
740 {
741 if(!computePassEncoder){
742 // endComputePass();
743 endRenderPassInt();
744 beginComputePass();
745 update_render_target = true;
746 }
747 }
748
749 void ContextWebGPU::updateComputePipeline()
750 {
751 assert(computePassEncoder);
752 PipelineStatesWebGPU &pipeline_states = graphicsDevice->pipeline_states;
753 bool reload = false;
754 if(HandleIsValid(currentComputePipeline)){
755 ComputePipelineWebGPU pipelineState = pipeline_states.computePipeline[currentComputePipeline];
756 if(pipelineState.effect != effect) reload = true;
757 }
758 else{
759 reload = true;
760 }
761 if(reload){
762 ComputePipelineHandle pipelineStateHandle = pipeline_states.loadComputePipeline(effect);
763 ComputePipelineWebGPU pipelineState = pipeline_states.computePipeline[pipelineStateHandle];
764 currentComputePipeline = pipelineStateHandle;
765 }
766 if(HandleIsValid(currentComputePipeline)){
767 ComputePipelineWebGPU &pipelineState = pipeline_states.computePipeline[currentComputePipeline];
768 wgpuComputePassEncoderSetPipeline(computePassEncoder, pipelineState.pipeline);
769 }
770 if(update_descriptors){
771 ComputePipelineWebGPU &pipelineState = pipeline_states.computePipeline[currentComputePipeline];
772
773 std::vector<WGPUBindGroupEntry> entries;
774 entries.resize(descriptors.size());
775 uint32_t i=0;
776 for(auto &tmp : descriptors){
777 entries[i++] = tmp.second;
778 }
779
780 WGPUBindGroupDescriptor bg_desc = {};
781 // char const * label;
782 bg_desc.layout = pipelineState.layout;
783 bg_desc.entryCount = (uint32_t)entries.size();
784 bg_desc.entries = entries.data();
785 current_bind_group = wgpuDeviceCreateBindGroup(graphicsDevice->device, &bg_desc);
786 }
787 if(current_bind_group){
788 uint32_t groupIndex = 0;
789 wgpuComputePassEncoderSetBindGroup(computePassEncoder, groupIndex, current_bind_group, 0, nullptr);
790 }
791 }
792
793 void ContextWebGPU::readDepthBuffer(BufferHandle bufferHandle, int x, int y, int width, int height, Framebuffer::EFrameBuffer)
794 {
795 const WGPUCommandEncoder &commandEncoder = graphicsDevice->commandEncoder;
796 TexturesWebGPU &textures = graphicsDevice->textures;
797 BufferWebGPU buffer = graphicsDevice->buffers.buffers[bufferHandle];
798
799 endRenderPassInt();
800
801 WGPUImageCopyTexture src = {};
802 if (HandleIsValid(renderTargetHandle) || HandleIsValid(depthStencilHandle)) {
803 if(!HandleIsValid(depthStencilHandle)) return;
804 DepthStencilTargetWebGPU &target = graphicsDevice->renderTargets.depth_stencil_targets[depthStencilHandle];
805 TextureWebGPU &src_tex = textures.textures[target.textureHandle];
806 src.texture = src_tex.texture;
807 }
808 else{
809 SwapChainWebGPU &defaultSwapChain = graphicsDevice->defaultSwapChain;
810 src.texture = defaultSwapChain.depthBufferTexture;
811 }
812 src.mipLevel = 0;
813 src.origin = {(uint32_t)x, (uint32_t)y, 0};
814 src.aspect = WGPUTextureAspect_DepthOnly;
815 WGPUImageCopyBuffer dst = {};
816 dst.layout.offset = 0;
817 dst.layout.bytesPerRow = (uint32_t)buffer.size;
818 dst.layout.rowsPerImage = 1;
819 dst.buffer = buffer.buffer;
820 WGPUExtent3D size = {};
821 size.width = width;
822 size.height = height;
823 size.depthOrArrayLayers = 1;
824 wgpuCommandEncoderCopyTextureToBuffer(commandEncoder, &src, &dst, &size);
825 }
826
827 void ContextWebGPU::readColorBuffer(BufferHandle bufferHandle, int x, int y, int width, int height, Framebuffer::EFrameBuffer)
828 {
829 const WGPUCommandEncoder &commandEncoder = graphicsDevice->commandEncoder;
830 TexturesWebGPU &textures = graphicsDevice->textures;
831 BufferWebGPU buffer = graphicsDevice->buffers.buffers[bufferHandle];
832
833 endRenderPassInt();
834
835 WGPUImageCopyTexture src = {};
836 if (HandleIsValid(renderTargetHandle) || HandleIsValid(depthStencilHandle)) {
837 if(!HandleIsValid(renderTargetHandle)) return;
838 RenderTargetWebGPU target = graphicsDevice->renderTargets.render_targets[renderTargetHandle];
839 TextureWebGPU &src_tex = textures.textures[target.textureHandle[0]];
840 src.texture = src_tex.texture;
841 }
842 else{
843 SwapChainWebGPU &defaultSwapChain = graphicsDevice->defaultSwapChain;
844#ifdef EMSCRIPTEN
845 // assert(false); // TODO ...
846 src.texture = defaultSwapChain.colorBufferTexture;
847#else
848 src.texture = defaultSwapChain.resolveTexture;
849#endif
850 }
851 src.mipLevel = 0;
852 src.origin = {(uint32_t)x, (uint32_t)y, 0};
853 src.aspect = WGPUTextureAspect_All;
854 WGPUImageCopyBuffer dst = {};
855 dst.layout.offset = 0;
856 dst.layout.bytesPerRow = (uint32_t)buffer.size;
857 dst.layout.rowsPerImage = 1;
858 dst.buffer = buffer.buffer;
859 WGPUExtent3D size = {};
860 size.width = width;
861 size.height = height;
862 size.depthOrArrayLayers = 1;
863 wgpuCommandEncoderCopyTextureToBuffer(commandEncoder, &src, &dst, &size);
864 }
865
866 void *ContextWebGPU::map(BufferHandle handle, MapMode::EMapMode mapMode, uint32_t* stride)
867 {
868 assert(stride == nullptr || stride[0] == 0);
869 BufferWebGPU &buffer = graphicsDevice->buffers.buffers[handle];
870 if(buffer.is_read_buffer){
871 assert(mapMode == MapMode::Read);
872 uint32_t offset = 0;
873 WGPUBufferMapCallback callback = nullptr;
874 void * userdata = nullptr;
875 wgpuBufferMapAsync(buffer.buffer, WGPUMapMode_Read, offset, buffer.size, callback, userdata);
876#ifndef EMSCRIPTEN
877 WGPUBufferMapState state = wgpuBufferGetMapState(buffer.buffer);
878 while(state != WGPUBufferMapState_Mapped){
879 // TODO this is bad... (Redesign for callback?)
880 assert(state == WGPUBufferMapState_Pending);
881 wgpuInstanceProcessEvents(graphicsDevice->instance);
882 wgpuDeviceTick(graphicsDevice->device);
883 state = wgpuBufferGetMapState(buffer.buffer);
884 }
885#else
886 assert(false);
887#endif
888 // return wgpuBufferGetMappedRange(buffer.buffer, 0, buffer.size);
889 return (void*)wgpuBufferGetConstMappedRange(buffer.buffer, 0, buffer.size);
890 }
891 else{
892 assert(mapMode == MapMode::WriteDiscard);
893 buffer.NextInstance(graphicsDevice);
894 buffer.map = new char[buffer.size];
895 return buffer.map;
896 }
897 }
898
899 void *ContextWebGPU::map(TextureHandle /*textureHandle*/, MapMode::EMapMode /*accessMode*/, uint32_t* /*rowPitch*/, uint32_t* /*depthPitch*/)
900 {
901 assert(false); // TODO
902 return nullptr;
903 }
904
905 void ContextWebGPU::unmap(BufferHandle handle)
906 {
907 BufferWebGPU &buffer = graphicsDevice->buffers.buffers[handle];
908 if(buffer.is_read_buffer){
909 // WGPUBufferMapState state = wgpuBufferGetMapState(buffer.buffer);
910 // if(state == WGPUBufferMapState_Mapped)
911 wgpuBufferUnmap(buffer.buffer);
912 }
913 else{
914 // const WGPUCommandEncoder &commandEncoder = graphicsDevice->commandEncoder;
915 // wgpuCommandEncoderWriteBuffer(commandEncoder, buffer.buffer, 0, (uint8_t*)buffer.map, buffer.size);
916 wgpuQueueWriteBuffer(graphicsDevice->queue, buffer.buffer, 0, buffer.map, buffer.size);
917 delete [] (char*)buffer.map;
918 buffer.map = nullptr;
919 }
920 }
921
922 void ContextWebGPU::unmap(TextureHandle /*textureHandle*/)
923 {
924 assert(false); // TODO
925 }
926
927 void ContextWebGPU::updateBuffer(BufferHandle handle, const void* data, const size_t size)
928 {
929 BufferWebGPU &buffer = graphicsDevice->buffers.buffers[handle];
930 buffer.NextInstance(graphicsDevice);
931 wgpuQueueWriteBuffer(graphicsDevice->queue, buffer.buffer, 0, data, size);
932 }
933
934 void ContextWebGPU::updateSubTexture(TextureHandle /*textureHandle*/, const size_t /*level*/, const void* /*data*/)
935 {
936 assert(false); // TODO
937 }
938
939 void ContextWebGPU::updateSubBuffer(BufferHandle handle, const size_t offset, const size_t size, const void* data)
940 {
941 BufferWebGPU &buffer = graphicsDevice->buffers.buffers[handle];
942 assert(buffer.alias_idx == 0); // TODO Copy over alias buffer data...
943 buffer.alias_idx++;
944 wgpuQueueWriteBuffer(graphicsDevice->queue, buffer.buffer, offset, data, size);
945 }
946
947 void ContextWebGPU::resolveResource(TextureHandle /*source*/, TextureHandle /*destination*/)
948 {
949 assert(false); // TODO
950 }
951
952 void ContextWebGPU::copyResource(BufferHandle /*destinationHandle*/, BufferHandle /*sourceHandle*/)
953 {
954 assert(false); // TODO
955 }
956
957 void ContextWebGPU::copyResource(TextureHandle /*destinationHandle*/, TextureHandle /*sourceHandle*/)
958 {
959 assert(false); // TODO
960 }
961
962 void ContextWebGPU::copyTexture(TextureHandle dstHandle, unsigned dstSub, unsigned dstX, unsigned dstY, unsigned dstZ, TextureHandle srcHandle, unsigned srcSub)
963 {
964 const WGPUCommandEncoder &commandEncoder = graphicsDevice->commandEncoder;
965 TexturesWebGPU &textures = graphicsDevice->textures;
966
967 TextureWebGPU &src = textures.textures[srcHandle];
968 TextureWebGPU &dst = textures.textures[dstHandle];
969
970 uint32_t srcLevel = 0; // TODO srcSub%LevelCount
971 uint32_t srcLayer = srcSub; // TODO srcSub/LevelCount
972
973 WGPUImageCopyTexture copy_src = {};
974 copy_src.texture = src.texture;
975 copy_src.mipLevel = srcLevel;
976 copy_src.origin = {0, 0, srcLayer};
977 copy_src.aspect = WGPUTextureAspect_All;
978
979 uint32_t dstLevel = 0; // TODO dstSub%LevelCount
980 uint32_t dstLayer = dstSub; // TODO dstSub/LevelCount
981
982 WGPUImageCopyTexture copy_dst = {};
983 copy_dst.texture = dst.texture;
984 copy_dst.mipLevel = dstLevel;
985 copy_dst.origin = {dstX, dstY, dstZ+dstLayer};
986 copy_dst.aspect = WGPUTextureAspect_All;
987
988 WGPUExtent3D size = {};
989 size.width = src.width;
990 size.height = src.height;
991 size.depthOrArrayLayers = 1;
992 wgpuCommandEncoderCopyTextureToTexture(commandEncoder, &copy_src, &copy_dst, &size);
993 }
994
995 void ContextWebGPU::clearResource(BufferHandle /*destinationHandle*/, uint32_t* /*values*/)
996 {
997 assert(false); // TODO
998 }
999
1000 void ContextWebGPU::clearResource(BufferHandle /*destinationHandle*/, float* /*values*/)
1001 {
1002 assert(false); // TODO
1003 }
1004
1005 EffectHandle ContextWebGPU::getCurrentEffect()
1006 {
1007 return effect;
1008 }
1009
1010 EffectsWebGPU *ContextWebGPU::getEffects()
1011 {
1012 return &graphicsDevice->effects;
1013 }
1014
1015}
virtual void setMatrixVariable(const StringView &, const float *) override
Sets the matrix variable with the given name in the current effect to value.
virtual void setSamplerState(const StringView &, unsigned int, SamplerStateHandle) override
Sets the sampler slot given by unit with the given name to contain the given sampler state.
virtual void getBufferCounter(BufferHandle, BufferHandle) override
Get the associated counter of a buffer.
virtual void setScalarVariable(const StringView &, const float) override
Sets the scalar floating point variable with the given name to the given value.
virtual void setVector2Variable(const StringView &, const float *) override
Sets the vector variable with the given name to the given two-component value.
virtual void setEffect(EffectHandle) override
Set the current effect.
virtual void setVector4Variable(const StringView &, const float *) override
Sets the vector variable with the given name to the given four-component value.
virtual void clearDepth(const float=1.0f) override
Clear the currently set depth/stencil target to the given depth.
virtual void setBlendState(const BlendStateHandle, const float *) override
Set the current blend state.
virtual void draw(PrimitiveType::EPrimitiveType, const size_t, const size_t) override
Draws non-indexed, non-instanced primitives.
virtual void setVertexBuffers(const VertexBufferHandle *, const size_t, const uint32_t *, const uint32_t *) override
Sets the current vertex buffers.
virtual void setBuffer(const StringView &, BufferHandle) override
Sets the given buffer to the buffer binding slot with the given name.
virtual void setVariable(const EffectVariableHandle, const uint8_t *, size_t) override
Sets the variable with the given name and size.
virtual void dispatchCompute(const unsigned int, const unsigned int, const unsigned int) override
Dispatch computing work on the graphics device using the desired thread group count.
virtual void drawIndexed(PrimitiveType::EPrimitiveType, const size_t, const size_t, const size_t=0) override
Draws indexed, non-instanced primitives.
virtual void setConstantBuffer(const StringView &, const BufferHandle, const uint32_t=0, const uint32_t=~0u) override
Sets a constant buffer to be bound to the given name and slot.
virtual void setBufferCounter(BufferHandle, uint32_t) override
Set the associated counter of a buffer.
virtual void setDepthStencilState(const DepthStencilStateHandle) override
Set the current depth stencil state.
virtual void setScissor(const int, const int, const int, const int) override
Sets the current scissor rectangle.
virtual void setRasterizerState(const RasterizerStateHandle) override
Set the current rasterizer state.
virtual void drawInstanced(PrimitiveType::EPrimitiveType, const size_t, const size_t, const size_t, const size_t) override
Draws non-indexed, instanced primitives.
virtual void endRenderPass() override
End a render pass.
virtual void beginRenderPass(const RenderPassInfo &info) override
Begin a render pass.
virtual void setVector3Variable(const StringView &, const float *) override
Sets the vector variable with the given name to the given three-component value.
virtual void setVertexArrayObject(VertexArrayObjectHandle) override
Sets vertexBuffers and index buffers using a prevalidated vertex array object.
virtual void signal(FenceHandle) override
Insert a fence in the command stream that will signal when all commands before the fence are complete...
virtual void setIndexBuffer(IndexBufferHandle, uint32_t=4, uint32_t=0) override
Sets the current index buffer.
virtual void clearRenderTarget(const float *) override
Clear the currently set render target to the given value (4 component floating point RGBA).
virtual void setTexture(const StringView &, unsigned int, TextureHandle) override
Sets the texture slot given by unit with the given name to contain the given texture.
virtual void setInputLayout(const InputLayoutHandle) override
Sets the current input layout.
virtual void setRenderTarget(const RenderTargetHandle handle, const DepthStencilHandle depthStencilHandle) override
Sets the current render target and an associated depth stencil target.
virtual void setViewport(const float, const float, const float, const float) override
Sets the current viewport to the given location and dimensions.
virtual void drawInstancedIndexed(PrimitiveType::EPrimitiveType, const size_t, const size_t, const size_t, const size_t) override
Draws indexed, instanced primitives.
virtual void readDepthBuffer(BufferHandle, int, int, int, int, Framebuffer::EFrameBuffer) override
Reads data from the current depth target into the given bufferHandle.
void releaseBufferBinding(BufferBindingHandle) override
Release a handle to a buffer binding.
Definition: EffectsWebGPU.h:84
BufferBindingHandle getBufferBinding(EffectHandle effectHandle, const StringView &name) override
Get a handle to a buffer binding.
virtual bool getSize(int &w, int &h) const override
Retrieve the size previously set by setSize.
Log implementation class.
Definition: LogManager.h:139
Provides a weakly referenced view over the contents of a string.
Definition: StringView.h:24
bool HandleIsValid(const ResourceHandle_t< T > &handle)
Check if the given resource is valid, that is not equal to NoHandle or InvalidHandle.
constexpr Log getLogger(const char(&name)[LEN]) noexcept
Definition: LogManager.h:180
Contains all Cogs related functionality.
Definition: FieldSetter.h:23
Handle template class used to provide opaque, non-converting handles.
Definition: Common.h:22
static const Handle_t NoHandle
Represents a handle to nothing.
Definition: Common.h:77
handle_type handle
Internal resource handle.
Definition: Common.h:74
EMapMode
Mapping mode enumeration.
Definition: Flags.h:93
EPrimitiveType
Primitive type enumeration.
Definition: Common.h:114