1#include "RenderTaskFactory.h"
3#include "Serialization/RenderPipelineReader.h"
5#include "Systems/Core/CameraSystem.h"
7#include "Services/Variables.h"
10#include "GenerateListTask.h"
11#include "FilterListTask.h"
12#include "RenderListTask.h"
14#include "DeferredLightingTask.h"
15#include "TransparencyRenderTask.h"
16#include "TransparencyMergeTask.h"
17#include "TransparencyTemporalUpscaleTask.h"
18#include "TransparencyUpscaleTask.h"
20#include "PostProcessTask.h"
21#include "ComputeTask.h"
22#include "MipLevelsTask.h"
24#include "ClearResourceTask.h"
25#include "CopyResourceTask.h"
26#include "ResolveResourceTask.h"
27#include "ReadbackTask.h"
29#include "Renderer/Renderer.h"
30#include "Renderer/RenderPipelineManager.h"
32#include "Foundation/Logging/Logger.h"
33#include "Foundation/Collections/Pool.h"
44 std::unordered_map<std::string, TaskCreator> creators;
45 std::unordered_map<std::string, TaskDestroyer> destroyers;
47 template<
typename ResourceType>
48 Collections::Pool<ResourceType> & getPool()
50 static Collections::Pool<ResourceType> pool(128, 128, MemBlockType::RenderResourceStorage);
55 template<
typename TaskType>
56 TaskType * createTask(RenderTaskContext * renderContext,
bool initialize =
true)
58 auto pool = &getPool<TaskType>();
59 auto task = pool->create();
64 task->cleanup(renderContext);
70 if (renderContext && initialize) {
71 task->initialize(renderContext);
77 void freeTask(RenderTask * task, RenderTaskContext * renderContext)
79 for (
auto & d : destroyers) {
80 d.second(&task, renderContext);
89 LOG_ERROR(logger,
"Render task could not be deleted.");
92 void setProcessTaskEffectParameter(RenderTaskContext* renderContext,
93 std::list<std::unique_ptr<SubContext>>& subContexts,
94 ExpressionContext * expressionContext,
96 const ParsedValue& parameter)
98 task->effectParameter = parameter;
100 task->scope = expressionContext;
101 for (
const auto & ep : task->effectParameter.values) {
102 if (ep.key ==
"useVariables") {
103 if (task->scope == expressionContext) {
104 subContexts.push_back(std::make_unique<SubContext>(expressionContext));
105 task->scope = &subContexts.back()->expressionContext;
107 subContexts.back()->useVariables(renderContext->context, ep.values);
109 else if (ep.key ==
"setVariables") {
110 if (task->scope == expressionContext) {
111 subContexts.push_back(std::make_unique<SubContext>(expressionContext));
112 task->scope = &subContexts.back()->expressionContext;
114 subContexts.back()->setVariables(renderContext->context, ep.values);
116 else if (ep.key ==
"useComponentFields") {
117 if (task->scope == expressionContext) {
118 subContexts.push_back(std::make_unique<SubContext>(expressionContext));
119 task->scope = &subContexts.back()->expressionContext;
121 subContexts.back()->useComponentFields(renderContext, ep.values);
125 for (
const auto & ep : task->effectParameter.values) {
126 if (ep.key ==
"properties") {
127 for (
const auto & p : ep.values) {
128 if (p.key ==
"source")
continue;
130 ProcessTaskProperty prop;
131 prop.definition = &p;
132 prop.float4x4Value = p.float4x4Value;
134 for (
const auto & q : p.expressions) {
136 prop.expressions.push_back({ q.first, task->scope->compile(q.second,
"") });
139 case ParsedDataType::Texture2D: {
140 SamplerState samplerState {
149 prop.texture.samplerName = Strings::get(Strings::add(p.key +
"Sampler"));
150 prop.texture.samplerState = renderContext->states->getSamplerState(samplerState);
156 task->properties.push_back(prop);
159 else if (ep.key ==
"groups" && ep.values.size() == 3) {
160 task->groups.expressions.clear();
161 for (
size_t i = 0; i < 3; i++) {
162 auto * e = task->scope->compile(ep.values[i].value,
"");
164 task->groups.expressions.push_back({ i, e });
175 BucketMask bucketMask = BucketMask::All;
176 StateChangeFlags stateChangeMask = StateChangeFlags::ChangeAll;
177 size_t permutationIndex = 0;
179 SortFlags sortFlags = SortFlags::Default;
184 bool viewportFromTarget =
true;
185 bool temporalOffsets =
false;
186 bool clearColor =
true;
187 bool clearDepth =
true;
188 bool discardColor =
false;
189 bool discardDepth =
false;
190 bool allowSelfDependency =
false;
191 bool drawCallID =
false;
192 bool blendModeSet =
false;
197 const PipelineOptions& options)
206 parseStringValue(option.second, val);
207 val.asBool(parameters.clearColor);
210 parseStringValue(option.second, val);
211 val.asBool(parameters.clearDepth);
219 for (
auto & p : taskDefinition.parameters) {
221 switch (StringView(p.key).hash()) {
223 parameters.bucketMask = parseEnumFlags(p.value, BucketMask::All);
226 parameters.stateChangeMask = parseEnumFlags<StateChangeFlags>(p.value, StateChangeFlags::ChangeAll);
229 parameters.permutationIndex = renderContext->renderer->getEnginePermutations().getIndex(p.value);
232 parameters.blendMode = parseEnum(p.value, parameters.blendMode);
233 parameters.blendModeSet =
true;
236 parameters.depthMode = parseEnum(p.value, parameters.depthMode);
239 parameters.depthFunc = parseEnum(p.value, parameters.depthFunc);
242 p.asBool(parameters.clearColor);
243 parameters.clearDepth = parameters.clearColor;
246 p.asBool(parameters.clearDepth);
249 p.asBool(parameters.clearColor);
252 p.asBool(parameters.discardDepth);
255 p.asBool(parameters.discardColor);
258 p.asBool(parameters.viewportFromTarget);
261 p.asBool(parameters.temporalOffsets);
264 p.asBool(parameters.allowSelfDependency);
267 parameters.flags = parseEnumFlags(p.value, RenderTaskFlags::None);
270 p.asBool(parameters.drawCallID);
273 parameters.renderMask = parseEnumFlags(p.value, RenderLayers::None);
277 parameters.sortFlags = parseEnumFlags<SortFlags>(p.value, parameters.sortFlags);
291 const RenderTaskDefinition & taskDefinition,
292 std::list<std::unique_ptr<SubContext>>& subContexts,
293 ExpressionContext * expressionContext,
294 const PipelineOptions & options)
296 RenderTask * task =
nullptr;
298 auto parameters = parseParameters(renderContext, taskDefinition, options);
300 if (taskDefinition.type ==
"GenerateList") {
301 task = createTask<GenerateListTask>(renderContext);
302 task->initialize(renderContext);
303 }
else if (taskDefinition.type ==
"Filter") {
304 FilterListTask* filterTask = createTask<FilterListTask>(renderContext);
305 filterTask->bucketMask = parameters.bucketMask;
306 filterTask->permutation = parameters.permutationIndex;
307 filterTask->drawCallID = parameters.drawCallID;
308 filterTask->renderMask = parameters.renderMask;
309 filterTask->sortFlags = parameters.sortFlags;
310 filterTask->blendMode = parameters.blendMode;
311 filterTask->blendModeSet = parameters.blendModeSet;
313 const CameraData* cameraData = &renderContext->context->cameraSystem->getMainCameraData();
315 if (renderContext->cameraData != cameraData) {
316 filterTask->viewportData = renderContext->cameraData;
319 filterTask->viewportData =
nullptr;
323 }
else if (taskDefinition.type ==
"RenderList") {
324 auto renderTask = createTask<RenderListTask>(renderContext,
false);
325 renderTask->bucketMask = parameters.bucketMask;
326 renderTask->stateChangeMask = parameters.stateChangeMask;
327 renderTask->permutationIndex = parameters.permutationIndex;
328 renderTask->colorClear = parameters.clearColor;
329 renderTask->depthClear = parameters.clearDepth;
330 renderTask->discardColor = parameters.discardColor;
331 renderTask->discardDepth = parameters.discardDepth;
332 renderTask->viewportFromTarget = parameters.viewportFromTarget;
333 renderTask->temporalOffsets = parameters.temporalOffsets;
334 renderTask->blendMode = parameters.blendMode;
335 renderTask->depthMode = parameters.depthMode;
336 renderTask->depthFunc = parameters.depthFunc;
337 renderTask->initialize(renderContext);
339 }
else if (taskDefinition.type ==
"DeferredLighting") {
340 auto defTask = createTask<DeferredLightingTask>(renderContext);
341 defTask->clear = parameters.clearColor;
342 defTask->clearToDefault =
true;
344 }
else if (taskDefinition.type ==
"TransparencyRender") {
345 auto tTask = createTask<TransparencyRenderTask>(renderContext);
346 tTask->bucketMask = parameters.bucketMask;
347 tTask->viewportFromTarget = parameters.viewportFromTarget;
348 tTask->temporalOffsets = parameters.temporalOffsets;
350 }
else if (taskDefinition.type ==
"TransparencyMerge") {
351 task = createTask<TransparencyMergeTask>(renderContext);
352 }
else if (taskDefinition.type ==
"TransparencyTemporalUpscale") {
353 task = createTask<TransparencyTemporalUpscaleTask>(renderContext);
354 }
else if (taskDefinition.type ==
"TransparencyUpscale") {
355 task = createTask<TransparencyUpscaleTask>(renderContext);
356 }
else if (taskDefinition.type ==
"PostProcess") {
357 PostProcessTask* pTask = createTask<PostProcessTask>(renderContext,
false);
358 pTask->viewportFromTarget = parameters.viewportFromTarget;
359 for (
auto & p : taskDefinition.parameters) {
360 if (p.key ==
"effect") {
361 setProcessTaskEffectParameter(renderContext, subContexts, expressionContext, pTask, p);
362 }
else if (p.key ==
"blendMode") {
363 pTask->blendMode = parseEnum<BlendMode>(p.value, pTask->blendMode);
364 }
else if (p.key ==
"writeDepth") {
365 pTask->writeDepth = p.asBool(pTask->writeDepth);
369 pTask->initialize(renderContext);
372 }
else if (taskDefinition.type ==
"ClearResource") {
373 auto pTask = createTask<ClearResourceTask>(renderContext);
375 for (
auto & p : taskDefinition.parameters) {
376 if (p.key ==
"destinationIndex") {
377 readSize_t(pTask->destinationIndex, expressionContext, taskDefinition.name, p);
379 else if (p.key ==
"fill") {
380 if (p.type == ParsedDataType::UInt) {
381 pTask->fill_float =
false;
382 for(uint32_t i=0; i<4; i++)
383 pTask->fill.UValues[i] = p.uintValue;
385 else if (p.type == ParsedDataType::Float) {
386 pTask->fill_float =
true;
387 for(uint32_t i=0; i<4; i++)
388 pTask->fill.FValues[i] = p.floatValue;
394 }
else if (taskDefinition.type ==
"CopyResource") {
395 auto pTask = createTask<CopyResourceTask>(renderContext);
397 for (
auto & p : taskDefinition.parameters) {
398 if (p.key ==
"sourceIndex") {
399 readSize_t(pTask->sourceIndex, expressionContext, taskDefinition.name, p);
400 }
else if (p.key ==
"destinationIndex") {
401 readSize_t(pTask->destinationIndex, expressionContext, taskDefinition.name, p);
406 }
else if (taskDefinition.type ==
"ResolveResource") {
407 task = createTask<ResolveResourceTask>(renderContext);
408 }
else if (taskDefinition.type ==
"Readback") {
409 auto pTask = createTask<ReadbackTask>(renderContext);
411 for (
auto & p : taskDefinition.parameters) {
412 if (p.key ==
"bufferIndex") {
413 readSize_t(pTask->bufferIndex, expressionContext, taskDefinition.name, p);
414 }
else if (p.key ==
"size") {
415 readSize_t(pTask->size, expressionContext, taskDefinition.name, p);
416 }
else if (p.key ==
"readbackKey") {
417 pTask->key = p.value;
422 }
else if (taskDefinition.type ==
"Compute") {
423 auto pTask = createTask<ComputeTask>(renderContext,
false);
425 for (
auto & p : taskDefinition.parameters) {
426 if (p.key ==
"effect") {
427 setProcessTaskEffectParameter(renderContext, subContexts, expressionContext, pTask, p);
431 pTask->initialize(renderContext);
434 }
else if (taskDefinition.type ==
"MipLevels") {
435 auto pTask = createTask<MipLevelsTask>(renderContext,
false);
437 for (
auto & p : taskDefinition.parameters) {
438 if (p.key ==
"effect") {
439 setProcessTaskEffectParameter(renderContext, subContexts, expressionContext, pTask, p);
440 }
else if (p.key ==
"firstLevel") {
441 readSize_t(pTask->firstLevel, expressionContext, std::to_string((
size_t)(pTask)) +
".firstLevel", p);
442 }
else if (p.key ==
"lastLevel") {
443 readSize_t(pTask->lastLevel, expressionContext, std::to_string((
size_t)(pTask)) +
".lastLevel", p);
444 }
else if (p.key ==
"blendMode") {
445 pTask->blendMode = parseEnum<BlendMode>(p.value, pTask->blendMode);
448 pTask->initialize(renderContext);
451 auto fIt = creators.find(taskDefinition.type);
453 if (fIt != creators.end()) {
454 task = fIt->second(renderContext, taskDefinition, options);
455 task->initialize(renderContext);
460 LOG_ERROR(logger,
"Could not create task of type %s.", taskDefinition.type.c_str());
464 task->name = taskDefinition.name;
465 task->options = options;
466 task->flags = (RenderTaskFlags::ERenderTaskFlags)parameters.flags;
467 task->allowSelfDependency = parameters.allowSelfDependency;
472void Cogs::Core::destroyRenderTask(RenderTaskContext* renderContext, RenderTask* task)
474 freeTask(task, renderContext);
477void Cogs::Core::addTaskType(
const StringView & key, TaskCreator creator, TaskDestroyer destroyer)
479 creators[key.to_string()] = creator;
480 destroyers[key.to_string()] = destroyer;
483void Cogs::Core::freeTasks(std::vector<RenderTask *> & tasks, RenderTaskContext * renderContext)
485 for (
auto & task : tasks) {
486 if (!(task->flags & RenderTaskFlags::Persistent)) {
487 freeTask(task, renderContext);
Log implementation class.
Provides a weakly referenced view over the contents of a string.
constexpr size_t hash() const noexcept
Get the hash code of the string.
BlendMode
Defines blending modes for rendering.
@ None
No blending enabled for opaque shapes, defaults to Blend for transparent shapes.
DepthMode
Defines common depth stencil modes.
@ Default
Default, depth test & write enabled.
DepthFunc
Defines common depth functions.
RenderLayers
Contains common render layers.
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.
std::pair< std::string, std::string > PreprocessorDefinition
Preprocessor definition.
Stores the parsed output of a key/value pair.
@ Clamp
Texture coordinates are clamped to the [0, 1] range.
@ MinMagMipPoint
Point sampling for both minification and magnification.
@ MinMagMipLinear
Linear sampling for both minification and magnification.