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