Cogs.Core
ProcessTask.cpp
1#include "ProcessTask.h"
2
3#include "Rendering/IContext.h"
4#include "Rendering/IBuffers.h"
5
6#include "Foundation/Logging/Logger.h"
7
8#include "Context.h"
9
10#include "Renderer/Renderer.h"
11#include "Renderer/RenderBuffer.h"
12#include "Renderer/RenderTexture.h"
13#include "Renderer/RenderTarget.h"
14#include "Renderer/RenderList.h"
15#include "Resources/BasicBlueNoiseManager.h"
16#include "Services/Variables.h"
17#include "Systems/Core/EnvironmentSystem.h"
18#include "Systems/Appearance/BasicOceanSystem.h"
19#include "Utilities/ValueVariant.h"
20
21namespace
22{
23 Cogs::Logging::Log logger = Cogs::Logging::getLogger("ProcessTask");
24}
25
26Cogs::Core::EffectDescription Cogs::Core::ProcessTask::createEffectDesc(RenderTaskContext* context)
27{
28 const RenderSettings& renderSettings = context->renderer->getSettings();
29
30 EffectDescription desc{};
31
32 if (context->context->variables->get("renderer.reverseDepth", false)) {
33 desc.definitions.push_back({ "COGS_REVERSE_DEPTH", "1" });
34 }
35
36 // See Default.permutations for defines.
37 switch (renderSettings.sRGBConversion) {
38 case RenderSettings::SRGBConversion::Fast:
39 desc.definitions.push_back({ "COGS_SRGB_CONVERSION_FAST", "1" });
40 break;
41 case RenderSettings::SRGBConversion::Approx:
42 desc.definitions.push_back({ "COGS_SRGB_CONVERSION_APPROX", "1" });
43 break;
44 case RenderSettings::SRGBConversion::Exact:
45 desc.definitions.push_back({ "COGS_SRGB_CONVERSION_EXACT", "1" });
46 break;
47 default:
48 assert(false && "Invalid enum");
49 break;
50 }
51
52 // See Default.permutations for defines.
53 switch (renderSettings.tonemapper) {
54 case RenderSettings::Tonemapper::Reinhard:
55 desc.definitions.push_back({ "COGS_TONEMAP_REINHARD", "1" });
56 break;
57 case RenderSettings::Tonemapper::Filmic:
58 desc.definitions.push_back({ "COGS_TONEMAP_FILMIC", "1" });
59 break;
60 case RenderSettings::Tonemapper::ACESLuminance:
61 desc.definitions.push_back({ "COGS_TONEMAP_ACES_LUMINANCE", "1" });
62 break;
63 case RenderSettings::Tonemapper::PBRNeutral:
64 desc.definitions.push_back({ "COGS_TONEMAP_PBR_NEUTRAL", "1" });
65 break;
66 default:
67 assert(false && "Invalid enum");
68 break;
69 }
70
71 return desc;
72}
73
74
75void Cogs::Core::ProcessTask::addProperty(ProcessTaskProperty& property) {
76 size_t alignment = 0;
77 switch (property.definition->type) {
78 case ParsedDataType::Float:
79 property.size = sizeof(float);
80 alignment = sizeof(float);
81 break;
82 case ParsedDataType::Float2:
83 property.size = 2 * sizeof(float);
84 alignment = 2 * sizeof(float);
85 break;
86 case ParsedDataType::Float3:
87 property.size = 3 * sizeof(float);
88 alignment = 4 * sizeof(float);
89 break;
90 case ParsedDataType::Float4:
91 property.size = 4 * sizeof(float);
92 alignment = 4 * sizeof(float);
93 break;
94 case ParsedDataType::Float4x4:
95 property.size = 16 * sizeof(float);
96 alignment = 4 * sizeof(float);
97 break;
98 case ParsedDataType::Int:
99 property.size = 1 * sizeof(int);
100 alignment = 1 * sizeof(int);
101 break;
102 case ParsedDataType::Int2:
103 property.size = 2 * sizeof(int);
104 alignment = 2 * sizeof(int);
105 break;
106 case ParsedDataType::Int3:
107 property.size = 3 * sizeof(int);
108 alignment = 4 * sizeof(int);
109 break;
110 case ParsedDataType::Int4:
111 property.size = 4 * sizeof(int);
112 alignment = 4 * sizeof(int);
113 break;
114 case ParsedDataType::UInt:
115 property.size = 1 * sizeof(int);
116 alignment = 1 * sizeof(int);
117 break;
118 case ParsedDataType::UInt2:
119 property.size = 2 * sizeof(int);
120 alignment = 2 * sizeof(int);
121 break;
122 case ParsedDataType::UInt3:
123 property.size = 3 * sizeof(int);
124 alignment = 4 * sizeof(int);
125 break;
126 case ParsedDataType::UInt4:
127 property.size = 4 * sizeof(int);
128 alignment = 4 * sizeof(int);
129
130 break;
131 case ParsedDataType::Bool:
132 property.size = 1 * sizeof(int);
133 alignment = 1 * sizeof(int);
134 // TODO
135 break;
136 case ParsedDataType::Double:
137 property.size = 0;
138 LOG_DEBUG(logger, "Double not supported in effect parameter yet");
139 break;
140
141 default:
142 property.size = 0; // skip textures and such
143 }
144 if (property.size > 0) {
145 property.offset = alignment * ((constantBufferData.size() + alignment - 1) / alignment);
146 constantBufferData.resize(property.offset + property.size);
147 std::memcpy(static_cast<void*> (constantBufferData.data() + property.offset), static_cast<const void*>(&(property.floatValue)), property.size);
148 }
149}
150
151void Cogs::Core::ProcessTask::initialize(RenderTaskContext* context)
152{
153 RenderTask::initialize(context);
154}
155
156void Cogs::Core::ProcessTask::initialize(RenderTaskContext* context, const RenderTaskDefinition& /*taskDefinition*/)
157{
158 RenderTask::initialize(context);
159 this->paramBufferDesc.name = "EffectParameters";
160 constantBufferData.reserve(1000);
161 constantBufferData.clear();
162 for (auto &property : properties) {
163 addProperty(property);
164 }
165 if (!constantBufferData.empty()) {
166 constantBuffer = context->device->getBuffers()->loadBuffer(nullptr, constantBufferData.size(), Usage::Dynamic, AccessMode::Write, BindFlags::ConstantBuffer);
167 context->device->getImmediateContext()->updateBuffer(constantBuffer, constantBufferData.data(), constantBufferData.size());
168 }
169}
170
171
172void Cogs::Core::ProcessTask::cleanup(RenderTaskContext * context)
173{
174 if (effect) context->renderer->getEffectCache().release(context, effect);
175 for (auto & prop : properties) {
176 //for (auto & p : prop.expressions) {
177 // //delete p.second;
178 //}
179 prop.expressions.clear();
180 }
181}
182
183void Cogs::Core::ProcessTask::setProperties(RenderTaskContext * renderTaskContext, Cogs::Core::RenderTexture* targetSource)
184{
185 texUnit = 0;
186 auto * context = renderTaskContext->context;
187 auto * deviceContext = renderTaskContext->device->getImmediateContext();
188
189 deviceContext->setBlendState(renderTaskContext->states->blendStates[size_t(blendMode)].handle);
190
191 //auto * scope = renderTaskContext->expressionContext;
192 assert(scope);
193
194 if (paramBufferHandle == ConstantBufferBindingHandle::NoHandle && !constantBufferData.empty()) {
195 auto effects = renderTaskContext->device->getEffects();
196 paramBufferHandle = effects->getConstantBufferBinding(effect->handle, "EffectParameters");
197 }
198
199 // HandleIsValid(binding)
200 deviceContext->setConstantBuffer(paramBufferHandle, constantBuffer);
201 //if (this->scope != nullptr) {
202 // scope = this->scope;
203 // for (auto & v : renderTaskContext->expressionContext->values) {
204 // scope->add(v.name, v.value);
205 // }
206
207 // for (auto & p : useVariables) {
208 // scope->add(p.first, context->variables->get(p.second)->get<double>());
209 // }
210 //}
211 bool dirty = false;
212 for (auto & p : properties) {
213
214 switch (p.definition->type) {
215 case ParsedDataType::Float:
216 case ParsedDataType::Float2:
217 case ParsedDataType::Float3:
218 case ParsedDataType::Float4:
219 case ParsedDataType::Float4x4:
220 for (auto & q : p.expressions) {
221 auto r = scope->update(q.second, (&p.definition->floatValue)[q.first]);
222 if (r != (&p.floatValue)[q.first]) {
223 (&p.floatValue)[q.first] = r;
224 reinterpret_cast<float*>(constantBufferData.data() + p.offset)[q.first] = r;
225 dirty = true;
226 }
227 }
228
229 break;
230 case ParsedDataType::Int:
231 case ParsedDataType::Int2:
232 case ParsedDataType::Int3:
233 case ParsedDataType::Int4:
234 case ParsedDataType::UInt:
235 case ParsedDataType::UInt2:
236 case ParsedDataType::UInt3:
237 case ParsedDataType::UInt4:
238 for (auto& q : p.expressions) {
239 auto r = scope->update(q.second, (&p.definition->intValue)[q.first]);
240 if (r != (&p.floatValue)[q.first]) {
241 (&p.intValue)[q.first] = r;
242 reinterpret_cast<int*>(constantBufferData.data() + p.offset)[q.first] = r;
243 dirty = true;
244 }
245 }
246 break;
247 default:
248 break;
249 }
250 }
251 if (dirty) {
252 deviceContext->updateBuffer(constantBuffer, constantBufferData.data(), constantBufferData.size());
253 }
254 auto basicOceanSystem = context->basicOceanSystem;
255 if (basicOceanSystem && !basicOceanSystem->pool.size()) {
256 basicOceanSystem = nullptr;
257 }
258
259 auto renderList = input.get(RenderResourceType::RenderList);
260 const EnvironmentComponent * envComp = nullptr;
261 if (renderList) {
262 envComp = renderList->renderList->viewportData->environment.resolveComponent<EnvironmentComponent>();
263 }
264
265 auto binding = renderTaskContext->device->getEffects()->getTextureBinding(effect->handle, "blueNoise_LDR_RGBA", 0);
266 if(HandleIsValid(binding)){
267 auto& blueNoiseManager = renderTaskContext->context->blueNoiseManager;
268 blueNoiseManager->enable();
269 TextureHandle blueNoise = blueNoiseManager->getBlueNoiseHandle(false)->texture;
270 RenderTexture * blueNoiseTexture = renderTaskContext->renderer->getRenderResources().getRenderTexture(blueNoise);
271 if (blueNoiseTexture) {
272 deviceContext->setTexture(binding, blueNoiseTexture->textureHandle);
273 }
274 }
275
276 // Set engine buffers if they are in use
277 deviceContext->setConstantBuffer("SceneBuffer", renderTaskContext->engineBuffers->sceneBufferHandle);
278 deviceContext->setConstantBuffer("LightBuffer", renderTaskContext->engineBuffers->lightBufferHandle);
279
280 {
281 {
282 for (auto & p : properties) {
283 bool setSampler = true;
284 switch (p.definition->type)
285 {
286 case ParsedDataType::Texture2D:
287 {
288 switch (p.definition->valueHash)
289 {
290 case Cogs::hash("Cogs.EnvironmentRadiance.NoSampler"):
291 setSampler = false;
292 case Cogs::hash("Cogs.EnvironmentRadiance"):
293 case Cogs::hash("Cogs.EnvironmentRadiance.SetSampler"):
294 if (envComp && HandleIsValid(envComp->radiance)) {
295 RenderTexture * tex = renderTaskContext->renderer->getRenderResources().getRenderTexture(envComp->radiance);
296 if (tex) {
297 deviceContext->setTexture(p.definition->key, texUnit, tex->textureHandle);
298 if (setSampler) {
299 deviceContext->setSamplerState(p.definition->key + "Sampler", texUnit, renderTaskContext->states->getSamplerState(SamplerState::DefaultState()));
300 }
301 }
302 }
303 break;
304
305 case Cogs::hash("Cogs.SubseaRadiance.NoSampler"):
306 setSampler = false;
307 case Cogs::hash("Cogs.SubseaRadiance"):
308 case Cogs::hash("Cogs.SubseaRadiance.SetSampler"):
309 if (envComp && HandleIsValid(envComp->subseaRadiance)) {
310 RenderTexture * tex = renderTaskContext->renderer->getRenderResources().getRenderTexture(envComp->subseaRadiance);
311 if (tex) {
312 deviceContext->setTexture(p.definition->key, texUnit, tex->textureHandle);
313 if (setSampler) {
314 deviceContext->setSamplerState(p.definition->key + "Sampler", texUnit, renderTaskContext->states->getSamplerState(SamplerState::DefaultState()));
315 }
316 }
317 }
318 break;
319
320 case Cogs::hash("Cogs.BasicOceanSystem.Real"):
321 if (basicOceanSystem) {
322 RenderTexture * tex = renderTaskContext->renderer->getRenderResources().getRenderTexture(basicOceanSystem->getRealTex());
323 if (tex) {
324 deviceContext->setTexture(p.definition->key, texUnit, tex->textureHandle);
325 deviceContext->setSamplerState(p.definition->key + "Sampler", texUnit, renderTaskContext->states->getSamplerState(SamplerState::DefaultState()));
326 texUnit++;
327 }
328 }
329 break;
330 case Cogs::hash("Cogs.BasicOceanSystem.Imag"):
331 if (basicOceanSystem) {
332 RenderTexture * tex = renderTaskContext->renderer->getRenderResources().getRenderTexture(basicOceanSystem->getImagTex());
333 if (tex) {
334 deviceContext->setTexture(p.definition->key, texUnit, tex->textureHandle);
335 deviceContext->setSamplerState(p.definition->key + "Sampler", texUnit, renderTaskContext->states->getSamplerState(SamplerState::DefaultState()));
336 texUnit++;
337 }
338 }
339 break;
340 case Cogs::hash("Cogs.BasicOceanSystem.Tangent"):
341 if (basicOceanSystem) {
342 RenderTexture * tex = renderTaskContext->renderer->getRenderResources().getRenderTexture(basicOceanSystem->getTangentTex());
343 if (tex) {
344 deviceContext->setTexture(p.definition->key, texUnit, tex->textureHandle);
345 deviceContext->setSamplerState(p.definition->key + "Sampler", texUnit, renderTaskContext->states->getSamplerState(SamplerState::DefaultState()));
346 texUnit++;
347 }
348 }
349 break;
350 default:
351 auto inputSource = input.get(p.definition->value);
352
353 RenderTexture* tex = nullptr;
354 if (inputSource->type == RenderResourceType::RenderTexture) {
355 tex = inputSource->renderTexure;
356 } else if (inputSource->type == RenderResourceType::RenderTarget) {
357 tex = inputSource->renderTarget->textures[0];
358 }
359
360 if (tex == nullptr) {
361 // report error
362 }
363 else if (tex == targetSource) {
364 // ignore
365 }
366 else {
367 deviceContext->setTexture(p.definition->key, texUnit, tex->textureHandle);
368 deviceContext->setSamplerState(p.texture.samplerName, texUnit, p.texture.samplerState);
369 texUnit++;
370 }
371 }
372 }
373 break;
374 case ParsedDataType::Buffer:
375 {
376 auto inputSource = input.get(p.definition->value);
377
378 if (!inputSource) {
379 auto outputSource = output.get(p.definition->value);
380
381 deviceContext->setBuffer(p.definition->key, outputSource->renderBuffer->buffer);
382 } else {
383 deviceContext->setBuffer(p.definition->key, inputSource->renderBuffer->buffer);
384 }
385 }
386 break;
387 case ParsedDataType::ConstantBuffer:
388 break;
389 default:
390 break;
391 }
392 }
393 }
394 }
395}
Log implementation class.
Definition: LogManager.h:140
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
Contains all Cogs related functionality.
Definition: FieldSetter.h:23
constexpr size_t hash() noexcept
Simple getter function that returns the initial value for fnv1a hashing.
Definition: HashFunctions.h:62
@ 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 const Handle_t NoHandle
Represents a handle to nothing.
Definition: Common.h:78
@ Dynamic
Buffer will be loaded and modified with some frequency.
Definition: Flags.h:30