Cogs.Core
RenderListTask.cpp
1#include "RenderListTask.h"
2#include "GenerateListTask.h"
3#include "FilterListTask.h"
4
5#include "Renderer/Renderer.h"
6#include "Renderer/RenderTexture.h"
7#include "Renderer/RenderMaterialInstance.h"
8#include "Renderer/RenderResources.h"
9#include "Renderer/RenderStateUpdater.h"
10#include "Renderer/RenderTexture.h"
11#include "Renderer/RenderTarget.h"
12#include "Renderer/EnginePermutations.h"
13
14#include "Platform/Instrumentation.h"
15
16#include "Context.h"
17
18#include "Services/Time.h"
19#include "Services/Variables.h"
20
21#include "Rendering/ITextures.h"
22#include "Rendering/IRenderTargets.h"
23#include "Rendering/ICapabilities.h"
24
25#include "Foundation/Logging/Logger.h"
26#include "Foundation/Collections/SmallVector.h"
27
28#include <glm/glm.hpp>
29#include <glm/gtc/color_space.hpp>
30
31#include <sstream>
32
33namespace
34{
35 Cogs::Logging::Log logger = Cogs::Logging::getLogger("RenderListTask");
36}
37
38Cogs::Core::RenderListTask::RenderListTask()
39{
40}
41
42Cogs::Core::RenderListTask::~RenderListTask()
43{
44}
45
46void Cogs::Core::RenderListTask::initialize(RenderTaskContext * context)
47{
48 RenderTask::initialize(context);
49
50 auto renderTargets = context->device->getRenderTargets();
51
52 blendState = renderTargets->loadBlendState(&context->states->blendStates[size_t(blendMode)].color,
53 &context->states->blendStates[size_t(blendMode)].alpha, 1, BlendFlags::IndependentBlend);
54 depthState = context->states->commonDepthStates[(int)DepthMode::Count*(int)depthFunc+(int)depthMode];
55
56 scopeName = context->renderer->getEnginePermutations().get(permutationIndex)->getName();
57}
58
59void Cogs::Core::RenderListTask::apply(RenderTaskContext * context)
60{
61 DynamicRenderInstrumentationScope(context->device->getImmediateContext(), SCOPE_RENDERING, "RenderListTask", scopeName.c_str());
62
63 if (!validate(context, 1, 1)) return;
64
65 const auto renderList = input.get(RenderResourceType::RenderList)->renderList;
66 auto renderTarget = output.get(RenderResourceType::RenderTarget)->renderTarget;
67
68 if (!renderList) {
69 LOG_ERROR(logger, "Missing input render list for %s.", scopeName.c_str());
70 return;
71 }
72
73 if (!renderTarget) {
74 LOG_ERROR(logger, "Missing output target for %s.", scopeName.c_str());
75 return;
76 }
77
78 const size_t previousHash = lastHash;
79 if (isStatic()) {
80 if (renderList->hash == lastHash) return;
81 lastHash = renderList->hash;
82 }
83
84 if (renderList->viewportData->viewportSize.x == 0 || renderList->viewportData->viewportSize.y == 0) return;
85
86 auto deviceContext = context->device->getImmediateContext();
87
88 setupRenderTarget(context, renderTarget, renderList->viewportData);
89
90 updateEngineBuffers(context, renderTarget, renderList->viewportData, nullptr);
91
92 renderItems(context,
93 renderTarget,
94 renderList,
95 bucketMask,
96 stateChangeMask);
97
98 if (isStatic() && hadUnreadyBinding) {
99 lastHash = previousHash;
100 }
101
102 if (context->device->getCapabilities()->getDeviceCapabilities().RenderPass &&
103 !renderList->viewportData->bindRenderTargetCallback) {
104 deviceContext->endRenderPass();
105 }
106
107 for (auto t : renderTarget->textures) {
108 if (t->description.flags & TextureFlags::GenerateMipMaps) {
109 context->device->getTextures()->generateMipmaps(t->textureHandle);
110 }
111 }
112}
113
114bool Cogs::Core::RenderListTask::validate(RenderTaskContext * /*context*/, size_t expectedInputs, size_t expectedOutputs)
115{
116 const bool validInputs = input.resources.size() >= expectedInputs;
117 const bool validOutputs = output.resources.size() >= expectedOutputs;
118
119 if (validInputs && validOutputs) {
120 return true;
121 } else {
122 LOG_ERROR(logger, "Failed validating connections for %s.", scopeName.c_str());
123 return false;
124 }
125}
126
127void Cogs::Core::RenderListTask::applyMaterial(const DrawContext & drawContext, const RenderItem & item, const EffectBinding * binding)
128{
129 updateEnvironmentBindings(&drawContext, binding);
130
131 auto permutation = drawContext.permutation;
132
133 for (auto & buffer : drawContext.permutation->constantBuffers.buffers) {
134 permutation->bufferHandles.resize(permutation->constantBuffers.buffers.size());
135
136 if (!HandleIsValid(permutation->bufferHandles[buffer.index])) {
137 IBuffers* buffers = drawContext.device->getBuffers();
138 permutation->bufferHandles[buffer.index] = buffers->loadBuffer(nullptr, buffer.size, Usage::Dynamic, AccessMode::Write, BindFlags::ConstantBuffer);
139 buffers->annotate(permutation->bufferHandles[buffer.index], "RenderListTask::applyMaterial");
140 }
141
142 drawContext.deviceContext->updateBuffer(permutation->bufferHandles[buffer.index], buffer.content.data(), buffer.size);
143 drawContext.deviceContext->setConstantBuffer(buffer.name, permutation->bufferHandles[buffer.index]);
144 }
145}
146
147void Cogs::Core::RenderListTask::renderBatched(RenderTaskContext * taskContext,
148 DrawContext & drawContext,
149 const RenderList* renderList,
150 const RenderItems & items,
151 BucketMask /*bucketMask*/,
152 StateChangeFlags stateChangeMask,
153 bool batched)
154{
155 auto renderer = taskContext->renderer;
156 auto device = renderer->getDevice();
157
158 auto context = device->getImmediateContext();
159
160 bool useVAO = device->getCapabilities()->getDeviceCapabilities().VertexArrayObjects;
161 if (useVAO && taskContext->context->variables->get("renderer.disableVertexArrayObjects", false)) {
162 useVAO = false;
163 }
164
165 auto setViewport = [&](const CameraData & c) {
166 context->setViewport(
167 c.viewportOrigin.x,
168 c.viewportOrigin.y,
169 (!viewportFromTarget && (c.viewportSize.x != 0)) ? c.viewportSize.x : static_cast<float>(defaultViewportSize.x),
170 (!viewportFromTarget && (c.viewportSize.y != 0)) ? c.viewportSize.y : static_cast<float>(defaultViewportSize.y));
171 };
172
173 const EffectBinding* currentBinding = nullptr;
174 bool skippedPrevious = false;
175
176 size_t o = 0;
177 size_t n = items.size();
178 while (o < n) {
179
180 size_t m = batched ? populateObjectBuffer(&drawContext, items.data(), o, n) : o + 1;
181
182 for (size_t i = o; i < m; i++) {
183 const RenderItem & currentItem = items[i];
184
185 if (currentItem.isCustom1() || currentItem.isCustom2()) {
186 bool bindingReady = true;
187 if (currentItem.streamsLayout) {
188 const CameraData* itemCameraData = currentItem.viewportData ? currentItem.viewportData : drawContext.cameraData;
189 const RenderPassOptions passOptions = initRenderPassOptions(*itemCameraData, currentItem.materialInstance);
190 const ClipShapeType clipShape = renderList->clipShapeCache->data[currentItem.clipShapeIx].clipShape;
191
192 RenderMaterialInstance* renderMaterialInstance = const_cast<RenderMaterialInstance*>(currentItem.renderMaterialInstance);
193 drawContext.binding = renderMaterialInstance->checkReady(*currentItem.streamsLayout, drawContext.permutation, passOptions, clipShape, drawContext.renderTarget);
194
195 bindingReady = drawContext.binding != nullptr;
196 }
197
198 if (bindingReady) {
199 if (currentItem.isCustom1()) {
200 (*currentItem.callback)(taskContext, &drawContext, &currentItem);
201 }
202 else {
203 (*currentItem.callback2)(taskContext, &drawContext, this, &currentItem);
204 }
205 }
206 else {
207 hadUnreadyBinding = true;
208 }
209 continue;
210 }
211
212 const StateChangeFlags stateChanges = (skippedPrevious ? StateChangeFlags::ChangeAll : currentItem.stateChanges) & stateChangeMask;
213
214 if ((stateChanges & StateChangeFlags::ChangeMaterialInstance) != 0) {
215 const MeshStreamsLayout* streamsLayout = nullptr;
216 MeshStreamsLayout instancedStreamsLayout{};
217
218 if (currentItem.isInstanced()) {
219 const RenderMesh* renderMesh = currentItem.meshData;
220 const RenderMesh* instanceMesh = currentItem.instanceData;
221
222 if (instanceMesh == nullptr) {
223 streamsLayout = &currentItem.meshData->streamsLayout;
224 }
225 else {
226 if (MeshStreamsLayout::maxStreams < renderMesh->streamsLayout.numStreams + instanceMesh->streamsLayout.numStreams) {
227 LOG_ERROR(logger, "max streams (%zu) < mesh streams (%u) + instance streams (%u)",
228 MeshStreamsLayout::maxStreams, renderMesh->streamsLayout.numStreams, instanceMesh->streamsLayout.numStreams);
229 continue;
230 }
231
232 // Add vertex streams
233 instancedStreamsLayout.numStreams = 0;
234 for (size_t j = 0; j < renderMesh->streamsLayout.numStreams; j++) {
235 instancedStreamsLayout.vertexFormats[instancedStreamsLayout.numStreams++] = renderMesh->streamsLayout.vertexFormats[j];
236 }
237
238 // Add instance streams
239 for (size_t j = 0; j < instanceMesh->streamsLayout.numStreams; j++) {
240 instancedStreamsLayout.vertexFormats[instancedStreamsLayout.numStreams++] = instanceMesh->streamsLayout.vertexFormats[j];
241 }
242 instancedStreamsLayout.updateHash();
243
244 streamsLayout = &instancedStreamsLayout;
245 }
246 }
247 else {
248 streamsLayout = &currentItem.meshData->streamsLayout;
249 }
250
251 const CameraData* itemCameraData = currentItem.viewportData ? currentItem.viewportData : drawContext.cameraData;
252 const RenderPassOptions passOptions = initRenderPassOptions(*itemCameraData, currentItem.materialInstance);
253 const ClipShapeType clipShape = renderList->clipShapeCache->data[currentItem.clipShapeIx].clipShape;
254
255 RenderMaterialInstance* renderMaterialInstance = const_cast<RenderMaterialInstance*>(currentItem.renderMaterialInstance);
256 currentBinding = renderMaterialInstance->checkReady(*streamsLayout, drawContext.permutation, passOptions, clipShape, drawContext.renderTarget);
257
258 if (!currentBinding) {
259 skippedPrevious = true;
260 hadUnreadyBinding = true;
261 continue;
262 }
263 skippedPrevious = false;
264 drawContext.binding = currentBinding;
265 }
266
267 if ((stateChanges & StateChangeFlags::ChangeViewport) != 0) {
268 setViewport(*drawContext.cameraData);
269 }
270
271 if ((stateChanges & StateChangeFlags::ChangeDepthStencilState) != 0) {
272 context->setDepthStencilState(taskContext->states->commonDepthStates[currentItem.depthState]);
273 }
274
275 if ((stateChanges & StateChangeFlags::ChangeBlendState) != 0) {
276 context->setBlendState(taskContext->states->blendStates[currentItem.blendState].handle);
277 }
278
279 if ((stateChanges & StateChangeFlags::ChangeRasterizerState) != 0) {
280 context->setRasterizerState(taskContext->states->rasterizerStateHandles[currentItem.rasterizerState]);
281 }
282
283 if ((stateChanges & StateChangeFlags::ChangeViewportData) != 0) {
284 const ClipShapeCache::Item& clipShape = renderList->clipShapeCache->data[currentItem.clipShapeIx];
285 updateViewportBuffer(taskContext, taskContext->engineBuffers->sceneBufferHandle, taskContext->engineBuffers->viewBufferHandle, drawContext.renderTarget, currentItem.viewportData ? currentItem.viewportData : drawContext.cameraData, &clipShape.clipEquations);
286 }
287
288 if ((stateChanges & StateChangeFlags::ChangeMaterialVariant) != 0) {
289 applyMaterialPermutation(taskContext, &drawContext, currentBinding, currentItem.renderMaterialInstance);
290
291 applyMaterial(drawContext, currentItem, currentBinding);
292 }
293
294 if ((stateChanges & StateChangeFlags::ChangeMaterialInstance) != 0) {
295 applyMaterialInstance(&drawContext, currentBinding, currentItem.renderMaterialInstance);
296 }
297
298 if ((stateChanges & StateChangeFlags::ChangeMesh) != 0) {
299
300 VertexArrayObjectHandle vao = VertexArrayObjectHandle::NoHandle;
301 if (useVAO && !currentItem.isInstanced() && !currentItem.isCustom()) {
302 vao = currentItem.meshData->getVertexArrayObject(device, currentBinding->renderEffect);
303 }
304
305 if (HandleIsValid(vao)) {
306 context->setVertexArrayObject(vao);
307 }
308 else {
309 context->setVertexBuffers(currentItem.meshData->vertexBuffers, currentItem.meshData->streamsLayout.numStreams, currentItem.meshData->vertexStrides, currentItem.meshData->vertexOffsets);
310
311 if (currentItem.meshData->indexBuffer != IndexBufferHandle::NoHandle) {
312 context->setIndexBuffer(currentItem.meshData->indexBuffer, currentItem.meshData->indexStride, currentItem.meshData->indexOffset);
313 }
314
315 }
316 }
317 if (batched) {
318 applyMaterialPerObjectBatched(&drawContext, currentItem.renderMaterialInstance, currentItem, i - o, currentBinding);
319 }
320 else {
321 applyMaterialPerObject(&drawContext, currentItem.renderMaterialInstance, currentItem, currentBinding);
322 }
323
324 if (currentItem.isInstanced()) {
325
326 if (currentItem.instanceData) {
327 auto renderMesh = currentItem.meshData;
328 auto instanceMesh = currentItem.instanceData;
329
330 assert(renderMesh && instanceMesh && "Invalid instanced rendering data.");
331 assert(renderMesh->streamsLayout.numStreams && instanceMesh->streamsLayout.numStreams && "Missing instanced render buffers.");
332 assert(renderMesh->streamsLayout.numStreams + instanceMesh->streamsLayout.numStreams <= MeshStreamsLayout::maxStreams);
333
335 uint32_t strides[MeshStreamsLayout::maxStreams];
336 uint32_t offsets[MeshStreamsLayout::maxStreams];
337
338 // Add vertex streams
339 size_t numStreams = 0;
340 for (size_t j = 0; j < renderMesh->streamsLayout.numStreams; j++) {
341 vertexBuffers[numStreams] = renderMesh->vertexBuffers[j];
342 strides[numStreams] = renderMesh->vertexStrides[j];
343 offsets[numStreams] = renderMesh->vertexOffsets[j];
344 numStreams++;
345 }
346
347 // Add instance streams
348 for (size_t j = 0; j < instanceMesh->streamsLayout.numStreams; j++) {
349 vertexBuffers[numStreams] = instanceMesh->vertexBuffers[j];
350 strides[numStreams] = instanceMesh->vertexStrides[j];
351 offsets[numStreams] = instanceMesh->vertexOffsets[j];
352 numStreams++;
353 }
354
355 context->setVertexBuffers(vertexBuffers, numStreams, strides, offsets);
356 }
357
358 if (currentItem.meshData->indexBuffer) {
359 context->setIndexBuffer(currentItem.meshData->indexBuffer);
360 context->drawInstancedIndexed(currentItem.primitiveType, currentItem.startInstance, currentItem.numInstances, currentItem.startIndex, currentItem.numIndexes);
361 } else {
362 context->drawInstanced(currentItem.primitiveType, currentItem.startIndex, currentItem.numIndexes, currentItem.startInstance, currentItem.numInstances);
363 }
364
365 } else if(currentItem.hasObjectArrayBufferSlot()){
366
367 // Use instance index to access the object array buffer in shader
368 uint32_t startInstance = currentItem.objectArrayBufferSlot % ArrayObjectBuffer::arrayGranularity;
369 uint32_t numInstances = 1;
370
371 if (currentItem.meshData->indexBuffer != IndexBufferHandle::NoHandle) {
372 context->drawInstancedIndexed(currentItem.primitiveType, startInstance, numInstances, currentItem.startIndex, currentItem.numIndexes);
373 } else {
374 context->drawInstanced(currentItem.primitiveType, currentItem.startIndex, currentItem.numIndexes, startInstance, numInstances);
375 }
376
377 } else {
378
379 if (currentItem.meshData->indexBuffer != IndexBufferHandle::NoHandle) {
380 context->drawIndexed(currentItem.primitiveType, currentItem.startIndex, currentItem.numIndexes);
381 } else {
382 context->draw(currentItem.primitiveType, currentItem.startIndex, currentItem.numIndexes);
383 }
384 }
385 }
386
387 o = m;
388 }
389
390
391}
392
393void Cogs::Core::RenderListTask::setupRenderTarget(RenderTaskContext * context, RenderTarget * renderTarget, const CameraData * viewportData)
394{
395 defaultViewportSize.x = renderTarget->width;
396 defaultViewportSize.y = renderTarget->height;
397
398 auto deviceContext = context->device->getImmediateContext();
399
400 const RenderSettings& renderSettings = context->renderer->getSettings();
401 MaterialOptions defaultMaterialOptions;
402 RenderPassOptions defaultPassOptions;
403
404 const bool isBackBuffer =
405 !HandleIsValid(renderTarget->renderTargetHandle) &&
406 !HandleIsValid(renderTarget->depthTargetHandle);
407 const bool doScissor = viewportData->passOptions &&
408 viewportData->passOptions->getFlag(RenderPassOptions::Flags::ScissorTest);
409 bool doColorClear = colorClear &&
410 (HandleIsValid(renderTarget->renderTargetHandle) || !HandleIsValid(renderTarget->depthTargetHandle));
411 bool doDepthClear = depthClear &&
412 (HandleIsValid(renderTarget->depthTargetHandle) || isBackBuffer);
413 if (isBackBuffer && (renderSettings.defaultRenderTargetClear == false)) {
414 doColorClear = false;
415 doDepthClear = false;
416 }
417 bool isCleared = false;
418
419 size_t nt = renderTarget->textures.size();
420 size_t no = std::max(size_t(1), nt);
421 glm::vec4 clearColorSRGB;
422 Collections::SmallVector<const float*, 8> clearColors(no);
423 {
424 glm::vec4 black(0.f);
425
426 size_t nc = renderTarget->clearColors.size();
427
428 for (size_t i = 0; i < no; i++) {
429
430 clearColors[i] = i == 0 ? glm::value_ptr(viewportData->useClearColor ? viewportData->clearColor : context->renderer->getBackgroundColor()) : glm::value_ptr(black);
431
432 if (i < nt && renderTarget->textures[i]->clearColorSet) {
433 clearColors[i] = renderTarget->textures[i]->clearColor;
434 }
435
436 else if (i < nc) {
437 clearColors[i] = glm::value_ptr(renderTarget->clearColors[i]);
438 }
439 }
440
441 if (no == 1) {
442 if ((isBackBuffer && renderSettings.defaultRenderTargetExpectsSRGB) || renderTarget->expectsSRGB) {
443 clearColorSRGB = glm::vec4(glm::convertLinearToSRGB(glm::make_vec3(clearColors[0])), clearColors[0][3]);
444 clearColors[0] = glm::value_ptr(clearColorSRGB);
445 }
446 }
447 }
448
449 if (viewportData->bindRenderTargetCallback) {
450 viewportData->bindRenderTargetCallback(viewportData->bindRenderTargetCallbackData);
451 }
452 else {
453 if(context->device->getCapabilities()->getDeviceCapabilities().RenderPass){
454 RenderPassInfo info;
455 info.renderTargetHandle = renderTarget->renderTargetHandle;
456 info.depthStencilHandle = renderTarget->depthTargetHandle;
457 for (size_t i = 0; i < no; i++) {
458 info.loadOp[i] = doColorClear ? LoadOp::Clear : LoadOp::Load;
459 info.storeOp[i] = discardColor ? StoreOp::Discard : StoreOp::Store;
460 info.clearValue[i][0] = clearColors[i][0];
461 info.clearValue[i][1] = clearColors[i][1];
462 info.clearValue[i][2] = clearColors[i][2];
463 info.clearValue[i][3] = clearColors[i][3];
464 }
465 info.depthLoadOp = doDepthClear ? LoadOp::Clear : LoadOp::Load;
466 info.depthStoreOp = discardDepth ? StoreOp::Discard : StoreOp::Store;
467 info.depthClearValue = context->renderer->getClearDepth();
468 info.depthReadOnly = !depthWrite;
469 deviceContext->beginRenderPass(info);
470 isCleared = true;
471 }
472 else{
473 deviceContext->setRenderTarget(renderTarget->renderTargetHandle, renderTarget->depthTargetHandle);
474 }
475 }
476
477 if (doScissor || doColorClear || doDepthClear || viewportData->bindRenderTargetCallback) {
478 // E.g. scissor test affects clears.'
479 // The bindRenderTargetCallback might change rasterization state.
480 uint16_t rasterizerStateIx = context->states->getRasterizerState(viewportData->passOptions ? *viewportData->passOptions : defaultPassOptions,
482 false, // RenderMode::Normal,
483 true);
484 RasterizerStateHandle& rasterizerStateHandle = context->states->rasterizerStateHandles[rasterizerStateIx];
485 deviceContext->setRasterizerState(rasterizerStateHandle);
486 }
487
488 if (doScissor) {
489 auto & rect = viewportData->passOptions->scissorRectangle;
490 deviceContext->setScissor(rect.x, rect.y, rect.z, rect.w);
491 }
492
493 if(!context->device->getCapabilities()->getDeviceCapabilities().RenderPass){
494 if (doColorClear && !isCleared) {
495 if (no == 1) {
496 deviceContext->clearRenderTarget(clearColors[0]);
497 }
498 else {
499 deviceContext->clearRenderTarget((const float**)clearColors.data(), static_cast<int>(nt));
500 }
501 }
502
503 if (doDepthClear && !isCleared) {
504 deviceContext->clearDepth(context->renderer->getClearDepth());
505 }
506 }
507
508 deviceContext->setBlendState(blendState);
509 deviceContext->setDepthStencilState(depthState);
510}
511
512void Cogs::Core::RenderListTask::renderItems(RenderTaskContext * taskContext,
513 RenderTarget* renderTarget,
514 const RenderList* renderList,
515 BucketMask bucketMask,
516 StateChangeFlags stateChangeMask)
517{
518 auto renderer = taskContext->renderer;
519 auto device = taskContext->device;
520 char buffer[ 128 ];
521
522 hadUnreadyBinding = false;
523
524 std::sprintf(buffer, "mask=0x%08X", static_cast<int>(bucketMask));
525 DynamicRenderInstrumentationScope(taskContext->device->getImmediateContext(), SCOPE_RENDERING, "RenderListTask::renderItems", buffer);
526
527 auto enginePermutation = renderer->getEnginePermutations().get(permutationIndex);
528
529 if(temporalOffsets){
530 uint32_t frame = taskContext->context->time->getFrame();
531 uint32_t widthDivisor = taskContext->context->variables->get("renderer.oit.TemporalUpscaleWidth", 1);
532 uint32_t heightDivisor = taskContext->context->variables->get("renderer.oit.TemporalUpscaleHeight", 1);
533 uint32_t i = frame % (widthDivisor * heightDivisor);
534 uint32_t w = i%widthDivisor;
535 uint32_t h = (i/widthDivisor)%heightDivisor;
536
537 CameraData &viewportData(*(CameraData*)renderList->viewportData);
538 viewportData.projectionMatrix = taskContext->renderer->getProjectionMatrix(viewportData.rawProjectionMatrix);
539 viewportData.projectionMatrix[2][0] += (float)w*(2.0f/widthDivisor)/(float)renderTarget->width;
540 viewportData.projectionMatrix[2][1] -= (float)h*(2.0f/heightDivisor)/(float)renderTarget->height;
541 viewportData.viewProjection = viewportData.projectionMatrix * viewportData.viewMatrix;
542 viewportData.inverseViewProjectionMatrix = glm::inverse(viewportData.viewProjection);
543 viewportData.inverseProjectionMatrix = glm::inverse(viewportData.projectionMatrix);
544 }
545
546 DrawContext drawContext;
547 drawContext.context = taskContext->context;
548 drawContext.renderer = renderer;
549 drawContext.device = device;
550 drawContext.deviceContext = device->getImmediateContext();
551 drawContext.cameraData = renderList->viewportData;
552 drawContext.permutationIndex = enginePermutation->getIndex();
553 drawContext.permutation = enginePermutation;
554 drawContext.engineBuffers = &renderer->getEngineBuffers();
555 drawContext.renderTarget = renderTarget;
556 drawContext.taskContext = taskContext;
557 drawContext.task = this;
558 drawContext.arrayObjectBuffer = renderList->arrayObjectBuffer;
559 drawContext.listObjectBuffer = renderList->listObjectBuffer;
560 drawContext.clipShapeCache = renderList->clipShapeCache;
561
562 bool batchObjectBuffer = drawContext.engineBuffers->objectBatch.count != 0;
563 const StringView batchObjectBufferKey = "renderer.batchObjectBuffer";
564 if (Variable* var = drawContext.context->variables->get(batchObjectBufferKey); !var->isEmpty()) {
565 batchObjectBuffer = var->getBool();
566 }
567 else {
568 drawContext.context->variables->set(batchObjectBufferKey, batchObjectBuffer);
569 }
570
571 // list object buffer has presendence
572 if (drawContext.arrayObjectBuffer && drawContext.arrayObjectBuffer->isInUse()) {
573 objectBufferMode = ObjectBufferMode::Array;
574 batchObjectBuffer = false;
575 }
576 else if (drawContext.listObjectBuffer && drawContext.listObjectBuffer->isInUse()) {
577 objectBufferMode = ObjectBufferMode::List;
578 batchObjectBuffer = false;
579 }
580 else if (drawContext.engineBuffers->objectBatch.count && batchObjectBuffer) {
581 objectBufferMode = ObjectBufferMode::Batched;
582 }
583 else {
584 objectBufferMode = ObjectBufferMode::Single;
585 batchObjectBuffer = false;
586 }
587
588 for (size_t b = 0; b < size_t(BucketType::Count); b++) {
589 if ((BucketMask(1 << b) & bucketMask) == 0) continue;
590
591 const RenderItems & items = renderList->buckets[b];
592 renderBatched(taskContext, drawContext, renderList, items, bucketMask, stateChangeMask, batchObjectBuffer);
593 }
594
595 if(temporalOffsets){
596 CameraData &viewportData(*(CameraData*)renderList->viewportData);
597 viewportData.projectionMatrix = taskContext->renderer->getProjectionMatrix(viewportData.rawProjectionMatrix);
598 viewportData.viewProjection = viewportData.projectionMatrix * viewportData.viewMatrix;
599 viewportData.inverseViewProjectionMatrix = glm::inverse(viewportData.viewProjection);
600 viewportData.inverseProjectionMatrix = glm::inverse(viewportData.projectionMatrix);
601 }
602}
Log implementation class.
Definition: LogManager.h:140
ClipShapeType
Specifices what kind of shape a clip shape has.
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
@ 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 constexpr size_t maxStreams
static const Handle_t NoHandle
Represents a handle to nothing.
Definition: Common.h:78
@ Back
Cull back facing primitives.
@ GenerateMipMaps
The texture supports automatic mipmap generation performed by the graphics device.
Definition: Flags.h:124
@ Dynamic
Buffer will be loaded and modified with some frequency.
Definition: Flags.h:30