Cogs.Core
GenerateListTask.cpp
1#include "GenerateListTask.h"
2
3#include "Context.h"
4#include "EntityStore.h"
5
6#include "Components/Core/RenderComponent.h"
7
8#include "Foundation/ComponentModel/Entity.h"
9#include "Foundation/Logging/Logger.h"
10
11#include "Rendering/ICapabilities.h"
12#include "Rendering/IBuffers.h"
13
14#include "Renderer/Renderer.h"
15#include "Renderer/RenderResources.h"
16#include "Renderer/RenderStateUpdater.h"
17#include "Renderer/CustomRenderer/DebugGeometryRenderers.h"
18
19#include "Resources/MaterialManager.h"
20#include "Resources/Mesh.h"
21
22#include "Services/Services.h"
23#include "Services/Variables.h"
24#include "Services/PipelineService.h"
25
26#include "Systems/Core/MeshSystem.h"
27#include "Systems/Core/RenderSystem.h"
28#include "Systems/Core/SubMeshRenderSystem.h"
29#include "Systems/Core/InstancedMeshRenderSystem.h"
30#include "Systems/Core/SpriteRenderSystem.h"
31#include "Systems/Core/AnimationSystem.h"
32#include "Systems/Core/StaticModelSystem.h"
33#include "Systems/Core/LightSystem.h"
34#include "Systems/Core/CameraSystem.h"
35#include "Systems/Core/ClipShapeSystem.h"
36
37#ifdef _WIN32
38// TODO: Remove when we update past GLM 0.9.9.7
39#pragma warning(push)
40#pragma warning(disable: 4127) // conditional expression is constant
41#include <glm/ext/matrix_clip_space.hpp>
42#pragma warning(pop)
43#endif
44
45#include <glm/gtx/transform.hpp>
46
47namespace {
48
49 Cogs::Logging::Log logger = Cogs::Logging::getLogger("GenerateListTask");
50
51 constexpr uint32_t minObjectBufferCapacity = 1024;
52
53}
54
55namespace Cogs::Core
56{
57 const MaterialInstance * getControllingInstance(const MaterialInstance * instance, MaterialFlags::EMaterialFlags overrideFlag)
58 {
59 if (instance->masterInstance && ((instance->masterInstance->getMaterialFlags() & overrideFlag) == overrideFlag)) {
60 return instance->masterInstance.resolve();
61 }
62
63 return instance;
64 }
65
66 void getTransparencyState(RenderStates & /*renderStates*/, const MaterialInstance * materialInstance, RenderItem & renderItem)
67 {
68 const auto instance = getControllingInstance(materialInstance, MaterialFlags::OverrideAlpha);
69 const auto hasTransparency = instance->hasTransparency();
70 auto blendMode = instance->options.blendMode;
71
72 if (blendMode == BlendMode::None && hasTransparency) blendMode = BlendMode::Blend;
73
74 renderItem.blendState = (uint16_t)blendMode;
75 }
76
77 RenderItemFlags getMaterialFlags(const MaterialInstance * materialInstance)
78 {
79 RenderItemFlags flags = RenderItemFlags::None;
80 flags |= (materialInstance->instanceFlags & MaterialFlags::CustomBucket) != 0 ? RenderItemFlags::CustomBucket : RenderItemFlags::None;
81 flags |= materialInstance->hasTransparency() ? RenderItemFlags::Transparent : RenderItemFlags::None;
82 flags |= materialInstance->isBackdrop() ? RenderItemFlags::Backdrop : RenderItemFlags::None;
83 return flags;
84 }
85}
86
87uint8_t Cogs::Core::ClipShapeCache::getIndex(Context* context, ComponentModel::ComponentHandle clipShapeHandle)
88{
90
91 // See if we have already seen this
92 for (size_t i = 1; i < count; i++) {
93 if (handles[i] == clipShapeHandle) {
94 return static_cast<uint8_t>(i);
95 }
96 }
97
98 // Not found, create a new one unless we have created more than 16
99 if (ClipShapeComponent* clipComp = clipShapeHandle.resolveComponent<ClipShapeComponent>(); clipComp) {
100 const ClipShapeData& clipData = context->clipShapeSystem->getData(clipComp);
101
102 switch (clipData.shape) {
104 return 0;
107 if (count < ClipShapeCache::maxClipShapes) {
108 handles[count] = clipShapeHandle;
109 data[count] = {
110 .clipEquations = {
111 clipData.planes[0],
112 clipData.planes[1],
113 clipData.planes[2],
114 clipData.planes[3],
115 clipData.planes[4],
116 clipData.planes[5]
117 },
118 .clipShape = clipData.shape
119 };
120 return static_cast<uint8_t>(count++);
121 }
122 break;
123 default:
124 assert(false && "Invalid enum");
125 }
126 LOG_ERROR_ONCE(logger, "Exceeding max number of clip shapes");
127 }
128 return 0;
129}
130
131
132Cogs::Core::RenderItem& Cogs::Core::GenerateListTask::createRenderItem(Context* context, RenderBatch& batch, const glm::mat4* localToWorld, const RenderComponent* renderComponent)
133{
134 if (renderComponent && (renderComponent->layer&RenderLayers::AllReserved)!=0) {
135 LOG_WARNING_ONCE(logger, "Using a reserved RenderLayer (Consider switching to RenderLayer::Custom).");
136 }
137
138 RenderItem& item = batch.alloc();
139 item = {};
140 item.cullingIndex = (uint32_t)-1;
141 if (localToWorld) {
142 item.worldMatrix = localToWorld;
143 }
144 item.flags = RenderItemFlags::None;
145
146 const uint32_t objectId = renderComponent ? renderComponent->objectId : NoObjectId;
147 if (listObjectBuffer.isInUse()) {
148
149 if (listObjectBuffer.cpuCapacity == listObjectBuffer.fill) {
150 listObjectBuffer.cpuCapacity = std::max(minObjectBufferCapacity,
151 listObjectBuffer.cpuCapacity + std::min(1024u * 16u, listObjectBuffer.cpuCapacity / 2));
152 listObjectBuffer.cpu.resize(size_t(listObjectBuffer.stride) * listObjectBuffer.cpuCapacity);
153 }
154
155 item.flags |= RenderItemFlags::ObjectBufferSlot;
156 item.objectBufferSlot = listObjectBuffer.fill++;
157
158 ObjectBuffer* objectBuffer = reinterpret_cast<ObjectBuffer*>((uint8_t*)(listObjectBuffer.cpu.data()) + size_t(listObjectBuffer.stride) * item.objectBufferSlot);
159 if (localToWorld) {
160 objectBuffer->worldMatrix = *localToWorld;
161 }
162 objectBuffer->objectId = objectId;
163 }
164 else {
165 item.objectId = objectId;
166 }
167
168 if (renderComponent) {
169 ComponentModel::ComponentHandle clipShapeHandle = renderComponent->clipShapeComponent;
170 if (clipShapeHandle != ComponentModel::ComponentHandle::Empty()) {
171 item.clipShapeIx = clipShapeCache.getIndex(context, clipShapeHandle);
172 }
173 }
174 return item;
175}
176
177size_t Cogs::Core::GenerateListTask::generateItems(Context* context, RenderBatch& batch, Renderer* renderer, RenderSystem* renderSystem, MeshSystem* /*meshSystem*/)
178{
179 size_t missing = 0;
180 for (const auto& renderComponent : renderSystem->pool) {
181 if (!renderComponent.isVisible()) continue;
182
183 auto& renderData = renderSystem->getData<MeshRenderData>(&renderComponent);
184
185 const MeshComponent* meshComponent = renderData.meshComponent.resolveComponent<MeshComponent>();
186 if (meshComponent == nullptr) {
187 LOG_ERROR_ONCE(logger, "No mesh component defined");
188 continue;
189 }
190
191 RenderMesh * renderMesh = renderer->getRenderResources().getRenderMesh(meshComponent->meshHandle);
192
193 if (!renderMesh) {
194 ++missing;
195 continue;
196 }
197
198 Mesh * mesh = meshComponent->meshHandle.resolve();
199
200 MaterialInstance * materialInstance = renderComponent.material.resolve();
201
202 if (!materialInstance) {
203 ++missing;
204 continue;
205 }
206
207 RenderItem& renderBlock = createRenderItem(context, batch, &renderData.localToWorld, &renderComponent);
208 renderBlock.lod = renderComponent.lod;
209 renderBlock.layer = renderComponent.layer;
210 renderBlock.flags |= renderComponent.castShadows() ? RenderItemFlags::CastShadows : RenderItemFlags::None;
211
212 if (renderComponent.disableCulling()) {
213 renderBlock.flags |= RenderItemFlags::DisableCulling;
214 }
215
216 renderBlock.cullingIndex = renderData.cullingIndex;
217
218
219 renderBlock.meshData = renderMesh;
220
221 const uint32_t meshCount = mesh->getCount();
222
223 if (renderComponent.vertexCount == uint32_t(-1)) {
224 renderBlock.startIndex = 0;
225 renderBlock.numIndexes = meshCount;
226 }
227 else {
228 renderBlock.startIndex = renderComponent.startIndex;
229 renderBlock.numIndexes = renderComponent.vertexCount;
230 if (meshCount <= renderBlock.startIndex || meshCount < renderBlock.startIndex + renderBlock.numIndexes) {
231 LOG_ERROR_ONCE(logger, "RenderComponent draw range is out of bounds");
232 continue;
233 }
234 }
235 renderBlock.primitiveType = renderComponent.primitiveType != (PrimitiveType::EPrimitiveType)-1 ? renderComponent.primitiveType : mesh->primitiveType;
236
237 if (mesh->isMeshFlagSet(MeshFlags::Instanced)) {
238 renderBlock.flags |= RenderItemFlags::Instanced;
239 renderBlock.numIndexes = mesh->getCount();
240 renderBlock.numInstances = mesh->getInstanceCount();
241 }
242
243 if (mesh->isMeshFlagSet(MeshFlags::Skinned)) {
244 const AnimationComponent* animationComponent = renderComponent.getComponent<AnimationComponent>();
245 if (animationComponent == nullptr) {
246 LOG_ERROR_ONCE(logger, "No animation component defined");
247 continue;
248 }
249 const AnimationData& animationData = context->animationSystem->getData(animationComponent);
250 renderBlock.poseData = animationData.pose.get();
251 }
252
253 renderBlock.flags |= !mesh->isCCW() ? RenderItemFlags::Clockwise : RenderItemFlags::None;
254 renderBlock.flags |= getMaterialFlags(materialInstance);
255 renderBlock.flags |= ((renderBlock.layer & RenderLayers::Sky) != RenderLayers::None) ? RenderItemFlags::Backdrop : RenderItemFlags::None;
256
257 renderBlock.materialInstance = materialInstance;
258
259 getTransparencyState(renderer->getRenderStates(), materialInstance, renderBlock);
260 renderBlock.drawOrder = materialInstance->options.drawOrder != 0 ? materialInstance->options.drawOrder : renderComponent.drawOrder;
261 }
262
263 return missing;
264}
265
266void Cogs::Core::GenerateListTask::initialize(RenderTaskContext* renderContext)
267{
268 RenderTask::initialize(renderContext);
269}
270
271void Cogs::Core::GenerateListTask::cleanup(RenderTaskContext* renderContext)
272{
273 if (HandleIsValid(listObjectBuffer.gpu)) {
274 IBuffers* buffers = renderContext->device->getBuffers();
275 buffers->releaseBuffer(listObjectBuffer.gpu);
276 listObjectBuffer.gpu = Cogs::BufferHandle::NoHandle;
277 }
278}
279
280void Cogs::Core::GenerateListTask::apply(RenderTaskContext * renderTaskContext)
281{
282 RenderInstrumentationScope(renderTaskContext->device->getImmediateContext(), SCOPE_RENDERING, "GenerateListTask::apply");
283
284 clipShapeCache.handles[0] = ComponentModel::ComponentHandle::Empty();
285 clipShapeCache.data[0] = ClipShapeCache::Item{
286 .clipShape = ClipShapeType::None
287 };
288 clipShapeCache.count = 1;
289
290 auto & renderList = *output.get(RenderResourceType::RenderList)->renderList;
291
292 auto context = renderTaskContext->context;
293 auto renderer = renderTaskContext->renderer;
294
295 ICapabilities* caps = renderTaskContext->device->getCapabilities();
296
297 // Init list object buffer if requested
298 bool useListObjectBuffer = false;
299 const StringView listObjectBufferKey = "renderer.listObjectBuffer";
300 if (Variable* var = context->variables->get(listObjectBufferKey); !var->isEmpty()) {
301 useListObjectBuffer = var->getBool();
302 }
303 else {
304 context->variables->set(listObjectBufferKey, useListObjectBuffer);
305 }
306 if (useListObjectBuffer && caps->getDeviceCapabilities().ConstantBufferRange) {
307 listObjectBuffer.stride = std::max(uint32_t(sizeof(ObjectBuffer)), uint32_t(caps->getDeviceCapabilities().ConstantBufferOffsetAlignment));
308 }
309 else {
310 listObjectBuffer.stride = 0;
311 }
312 listObjectBuffer.fill = 0;
313
314 renderList.clear();
315 generateItems(context, renderList.batch, renderer, context->renderSystem, context->meshSystem);
316
317 for (auto & staticModel : context->staticModelSystem->pool) {
318 if (!staticModel.model) continue;
319
320 auto renderSystem = context->staticModelSystem->getRenderSystem(&staticModel);
321 auto meshSystem = context->staticModelSystem->getMeshSystem(&staticModel);
322
323 if (!renderSystem || !renderSystem->pool.size()) continue;
324
325 auto batch = context->staticModelSystem->getRenderBatch(&staticModel);
326
327 if (batch->generation != renderSystem->getGeneration()) {
328 batch->clear();
329 auto missing = generateItems(context, *batch, renderer, renderSystem, meshSystem);
330 batch->missing = missing;
331 batch->generation = renderSystem->getGeneration();
332 }
333
334 renderList.batches.emplace_back(batch);
335 }
336
337 for (const SubMeshRenderComponent& renderComponent : context->subMeshRenderSystem->pool) {
338 if (!renderComponent.isVisible()) continue;
339
340 auto & renderData = context->subMeshRenderSystem->getData<SubMeshRenderData>(&renderComponent);
341
342 const MeshComponent* meshComponent = renderData.meshComponent.resolveComponent<MeshComponent>();
343 if (meshComponent == nullptr) {
344 LOG_ERROR_ONCE(logger, "No mesh component defined");
345 continue;
346 }
347
348 RenderMesh * renderMesh = renderer->getRenderResources().getRenderMesh(meshComponent->meshHandle);
349
350 if (!renderMesh) continue;
351
352 Mesh * mesh = meshComponent->meshHandle.resolve();
353 const uint32_t meshCount = mesh->getCount();
354
355 size_t subMeshBegin = 0;
356 size_t subMeshEnd = mesh->getSubMeshes().size();
357
358 if ((0 <= renderComponent.subMesh) && (static_cast<size_t>(renderComponent.subMesh) < subMeshEnd)) {
359 subMeshBegin = renderComponent.subMesh;
360 subMeshEnd = subMeshBegin + 1;
361 }
362
363 for (size_t m = subMeshBegin; m < subMeshEnd; ++m) {
364 auto & subMesh = mesh->getSubMeshes()[m];
365
366 if (subMesh.numIndexes && renderMesh->streamsLayout.numStreams) {
367 auto materialInstance = ((renderComponent.materials.size() > m) ? renderComponent.materials[m] : renderComponent.materials.front()).resolve();
368
369 if (!materialInstance) continue;
370
371 RenderItem& renderBlock = createRenderItem(context, renderList.batch, &renderData.localToWorld, &renderComponent);
372 renderBlock.lod = renderComponent.lod;
373 renderBlock.layer = renderComponent.layer;
374 renderBlock.flags |= renderComponent.castShadows() ? RenderItemFlags::CastShadows : RenderItemFlags::None;
375
376 renderBlock.cullingIndex = renderData.cullingIndex;
377
378 renderBlock.meshData = renderMesh;
379 if (subMesh.numIndexes == uint32_t(-1)) {
380 renderBlock.startIndex = 0;
381 renderBlock.numIndexes = meshCount;
382 }
383 else {
384 renderBlock.startIndex = subMesh.startIndex;
385 renderBlock.numIndexes = subMesh.numIndexes;
386 if (meshCount <= renderBlock.startIndex || meshCount < renderBlock.startIndex + renderBlock.numIndexes) {
387 LOG_ERROR_ONCE(logger, "SubMeshRenderComponent draw range is out of bounds");
388 continue;
389 }
390 }
391
392 renderBlock.primitiveType = subMesh.primitiveType;
393
394 if (mesh->isMeshFlagSet(MeshFlags::Skinned)) {
395 auto animationComponent = renderComponent.getComponent<AnimationComponent>();
396 const auto & animationData = context->animationSystem->getData(animationComponent);
397 renderBlock.poseData = animationData.pose.get();
398 }
399
400 renderBlock.flags |= !mesh->isCCW() ? RenderItemFlags::Clockwise : RenderItemFlags::None;
401 renderBlock.flags |= getMaterialFlags(materialInstance);
402 renderBlock.flags |= ((renderBlock.layer & RenderLayers::Sky) != RenderLayers::None) ? RenderItemFlags::Backdrop : RenderItemFlags::None;
403
404 renderBlock.materialInstance = materialInstance;
405
406 getTransparencyState(renderer->getRenderStates(), materialInstance, renderBlock);
407 renderBlock.drawOrder = materialInstance->options.drawOrder != 0 ? materialInstance->options.drawOrder : renderComponent.drawOrder;
408 }
409 }
410 }
411
412 for (const auto & renderComponent : context->instancedMeshRenderSystem->pool) {
413 if (!renderComponent.isVisible()) continue;
414
415 auto & renderData = context->instancedMeshRenderSystem->getData<InstancedMeshRenderData>(&renderComponent);
416
417 const MeshComponent * meshComponent = renderData.meshComponent.resolveComponent<MeshComponent>();
418
419 assert(meshComponent && "No mesh component defined");
420
421 RenderMesh * renderMesh = renderer->getRenderResources().getRenderMesh(meshComponent->meshHandle);
422 if (!renderMesh) continue;
423
424 RenderMesh * instanceRenderMesh = renderer->getRenderResources().getRenderMesh(renderComponent.instanceMesh);
425 if (!instanceRenderMesh) continue;
426
427 Mesh * mesh = meshComponent->meshHandle.resolve();
428 Mesh * instanceMesh = renderComponent.instanceMesh.resolve();
429
430 MaterialInstance * materialInstance = renderComponent.material.resolve();
431 if (!materialInstance) continue;
432
433 const uint32_t instanceCount = InstancedMeshRenderComponent::getRenderCount(renderComponent.startInstance, renderComponent.instanceCount, instanceMesh->getCount());
434 if (instanceCount == 0) {
435 continue;
436 }
437
438 RenderItem& renderBlock = createRenderItem(context, renderList.batch, &renderData.localToWorld, &renderComponent);
439 renderBlock.lod = renderComponent.lod;
440 renderBlock.layer = renderComponent.layer;
441 renderBlock.flags |= renderComponent.castShadows() ? RenderItemFlags::CastShadows : RenderItemFlags::None;
442 renderBlock.flags |= RenderItemFlags::Instanced;
443
444 renderBlock.cullingIndex = renderData.cullingIndex;
445
446 renderBlock.meshData = renderMesh;
447 renderBlock.instanceData = instanceRenderMesh;
448 renderBlock.startIndex = renderComponent.startIndex;
449 renderBlock.numIndexes = InstancedMeshRenderComponent::getRenderCount(renderComponent.startIndex, renderComponent.vertexCount, mesh->getCount());
450 renderBlock.startInstance = renderComponent.startInstance;
451 renderBlock.numInstances = instanceCount;
452 renderBlock.primitiveType = renderComponent.primitiveType != (PrimitiveType::EPrimitiveType) - 1 ? renderComponent.primitiveType : mesh->primitiveType;
453
454 if (mesh->isMeshFlagSet(MeshFlags::Skinned)) {
455 auto animationComponent = renderComponent.getComponent<AnimationComponent>();
456 const auto & animationData = context->animationSystem->getData(animationComponent);
457 renderBlock.poseData = animationData.pose.get();
458 }
459
460 renderBlock.flags |= !mesh->isCCW() ? RenderItemFlags::Clockwise : RenderItemFlags::None;
461 renderBlock.flags |= getMaterialFlags(materialInstance);
462 renderBlock.flags |= ((renderBlock.layer & RenderLayers::Sky) != RenderLayers::None) ? RenderItemFlags::Backdrop : RenderItemFlags::None;
463
464 renderBlock.materialInstance = materialInstance;
465
466 getTransparencyState(renderer->getRenderStates(), materialInstance, renderBlock);
467 renderBlock.drawOrder = materialInstance->options.drawOrder != 0 ? materialInstance->options.drawOrder : renderComponent.drawOrder;
468 }
469
470 for (const SpriteBatch& batch : context->spriteRenderSystem->getSpriteBatches()) {
471 if (!batch.count) continue;
472
473 RenderMesh * renderMesh = renderer->getRenderResources().getRenderMesh(batch.mesh);
474
475 if (!renderMesh || !renderMesh->numVertexes) {
476 continue;
477 }
478
479 MaterialInstance * materialInstance = batch.material.resolve();
480
481 if (!materialInstance) continue;
482
483 RenderItem& renderBlock = createRenderItem(context, renderList.batch, &batch.transform, nullptr);
484 renderBlock.lod = batch.lod;
485 renderBlock.cullingIndex = NoCullingIndex;
486 renderBlock.depth = batch.depth;
487
488 renderBlock.flags |= batch.flags | RenderItemFlags::Sprite;
489 renderBlock.layer = RenderLayers::Overlay;
490
491 renderBlock.setBounds(&batch.bbox);
492
493 renderBlock.materialInstance = materialInstance;
494 renderBlock.blendState = (uint16_t)batch.blendMode;
495
496 renderBlock.meshData = renderMesh;
497 renderBlock.startIndex = static_cast<uint32_t>(batch.start);
498 renderBlock.numIndexes = static_cast<uint32_t>(batch.count);
499 renderBlock.primitiveType = batch.mesh->primitiveType;
500 }
501
502 if (context->variables->getOrAdd("renderer.showCoordSys", false)) {
503
504 static auto renderCallback = [](RenderTaskContext * taskContext, DrawContext * drawContext, const RenderItem * item)
505 {
506 RenderInstrumentationScope(taskContext->device->getImmediateContext(), SCOPE_RENDERING, "showCoordSysRender");
507 auto * renderer = taskContext->renderer;
508 const auto M = renderer->getProjectionMatrix(glm::frustum(-0.7f, 0.7f, -0.7f, 0.7f, 1.0f, 3.0f)) * glm::translate(glm::vec3(0,0,-2.0f)) * glm::mat4(glm::mat3(drawContext->cameraData->viewMatrix));
509 auto b = drawContext->cameraData->viewportOrigin.y + drawContext->cameraData->viewportSize.y;
510 auto * deviceContext = taskContext->device->getImmediateContext();
511 if(renderer->getDevice()->getType() == GraphicsDeviceType::OpenGLES30 ||
512 renderer->getDevice()->getType() == GraphicsDeviceType::OpenGL20)
513 deviceContext->setViewport(0, 0, 80, 80);
514 else
515 deviceContext->setViewport(0, b - 80, 80, 80);
516 drawCoordSys(taskContext, drawContext, item, M, true);
517 auto & o = drawContext->cameraData->viewportOrigin;
518 auto & s = drawContext->cameraData->viewportSize;
519 deviceContext->setViewport(o.x, o.y, s.x, s.y);
520 };
521
522 auto & item = renderList.createCustom(nullptr);
523 item.layer = RenderLayers::Annotations;
524 item.materialInstance = getDefaultMaterialInstance(context).resolve();
525 item.blendState = (uint16_t)BlendMode::None;
526 item.depthState = (uint16_t)DepthMode::Disabled;
527
528 item.flags |= RenderItemFlags::Custom2 | RenderItemFlags::DisableCulling;
529 item.callback = renderCallback;
530 }
531
532 if (context->variables->getOrAdd("renderer.showFrustums", false)) {
533
534 static auto renderCallback = [](RenderTaskContext * taskContext, DrawContext * drawContext, const RenderItem * item)
535 {
536 RenderInstrumentationScope(taskContext->device->getImmediateContext(), SCOPE_RENDERING, "showFrustumsRender");
537 const auto * camData = item->getCallbackData<CameraData>();
538 const auto M = drawContext->cameraData->viewProjection * camData->inverseViewMatrix * glm::inverse(camData->rawProjectionMatrix);
539 drawOneOneWireBox(taskContext, drawContext, item, M, static_cast<unsigned>(reinterpret_cast<size_t>(item->getCallbackData2<void>())));
540 };
541
542 size_t o = 0;
543 auto genFrustumItem = [&](CameraData* cd, size_t i)
544 {
545 auto & item = renderList.createCustom(nullptr);
546 item.layer = RenderLayers::Annotations;
547 item.materialInstance = getDefaultMaterialInstance(context).resolve();
548 item.blendState = (uint16_t)BlendMode::None;
549 item.depthState = (uint16_t)DepthMode::Default;
550
551 item.flags |= RenderItemFlags::Custom2 | RenderItemFlags::DisableCulling;
552 item.setCallbackData(cd);
553 item.setCallbackData2(reinterpret_cast<void*>(i));
554 item.callback = renderCallback;
555 o++;
556 };
557
558 auto* pipeService = context->services->getService<PipelineService>();
559 for (const auto* run : pipeService->runs) {
560 if (run->cameraData) {
561 genFrustumItem(run->cameraData, o);
562 }
563 }
564
565 for (const auto & cameraComp : context->cameraSystem->pool) {
566 if ((cameraComp.flags & CameraFlags::EnableRender) != 0) {
567 auto & camData = context->cameraSystem->getData(&cameraComp);
568 genFrustumItem(&camData, o);
569 }
570 }
571 for (const auto & lightComp : context->lightSystem->pool) {
572 auto & lightData = context->lightSystem->getData(&lightComp);
573 if (lightData.castShadows) {
574 for (unsigned i = 0; i < lightData.numViewports; i++) {
575 genFrustumItem(&lightData.lightCameraData[i], i);
576 }
577 }
578 }
579
580 }
581
582
583 for (auto & extension : renderer->getExtensions()) {
584 extension->generateCommands(renderTaskContext, &renderList);
585 }
586
587 // Update list object buffer if active
588 if (listObjectBuffer.isInUse()) {
589
590 if (2 * std::max(minObjectBufferCapacity, listObjectBuffer.fill) < listObjectBuffer.cpuCapacity) {
591 listObjectBuffer.cpuCapacity = listObjectBuffer.cpuCapacity / 2;
592 listObjectBuffer.cpu.resize(size_t(listObjectBuffer.stride)* listObjectBuffer.cpuCapacity);
593 }
594
595 if (listObjectBuffer.gpuCapacity != listObjectBuffer.cpuCapacity) {
596
597 if (listObjectBuffer.gpuCapacity == 0) {
598 LOG_DEBUG(logger, "Setting up list object buffer GPU storage");
599 }
600
601 listObjectBuffer.gpuCapacity = listObjectBuffer.cpuCapacity;
602
603 IBuffers* buffers = renderTaskContext->device->getBuffers();
604
605 if (HandleIsValid(listObjectBuffer.gpu)) {
606 buffers->releaseBuffer(listObjectBuffer.gpu);
607 listObjectBuffer.gpu = Cogs::BufferHandle::NoHandle;
608 }
609
610 listObjectBuffer.gpu = buffers->loadBuffer(nullptr,
611 size_t(listObjectBuffer.stride) * listObjectBuffer.gpuCapacity,
615 buffers->annotate(listObjectBuffer.gpu, "ListObjectBuffer");
616
617 }
618
619 if (listObjectBuffer.fill) {
620 IContext* immediateContext = renderTaskContext->device->getImmediateContext();
621 immediateContext->updateBuffer(listObjectBuffer.gpu,
622 listObjectBuffer.cpu.data(),
623 size_t(listObjectBuffer.stride) * listObjectBuffer.fill);
624 }
625 renderList.listObjectBuffer = &listObjectBuffer;
626 }
627 else if (HandleIsValid(listObjectBuffer.gpu)) {
628
629 IBuffers* buffers = renderTaskContext->device->getBuffers();
630 buffers->releaseBuffer(listObjectBuffer.gpu);
631 listObjectBuffer.gpu = Cogs::BufferHandle::NoHandle;
632 listObjectBuffer.gpuCapacity = 0;
633
634 listObjectBuffer.cpu.clear();
635 listObjectBuffer.cpuCapacity = 0;
636
637 LOG_DEBUG(logger, "Released list object buffer GPU storage");
638 }
639
640 renderList.clipShapeCache = &clipShapeCache;
641}
static uint32_t getRenderCount(uint32_t startIndex, uint32_t instanceCount, uint32_t meshCount)
Get number of instanced Meshes to render.
Log implementation class.
Definition: LogManager.h:139
Contains the Engine, Renderer, resource managers and other systems needed to run Cogs....
@ InvertedCube
Clip the inside of a cube.
@ None
No clipping at all.
@ Cube
Clip the outside of a cube,.
bool HandleIsValid(const ResourceHandle_t< T > &handle)
Check if the given resource is valid, that is not equal to NoHandle or InvalidHandle.
@ EnableRender
Renderable.
@ Blend
Render with regular alpha blending.
@ None
No blending enabled for opaque shapes, defaults to Blend for transparent shapes.
@ Default
Default, depth test & write enabled.
@ Disabled
Depth test/write disabled.
constexpr Log getLogger(const char(&name)[LEN]) noexcept
Definition: LogManager.h:180
@ OpenGLES30
Graphics device using the OpenGLES 3.0 API.
@ OpenGL20
Graphics device using OpenGL, supporting at least OpenGL 2.0.
@ Write
The buffer can be mapped and written to by the CPU after creation.
Definition: Flags.h:50
@ ConstantBuffer
The buffer can be bound as input to effects as a constant buffer.
Definition: Flags.h:72
static ComponentHandle Empty()
Returns an empty, invalid handle. Will evaluate to false if tested against using operator bool().
Definition: Component.h:119
EMaterialFlags
Material flags.
Definition: Material.h:41
@ OverrideAlpha
Override alpha of any inheriting materials.
Definition: Material.h:54
@ CustomBucket
Items with this flag should be put in Custom rendering buckets.
Definition: Material.h:64
MaterialInstanceHandle masterInstance
Master material instance overriding properties in this instance if override is enabled.
@ Instanced
Mesh contains instance data.
Definition: Mesh.h:70
ResourceType * resolve() const
Resolve the handle, returning a pointer to the actual resource.
static const Handle_t NoHandle
Represents a handle to nothing.
Definition: Common.h:77
EPrimitiveType
Primitive type enumeration.
Definition: Common.h:114
@ Dynamic
Buffer will be loaded and modified with some frequency.
Definition: Flags.h:30