1#include "ContextWebGPU.h"
3#include "GraphicsDeviceWebGPU.h"
4#include "PipelineStatesWebGPU.h"
5#include "Foundation/Logging/Logger.h"
10 WGPULoadOp ConvWebGPULoadOp(Cogs::LoadOp 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;
17 return WGPULoadOp_Undefined;
19 WGPUStoreOp ConvWebGPUStoreOp(Cogs::StoreOp 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;
26 return WGPUStoreOp_Undefined;
29 void decodeConstantBufferBindingHandle(int64_t handle,
size_t &group, uint32_t &binding) {
32 binding = (i & 0xFFFF) - 1;
39 void ContextWebGPU::initialize(GraphicsDeviceWebGPU *graphicsDeviceIn)
41 graphicsDevice = graphicsDeviceIn;
44 void ContextWebGPU::frameStatisticsConfigure(
bool )
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];
63 do_clear_render_target =
true;
64 update_render_target =
true;
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];
76 for(
size_t i=numvalues; i<
sizeof(clearColor)/
sizeof(clearColor[0]); i++){
79 do_clear_render_target =
true;
80 update_render_target =
true;
85 assert(!inRenderPass);
86 clearDepthVal = depth;
87 do_clear_depth =
true;
88 update_render_target =
true;
93 assert(renderPassEncoder == 0);
94 assert(computePassEncoder == 0);
95 assert(!inRenderPass);
97 update_render_target =
false;
99 renderTargetHandle = info.renderTargetHandle;
100 depthStencilHandle = info.depthStencilHandle;
102 WGPURenderPassColorAttachment color_attachment[8] = {};
103 WGPURenderPassDepthStencilAttachment ds_attachment = {};
104 uint32_t color_attachment_count = 0;
105 uint32_t ds_attachment_count = 0;
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;
120 att.resolveTarget =
nullptr;
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];
129 color_attachment_count = target.count;
131 if(HandleIsValid(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;
147 name =
"Default Render Pass";
149 if(defaultSwapChain.samples > 1){
150 color_attachment[0].view = defaultSwapChain.colorBufferView;
151 color_attachment[0].resolveTarget = defaultSwapChain.resolveView;
154 color_attachment[0].view = defaultSwapChain.resolveView;
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;
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;
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;
183 if(ds_attachment_count){
184 render_pass_desc.depthStencilAttachment = &ds_attachment;
186 render_pass_desc.occlusionQuerySet =
nullptr;
188 render_pass_desc.timestampWrites =
nullptr;
189 renderPassEncoder = wgpuCommandEncoderBeginRenderPass(graphicsDevice->commandEncoder, &render_pass_desc);
193 assert(renderPassEncoder);
194 assert(inRenderPass);
195 inRenderPass =
false;
196 wgpuRenderPassEncoderEnd(renderPassEncoder);
197 wgpuRenderPassEncoderRelease(renderPassEncoder);
198 renderPassEncoder = 0;
199 update_render_target =
true;
204 if(HandleIsValid(rt_handle))
205 renderTargetHandle = rt_handle;
207 renderTargetHandle = {};
208 if(HandleIsValid(ds_handle))
209 depthStencilHandle = ds_handle;
211 depthStencilHandle = {};
212 rasterizeStateHandle = {};
213 blendStateHandle = {};
214 assert(do_clear_render_target ==
false);
215 assert(do_clear_depth ==
false);
216 do_clear_render_target =
false;
217 do_clear_depth =
false;
218 update_render_target =
true;
224 float minDepth = 0.0f;
225 float maxDepth = 1.0f;
226 wgpuRenderPassEncoderSetViewport(renderPassEncoder, x, y, width, height, minDepth, maxDepth);
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);
243 if(HandleIsValid(handle))
244 depthStencilStateHandle = handle;
246 depthStencilStateHandle = {};
252 if(HandleIsValid(handle))
253 blendStateHandle = handle;
255 blendStateHandle = {};
258 color.r = constants[0];
259 color.g = constants[1];
260 color.b = constants[2];
261 color.a = constants[3];
269 wgpuRenderPassEncoderSetBlendConstant(renderPassEncoder, &color);
274 if(HandleIsValid(handle))
275 rasterizeStateHandle = handle;
277 rasterizeStateHandle = {};
280 void ContextWebGPU::setDefaults() {
281 rasterizeStateHandle = {};
282 depthStencilStateHandle = {};
283 blendStateHandle = {};
288 if(HandleIsValid(handle))
292 inputLayoutHandle = {};
294 update_descriptors =
true;
299 setTexture(getEffects()->getTextureBinding(getCurrentEffect(), name, unit), textureHandle);
306 if (!HandleIsValid(handle)) {
307 descriptors.erase((uint32_t)binding.
handle);
310 if (!HandleIsValid(binding)) {
313 TextureWebGPU texture = graphicsDevice->textures.textures[handle];
314 WGPUBindGroupEntry bg_ent = {};
316 decodeConstantBufferBindingHandle(binding.
handle, group, bg_ent.binding);
318 bg_ent.buffer =
nullptr;
321 bg_ent.sampler =
nullptr;
322 bg_ent.textureView = texture.texture_view;
323 descriptors[bg_ent.binding] = bg_ent;
324 update_descriptors =
true;
329 setTexture(getEffects()->getTextureBinding(getCurrentEffect(), name, 1), textureViewHandle);
336 if (!HandleIsValid(handle)) {
337 descriptors.erase((uint32_t)binding.handle);
340 TextureViewWebGPU texture_view = graphicsDevice->textures.textureViews[handle];
341 WGPUBindGroupEntry bg_ent = {};
343 decodeConstantBufferBindingHandle(binding.handle, group, bg_ent.binding);
345 bg_ent.buffer =
nullptr;
348 bg_ent.sampler =
nullptr;
349 bg_ent.textureView = texture_view.texture_view;
350 descriptors[bg_ent.binding] = bg_ent;
351 update_descriptors =
true;
356 setSamplerState(getEffects()->getSamplerStateBinding(getCurrentEffect(), name, unit), handle);
363 if (!HandleIsValid(handle)) {
364 descriptors.erase((uint32_t)binding.
handle);
367 if (!HandleIsValid(binding)) {
371 WGPUBindGroupEntry bg_ent = {};
373 decodeConstantBufferBindingHandle(binding.
handle, group, bg_ent.binding);
375 bg_ent.buffer =
nullptr;
378 bg_ent.sampler = sampler.sampler;
379 bg_ent.textureView =
nullptr;
380 descriptors[bg_ent.binding] = bg_ent;
387 update_descriptors =
true;
392 if(HandleIsValid(handle))
393 inputLayoutHandle = handle;
395 inputLayoutHandle = {};
401 for(
size_t i=0; i<count; i++){
403 uint32_t slot = (uint32_t)i;
405 uint32_t offset = offsets ? offsets[i] : 0;
406 wgpuRenderPassEncoderSetVertexBuffer(renderPassEncoder, slot, buffer.buffer, offset, buffer.size-offset);
421 WGPUIndexFormat format = (stride == 2) ? WGPUIndexFormat_Uint16 : WGPUIndexFormat_Uint32;
422 uint64_t offset = offset_in;
424 wgpuRenderPassEncoderSetIndexBuffer(renderPassEncoder, buffer.buffer, format, offset, buffer.size);
434 setConstantBuffer(getEffects()->getConstantBufferBinding(getCurrentEffect(), name), bufferHandle, offset, size);
441 if (!HandleIsValid(handle)) {
442 descriptors.erase((uint32_t)binding.
handle);
445 if (!HandleIsValid(binding)) {
449 BufferWebGPU &buffer = graphicsDevice->buffers.buffers[handle];
450 WGPUBindGroupEntry bg_ent = {};
452 decodeConstantBufferBindingHandle(binding.
handle, group, bg_ent.binding);
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;
493 if (updateRenderPipeline(primitiveType)) {
494 drawInstanced(primitiveType, startVertex, numVertexes, 0, 1);
501 if (updateRenderPipeline(primitiveType)) {
502 wgpuRenderPassEncoderDrawIndexed(renderPassEncoder, (uint32_t)numIndexes, 1, (uint32_t)startIndex, (int32_t)startVertex, 0);
509 if (updateRenderPipeline(primitiveType)) {
510 wgpuRenderPassEncoderDraw(renderPassEncoder, (uint32_t)numVertexes, (uint32_t)numInstances, (uint32_t)startVertex, (uint32_t)startInstance);
517 if (updateRenderPipeline(primitiveType)) {
518 wgpuRenderPassEncoderDrawIndexed(renderPassEncoder, (uint32_t)numIndexes, (uint32_t)numInstances, (uint32_t)startIndex, 0, (uint32_t)startInstance);
522 void ContextWebGPU::beginRenderPassInt()
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;
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;
537 name =
"Custom Render Pass";
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;
546 att.storeOp = WGPUStoreOp_Store;
547 att.clearValue = clearColor[i];
549 color_attachment_count = target.count;
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;
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;
574 color_attachment[0].view = defaultSwapChain.resolveView;
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;
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;
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;
600 if(ds_attachment_count){
601 render_pass_desc.depthStencilAttachment = &ds_attachment;
603 render_pass_desc.occlusionQuerySet =
nullptr;
605 render_pass_desc.timestampWrites =
nullptr;
606 renderPassEncoder = wgpuCommandEncoderBeginRenderPass(graphicsDevice->commandEncoder, &render_pass_desc);
609 void ContextWebGPU::endRenderPassInt()
611 assert(!inRenderPass);
612 if(!renderPassEncoder)
return;
613 wgpuRenderPassEncoderEnd(renderPassEncoder);
614 wgpuRenderPassEncoderRelease(renderPassEncoder);
615 renderPassEncoder = 0;
616 update_render_target =
true;
619 void ContextWebGPU::updateRenderPass()
621 if(update_render_target){
624 beginRenderPassInt();
625 update_render_target =
false;
629 bool ContextWebGPU::updateRenderPipeline(
PrimitiveType primitiveType)
631 assert(renderPassEncoder);
632 PipelineStatesWebGPU &pipeline_states = graphicsDevice->pipeline_states;
635 RenderPipelineWebGPU pipelineState = pipeline_states.renderPipeline[currentRenderPipeline];
636 size_t hash = pipeline_states.renderPipelineHash(effect,
639 rasterizeStateHandle,
640 depthStencilStateHandle,
644 if(
hash != pipelineState.hash) reload =
true;
650 RenderPipelineHandle pipelineStateHandle = pipeline_states.loadRenderPipeline
655 rasterizeStateHandle,
656 depthStencilStateHandle,
661 RenderPipelineWebGPU pipelineState = pipeline_states.renderPipeline[pipelineStateHandle];
662 currentRenderPipeline = pipelineStateHandle;
665 RenderPipelineWebGPU &pipelineState = pipeline_states.renderPipeline[currentRenderPipeline];
666 wgpuRenderPassEncoderSetPipeline(renderPassEncoder, pipelineState.pipeline);
668 if(update_descriptors){
669 RenderPipelineWebGPU &pipelineState = pipeline_states.renderPipeline[currentRenderPipeline];
671 std::vector<WGPUBindGroupEntry> entries;
672 entries.resize(descriptors.size());
674 for(
auto &tmp : descriptors){
675 entries[i++] = tmp.second;
680 auto bindings = getEffects()->getConstantBufferBindings(effect, num_bindings);
682 for (
size_t ii = 0; ii < num_bindings; ii++) {
684 for (
size_t j = 0; j < entries.size(); j++) {
685 if (bindings[ii].bg_ent.binding == entries[j].binding) {
690 LOG_ERROR_ONCE(logger,
"binding %d in layout but not set", bindings[ii].bg_ent.binding);
694 for (
size_t j = 0; j < entries.size(); j++) {
696 for (
size_t ii = 0; ii < num_bindings; ii++) {
697 if (bindings[ii].bg_ent.binding == entries[j].binding) {
702 LOG_ERROR_ONCE(logger,
"binding %d is set but not in layout", entries[j].binding);
707 WGPUBindGroupDescriptor bg_desc = {};
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);
714 if(current_bind_group){
715 uint32_t groupIndex = 0;
716 wgpuRenderPassEncoderSetBindGroup(renderPassEncoder, groupIndex, current_bind_group, 0,
nullptr);
724 updateComputePipeline();
725 wgpuComputePassEncoderDispatchWorkgroups(computePassEncoder, threadGroupsX, threadGroupsY, threadGroupsZ);
728 void ContextWebGPU::beginComputePass()
730 assert(renderPassEncoder == 0);
731 assert(computePassEncoder == 0);
732 WGPUComputePassDescriptor compute_pass_desc = {};
733 compute_pass_desc.label = {
"Compute Pass", WGPU_STRLEN};
735 compute_pass_desc.timestampWrites =
nullptr;
736 computePassEncoder = wgpuCommandEncoderBeginComputePass(graphicsDevice->commandEncoder, &compute_pass_desc);
739 void ContextWebGPU::endComputePass()
741 if(!computePassEncoder)
return;
742 wgpuComputePassEncoderEnd(computePassEncoder);
743 computePassEncoder = 0;
746 void ContextWebGPU::updateComputePass()
748 if(!computePassEncoder){
752 update_render_target =
true;
756 void ContextWebGPU::updateComputePipeline()
758 assert(computePassEncoder);
759 PipelineStatesWebGPU &pipeline_states = graphicsDevice->pipeline_states;
762 ComputePipelineWebGPU pipelineState = pipeline_states.computePipeline[currentComputePipeline];
763 if(pipelineState.effect != effect) reload =
true;
769 ComputePipelineHandle pipelineStateHandle = pipeline_states.loadComputePipeline(effect);
770 ComputePipelineWebGPU pipelineState = pipeline_states.computePipeline[pipelineStateHandle];
771 currentComputePipeline = pipelineStateHandle;
774 ComputePipelineWebGPU &pipelineState = pipeline_states.computePipeline[currentComputePipeline];
775 wgpuComputePassEncoderSetPipeline(computePassEncoder, pipelineState.pipeline);
777 if(update_descriptors){
778 ComputePipelineWebGPU &pipelineState = pipeline_states.computePipeline[currentComputePipeline];
780 std::vector<WGPUBindGroupEntry> entries;
781 entries.resize(descriptors.size());
783 for(
auto &tmp : descriptors){
784 entries[i++] = tmp.second;
787 WGPUBindGroupDescriptor bg_desc = {};
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);
794 if(current_bind_group){
795 uint32_t groupIndex = 0;
796 wgpuComputePassEncoderSetBindGroup(computePassEncoder, groupIndex, current_bind_group, 0,
nullptr);
802 const WGPUCommandEncoder &commandEncoder = graphicsDevice->commandEncoder;
804 BufferWebGPU buffer = graphicsDevice->buffers.buffers[bufferHandle];
808 WGPUTexelCopyTextureInfo src = {};
809 if (HandleIsValid(renderTargetHandle) || HandleIsValid(depthStencilHandle)) {
810 if(!HandleIsValid(depthStencilHandle))
return;
812 TextureWebGPU &src_tex = textures.textures[target.textureHandle];
813 src.texture = src_tex.texture;
817 src.texture = defaultSwapChain.depthBufferTexture;
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 = {};
829 size.height = height;
830 size.depthOrArrayLayers = 1;
831 wgpuCommandEncoderCopyTextureToBuffer(commandEncoder, &src, &dst, &size);
836 const WGPUCommandEncoder &commandEncoder = graphicsDevice->commandEncoder;
838 BufferWebGPU buffer = graphicsDevice->buffers.buffers[bufferHandle];
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;
853 src.texture = defaultSwapChain.colorBufferTexture;
855 src.texture = defaultSwapChain.resolveTexture;
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 = {};
868 size.height = height;
869 size.depthOrArrayLayers = 1;
870 wgpuCommandEncoderCopyTextureToBuffer(commandEncoder, &src, &dst, &size);
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);
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);
889 WGPUBufferMapState state = wgpuBufferGetMapState(buffer.buffer);
890 while(state != WGPUBufferMapState_Mapped){
892 assert(state == WGPUBufferMapState_Pending);
893 wgpuInstanceProcessEvents(graphicsDevice->instance);
894 wgpuDeviceTick(graphicsDevice->device);
895 state = wgpuBufferGetMapState(buffer.buffer);
901 return (
void*)wgpuBufferGetConstMappedRange(buffer.buffer, 0, buffer.size);
904 assert(mapMode == MapMode::WriteDiscard);
905 buffer.NextInstance(graphicsDevice);
906 buffer.map =
new char[buffer.size];
919 BufferWebGPU &buffer = graphicsDevice->buffers.buffers[handle];
920 if(buffer.is_read_buffer){
923 wgpuBufferUnmap(buffer.buffer);
928 wgpuQueueWriteBuffer(graphicsDevice->queue, buffer.buffer, 0, buffer.map, buffer.size);
929 delete [] (
char*)buffer.map;
930 buffer.map =
nullptr;
939 void ContextWebGPU::updateBuffer(
BufferHandle handle,
const void* data,
const size_t size)
941 BufferWebGPU &buffer = graphicsDevice->buffers.buffers[handle];
942 buffer.NextInstance(graphicsDevice);
943 wgpuQueueWriteBuffer(graphicsDevice->queue, buffer.buffer, 0, data, size);
946 void ContextWebGPU::updateSubTexture(
TextureHandle textureHandle,
const size_t level,
const void* data)
948 assert(HandleIsValid(textureHandle) &&
"Texture handle is invalid.");
950 TextureWebGPU & texture = graphicsDevice->textures.textures[textureHandle];
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));
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 };
961 const Cogs::FormatInfo *textureFormat = Cogs::getFormatInfo(texture.format);
963 WGPUTexelCopyBufferLayout sourceLayout;
964 sourceLayout.offset = 0;
966 sourceLayout.rowsPerImage = (height + textureFormat->
blockExtent.height - 1) / textureFormat->
blockExtent.height;
968 size_t size = sourceLayout.bytesPerRow * sourceLayout.rowsPerImage;
971 extent.width = width;
972 extent.height = height;
973 extent.depthOrArrayLayers = 1;
975 wgpuQueueWriteTexture(graphicsDevice->queue, &destinationTexture, data,
static_cast<size_t>(size), &sourceLayout, &extent);
978 void ContextWebGPU::updateSubBuffer(
BufferHandle handle,
const size_t offset,
const size_t size,
const void* data)
980 BufferWebGPU &buffer = graphicsDevice->buffers.buffers[handle];
981 assert(buffer.alias_idx == 0);
983 wgpuQueueWriteBuffer(graphicsDevice->queue, buffer.buffer, offset, data, size);
996 void ContextWebGPU::copyResource(TextureHandle , TextureHandle )
1001 void ContextWebGPU::copyTexture(TextureHandle dstHandle,
unsigned dstSub,
unsigned dstX,
unsigned dstY,
unsigned dstZ, TextureHandle srcHandle,
unsigned srcSub)
1003 graphicsDevice->maybeCreateUploadCommandEncoder();
1004 const WGPUCommandEncoder &commandEncoder = graphicsDevice->commandEncoder;
1005 TexturesWebGPU &textures = graphicsDevice->textures;
1007 TextureWebGPU &src = textures.textures[srcHandle];
1008 TextureWebGPU &dst = textures.textures[dstHandle];
1010 uint32_t srcLevel = 0;
1011 uint32_t srcLayer = srcSub;
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;
1019 uint32_t dstLevel = 0;
1020 uint32_t dstLayer = dstSub;
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;
1028 WGPUExtent3D size = {};
1029 size.width = src.width;
1030 size.height = src.height;
1031 size.depthOrArrayLayers = 1;
1032 wgpuCommandEncoderCopyTextureToTexture(commandEncoder, ©_src, ©_dst, &size);
1035 void ContextWebGPU::clearResource(BufferHandle , uint32_t* )
1040 void ContextWebGPU::clearResource(BufferHandle ,
float* )
1045 EffectHandle ContextWebGPU::getCurrentEffect()
1050 EffectsWebGPU *ContextWebGPU::getEffects()
1052 return &graphicsDevice->effects;
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.
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.
Provides a weakly referenced view over the contents of a string.
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
Contains all Cogs related functionality.
constexpr size_t hash() noexcept
Simple getter function that returns the initial value for fnv1a hashing.
Framebuffer
Framebuffers to select from when doing framebuffer operations.
PrimitiveType
Primitive types for interpreting vertex data sent to the graphics pipeline.
Handle template class used to provide opaque, non-converting handles.
static const Handle_t NoHandle
Represents a handle to nothing.
handle_type handle
Internal resource handle.
EMapMode
Mapping mode enumeration.