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 });
168 else if (ep.key ==
"options") {
169 task->options.clear();
170 for (
const auto& p : ep.values) {
171 if (p.type == ParsedDataType::String) {
172 task->options.emplace_back(p.key, p.value);
174 LOG_ERROR(logger,
"Process task options should be of type string, key=\"%s\".", p.key.c_str());
184 BucketMask bucketMask = BucketMask::All;
185 StateChangeFlags stateChangeMask = StateChangeFlags::ChangeAll;
186 size_t permutationIndex = 0;
188 SortFlags sortFlags = SortFlags::Default;
193 bool viewportFromTarget =
true;
194 bool temporalOffsets =
false;
195 bool clearColor =
true;
196 bool clearDepth =
true;
197 bool discardColor =
false;
198 bool discardDepth =
false;
199 bool allowSelfDependency =
false;
200 bool drawCallID =
false;
201 bool blendModeSet =
false;
206 const PipelineOptions& options)
215 parseStringValue(option.second, val);
216 val.asBool(parameters.clearColor);
219 parseStringValue(option.second, val);
220 val.asBool(parameters.clearDepth);
228 for (
auto & p : taskDefinition.parameters) {
230 switch (StringView(p.key).hash()) {
232 parameters.bucketMask = parseEnumFlags(p.value, BucketMask::All);
235 parameters.stateChangeMask = parseEnumFlags<StateChangeFlags>(p.value, StateChangeFlags::ChangeAll);
238 parameters.permutationIndex = renderContext->renderer->getEnginePermutations().getIndex(p.value);
241 parameters.blendMode = parseEnum(p.value, parameters.blendMode);
242 parameters.blendModeSet =
true;
245 parameters.depthMode = parseEnum(p.value, parameters.depthMode);
248 parameters.depthFunc = parseEnum(p.value, parameters.depthFunc);
251 p.asBool(parameters.clearColor);
252 parameters.clearDepth = parameters.clearColor;
255 p.asBool(parameters.clearDepth);
258 p.asBool(parameters.clearColor);
261 p.asBool(parameters.discardDepth);
264 p.asBool(parameters.discardColor);
267 p.asBool(parameters.viewportFromTarget);
270 p.asBool(parameters.temporalOffsets);
273 p.asBool(parameters.allowSelfDependency);
276 parameters.flags = parseEnumFlags(p.value, RenderTaskFlags::None);
279 p.asBool(parameters.drawCallID);
282 parameters.renderMask = parseEnumFlags(p.value, RenderLayers::None);
286 parameters.sortFlags = parseEnumFlags<SortFlags>(p.value, parameters.sortFlags);
300 const RenderTaskDefinition & taskDefinition,
301 std::list<std::unique_ptr<SubContext>>& subContexts,
302 ExpressionContext * expressionContext,
303 const PipelineOptions & options)
305 RenderTask * task =
nullptr;
307 auto parameters = parseParameters(renderContext, taskDefinition, options);
309 if (taskDefinition.type ==
"GenerateList") {
310 task = createTask<GenerateListTask>(renderContext);
311 task->initialize(renderContext);
312 }
else if (taskDefinition.type ==
"Filter") {
313 FilterListTask* filterTask = createTask<FilterListTask>(renderContext);
314 filterTask->bucketMask = parameters.bucketMask;
315 filterTask->permutation = parameters.permutationIndex;
316 filterTask->drawCallID = parameters.drawCallID;
317 filterTask->renderMask = parameters.renderMask;
318 filterTask->sortFlags = parameters.sortFlags;
319 filterTask->blendMode = parameters.blendMode;
320 filterTask->blendModeSet = parameters.blendModeSet;
322 const CameraData* cameraData = &renderContext->context->cameraSystem->getMainCameraData();
324 if (renderContext->cameraData != cameraData) {
325 filterTask->viewportData = renderContext->cameraData;
328 filterTask->viewportData =
nullptr;
332 }
else if (taskDefinition.type ==
"RenderList") {
333 auto renderTask = createTask<RenderListTask>(renderContext,
false);
334 renderTask->bucketMask = parameters.bucketMask;
335 renderTask->stateChangeMask = parameters.stateChangeMask;
336 renderTask->permutationIndex = parameters.permutationIndex;
337 renderTask->colorClear = parameters.clearColor;
338 renderTask->depthClear = parameters.clearDepth;
339 renderTask->discardColor = parameters.discardColor;
340 renderTask->discardDepth = parameters.discardDepth;
341 renderTask->viewportFromTarget = parameters.viewportFromTarget;
342 renderTask->temporalOffsets = parameters.temporalOffsets;
343 renderTask->blendMode = parameters.blendMode;
344 renderTask->depthMode = parameters.depthMode;
345 renderTask->depthFunc = parameters.depthFunc;
346 renderTask->initialize(renderContext);
348 }
else if (taskDefinition.type ==
"DeferredLighting") {
349 auto defTask = createTask<DeferredLightingTask>(renderContext);
350 defTask->clear = parameters.clearColor;
351 defTask->clearToDefault =
true;
353 }
else if (taskDefinition.type ==
"TransparencyRender") {
354 auto tTask = createTask<TransparencyRenderTask>(renderContext);
355 tTask->bucketMask = parameters.bucketMask;
356 tTask->viewportFromTarget = parameters.viewportFromTarget;
357 tTask->temporalOffsets = parameters.temporalOffsets;
359 }
else if (taskDefinition.type ==
"TransparencyMerge") {
360 task = createTask<TransparencyMergeTask>(renderContext);
361 }
else if (taskDefinition.type ==
"TransparencyTemporalUpscale") {
362 task = createTask<TransparencyTemporalUpscaleTask>(renderContext);
363 }
else if (taskDefinition.type ==
"TransparencyUpscale") {
364 task = createTask<TransparencyUpscaleTask>(renderContext);
365 }
else if (taskDefinition.type ==
"PostProcess") {
366 PostProcessTask* pTask = createTask<PostProcessTask>(renderContext,
false);
367 pTask->viewportFromTarget = parameters.viewportFromTarget;
368 pTask->clearColor = parameters.clearColor;
369 pTask->clearDepth = parameters.clearDepth;
370 for (
auto & p : taskDefinition.parameters) {
371 if (p.key ==
"effect") {
372 setProcessTaskEffectParameter(renderContext, subContexts, expressionContext, pTask, p);
373 }
else if (p.key ==
"blendMode") {
374 pTask->blendMode = parseEnum<BlendMode>(p.value, pTask->blendMode);
375 }
else if (p.key ==
"writeColor") {
376 p.asBool(pTask->writeColor);
377 }
else if (p.key ==
"writeDepth") {
378 p.asBool(pTask->writeDepth);
382 pTask->initialize(renderContext, taskDefinition);
385 }
else if (taskDefinition.type ==
"ClearResource") {
386 auto pTask = createTask<ClearResourceTask>(renderContext);
388 for (
auto & p : taskDefinition.parameters) {
389 if (p.key ==
"destinationIndex") {
390 readSize_t(pTask->destinationIndex, expressionContext, taskDefinition.name, p);
392 else if (p.key ==
"fill") {
393 if (p.type == ParsedDataType::UInt) {
394 pTask->fill_float =
false;
395 for(uint32_t i=0; i<4; i++)
396 pTask->fill.UValues[i] = p.uintValue;
398 else if (p.type == ParsedDataType::Float) {
399 pTask->fill_float =
true;
400 for(uint32_t i=0; i<4; i++)
401 pTask->fill.FValues[i] = p.floatValue;
407 }
else if (taskDefinition.type ==
"CopyResource") {
408 auto pTask = createTask<CopyResourceTask>(renderContext);
410 for (
auto & p : taskDefinition.parameters) {
411 if (p.key ==
"sourceIndex") {
412 readSize_t(pTask->sourceIndex, expressionContext, taskDefinition.name, p);
413 }
else if (p.key ==
"destinationIndex") {
414 readSize_t(pTask->destinationIndex, expressionContext, taskDefinition.name, p);
419 }
else if (taskDefinition.type ==
"ResolveResource") {
420 task = createTask<ResolveResourceTask>(renderContext);
421 }
else if (taskDefinition.type ==
"Readback") {
422 auto pTask = createTask<ReadbackTask>(renderContext);
424 for (
auto & p : taskDefinition.parameters) {
425 if (p.key ==
"bufferIndex") {
426 readSize_t(pTask->bufferIndex, expressionContext, taskDefinition.name, p);
427 }
else if (p.key ==
"size") {
428 readSize_t(pTask->size, expressionContext, taskDefinition.name, p);
429 }
else if (p.key ==
"readbackKey") {
430 pTask->key = p.value;
435 }
else if (taskDefinition.type ==
"Compute") {
436 auto pTask = createTask<ComputeTask>(renderContext,
false);
438 for (
auto & p : taskDefinition.parameters) {
439 if (p.key ==
"effect") {
440 setProcessTaskEffectParameter(renderContext, subContexts, expressionContext, pTask, p);
444 pTask->initialize(renderContext, taskDefinition);
447 }
else if (taskDefinition.type ==
"MipLevels") {
448 auto pTask = createTask<MipLevelsTask>(renderContext,
false);
450 for (
auto & p : taskDefinition.parameters) {
451 if (p.key ==
"effect") {
452 setProcessTaskEffectParameter(renderContext, subContexts, expressionContext, pTask, p);
453 }
else if (p.key ==
"firstLevel") {
454 readSize_t(pTask->firstLevel, expressionContext, std::to_string((
size_t)(pTask)) +
".firstLevel", p);
455 }
else if (p.key ==
"lastLevel") {
456 readSize_t(pTask->lastLevel, expressionContext, std::to_string((
size_t)(pTask)) +
".lastLevel", p);
457 }
else if (p.key ==
"blendMode") {
458 pTask->blendMode = parseEnum<BlendMode>(p.value, pTask->blendMode);
461 pTask->initialize(renderContext, taskDefinition);
464 auto fIt = creators.find(taskDefinition.type);
466 if (fIt != creators.end()) {
467 task = fIt->second(renderContext, taskDefinition, options);
468 task->initialize(renderContext);
473 LOG_ERROR(logger,
"Could not create task of type %s.", taskDefinition.type.c_str());
477 task->name = taskDefinition.name;
478 task->options = options;
479 task->flags = (RenderTaskFlags::ERenderTaskFlags)parameters.flags;
480 task->allowSelfDependency = parameters.allowSelfDependency;
485void Cogs::Core::destroyRenderTask(RenderTaskContext* renderContext, RenderTask* task)
487 freeTask(task, renderContext);
490void Cogs::Core::addTaskType(
const StringView & key, TaskCreator creator, TaskDestroyer destroyer)
492 creators[key.to_string()] = creator;
493 destroyers[key.to_string()] = destroyer;
496void Cogs::Core::freeTasks(std::vector<RenderTask *> & tasks, RenderTaskContext * renderContext)
498 for (
auto & task : tasks) {
499 if (!(task->flags & RenderTaskFlags::Persistent)) {
500 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.