Cogs.Core
RendererExtension.cpp
1#include "ExtensionRegistry.h"
2#include "Renderer/Renderer.h"
3#include "Renderer/RenderList.h"
4#include "Renderer/RenderStateUpdater.h"
5#include "Renderer/RenderTarget.h"
6#include "Renderer/Tasks/RenderListTask.h"
7#include "Renderer/Tasks/FilterListTask.h"
8#include "Renderer/Tasks/GenerateListTask.h"
9
10#include "Image360System.h"
11
12#include "Rendering/IGraphicsDevice.h"
13#include "Rendering/ITextures.h"
14#include "Rendering/ICapabilities.h"
15#include "Rendering/IRenderTargets.h"
16#include "Foundation/Logging/Logger.h"
17
18#include <glm/glm.hpp>
19
20#include <array>
21
22
23namespace {
24 using namespace Cogs::Core;
25 using namespace Cogs::Core::Image360;
26
28
29 struct Constants
30 {
31 glm::mat4 worldFromLocal;
32 glm::mat4 localFromWorld;
33 float clipSpaceNearPlane;
34 float valueScale;
35 float valueBias;
36 float depthScale;
37 float depthBias;
38 float baseSize;
39 uint32_t noDataDepth;
40 };
41
42 void image360RenderCallback(RenderTaskContext* taskContext, DrawContext* drawContext, const RenderItem* renderItem)
43 {
44 const auto* camData = drawContext->cameraData;
45 if (camData == nullptr) return;
46
47 Renderer* renderer = taskContext->renderer;
48
49 Cogs::IGraphicsDevice* device = renderer->getDevice();
50 Cogs::IContext* iContext = device->getImmediateContext();
51 RendererExtension* im360Renderer = renderItem->getCallbackData<RendererExtension>();
52 RendererExtensionData* rendererData = renderItem->getCallbackData2<RendererExtensionData>();
53 if (!HandleIsValid(rendererData->encodedTreesTex)) {
54 return;
55 }
56 if (!HandleIsValid(rendererData->value.tilesTex)) {
57 return;
58 }
59
60 if (drawContext->task->viewportFromTarget && drawContext->renderTarget) {
61 iContext->setViewport(0.f, 0.f, float(drawContext->renderTarget->width), float(drawContext->renderTarget->height));
62 }
63 else {
64 iContext->setViewport(camData->viewportOrigin.x, camData->viewportOrigin.y, camData->viewportSize.x, camData->viewportSize.y);
65 }
66
67 iContext->setDepthStencilState(taskContext->states->commonDepthStates[renderItem->depthState]);
68 iContext->setBlendState(taskContext->states->blendStates[renderItem->blendState].handle);
69
70 const RenderPassOptions passOptions = initRenderPassOptions(*camData , renderItem->materialInstance);
71 iContext->setRasterizerState(taskContext->states->rasterizerStateHandles[getRasterizerState(renderer, *renderItem, passOptions, camData->flipWindingOrder, true)]);
72
73 // Invokes updateSceneBindings
74 // Invokes updateMaterialBindings(instance=false)
75 applyMaterialPermutation(taskContext, drawContext, renderItem->binding, renderItem->renderMaterialInstance);
76
77 // INvokes updateEnvironmentBindings,
78 // Updates permutation->constant buffers
79 drawContext->task->applyMaterial(*drawContext, *renderItem);
80
81 // Invokes updateMaterialBindings -> applyMaterialProperties
82 applyMaterialInstance(drawContext, renderItem->binding, renderItem->renderMaterialInstance);
83
84 updateSceneBindings(drawContext, drawContext->cameraData, renderItem->binding);
85
86 updateMaterialBindings(drawContext, renderItem->renderMaterialInstance, renderItem->binding, true);
87
88 Cogs::IEffects* effects = device->getEffects();
89
90 const glm::mat3 viewFromLocal = glm::mat3(drawContext->cameraData->viewMatrix) * rendererData->worldFromLocal;
91 const glm::mat3 localFromView = rendererData->localFromWorld * glm::mat3(drawContext->cameraData->inverseViewMatrix);
92 const float clipSpaceNearPlane = drawContext->context->variables->get("renderer.reverseDepth", false) ? 1.f : -1.f;
93 const EffectBinding* bindings = renderItem->binding;
94 const EngineBuffers& engineBuffers = *drawContext->engineBuffers;
95
96 if (Cogs::ConstantBufferBindingHandle constantsBinding = effects->getConstantBufferBinding(renderItem->binding->renderEffect->effectHandle, "Constants"); HandleIsValid(constantsBinding)) {
97 Constants constants{
98 .worldFromLocal = rendererData->worldFromLocal,
99 .localFromWorld = rendererData->localFromWorld,
100 .clipSpaceNearPlane = clipSpaceNearPlane,
101 .valueScale = rendererData->value.scale,
102 .valueBias = rendererData->value.bias,
103 .depthScale = rendererData->depth.scale,
104 .depthBias = rendererData->depth.bias,
105 .baseSize = float(rendererData->baseSize),
106 .noDataDepth = rendererData->noDataDepth
107 };
108 iContext->updateBuffer(rendererData->constants, &constants, sizeof(constants));
109 iContext->setConstantBuffer(constantsBinding, rendererData->constants);
110 }
111
112 if (HandleIsValid(bindings->objectBufferBinding)) {
113 ObjectBuffer objectBuffer = {};
114 objectBuffer.objectId = renderItem->objectId;
115 iContext->updateBuffer(rendererData->constants, &objectBuffer, sizeof(objectBuffer));
116 iContext->setConstantBuffer(bindings->objectBufferBinding, engineBuffers.objectBufferHandle);
117 }
118
119 iContext->setTexture("encodedTrees", 0, rendererData->encodedTreesTex);
120 iContext->setSamplerState("encodedTreesSampler", 0, renderer->getRenderStates().commonSamplerStates[3]);
121
122 if (rendererData->isValueUint) {
123 iContext->setTexture("tilesValue_uint", 1, rendererData->value.tilesTex);
124 iContext->setSamplerState("tilesValue_uintSampler", 1, renderer->getRenderStates().commonSamplerStates[rendererData->value.sampler]);
125 }
126 else
127 {
128 iContext->setTexture("tilesValue_srgb", 1, rendererData->value.tilesTex);
129 iContext->setSamplerState("tilesValue_srgbSampler", 1, renderer->getRenderStates().commonSamplerStates[rendererData->value.sampler]);
130 }
131
132 iContext->setTexture("tilesDepth", 2, rendererData->depth.tilesTex);
133 iContext->setSamplerState("tilesDepthSampler", 2, renderer->getRenderStates().commonSamplerStates[rendererData->depth.sampler]);
134
135 iContext->setVertexBuffers(&im360Renderer->fullScreenTriangle.vertices, 1);
137 }
138
139
140 constexpr const char* atlasBlitVS_es30 = R"(#version 300 es
141precision highp float;
142in vec2 a_POSITION;
143void main()
144{
145 gl_Position = vec4(a_POSITION, 0, 1);
146}
147)";
148
149 constexpr const char* atlasBlitFloatPS_es30 = R"(#version 300 es
150precision highp float;
151precision highp sampler2DArray;
152uniform Params {
153 int sourceLayer;
154};
155uniform sampler2DArray source;
156out vec4 destination;
157void main()
158{
159 destination = texelFetch(source, ivec3(floor(gl_FragCoord.xy), sourceLayer), 0);
160}
161)";
162
163 constexpr const char* atlasBlitUIntPS_es30 = R"(#version 300 es
164precision highp float;
165precision highp int;
166precision highp usampler2DArray;
167uniform Params {
168 int sourceLayer;
169};
170uniform usampler2DArray source;
171out uvec4 destination;
172void main()
173{
174 destination = texelFetch(source, ivec3(floor(gl_FragCoord.xy), sourceLayer), 0);
175}
176)";
177
178
179 void atlasBlitInit(Context* context, Image360::RendererExtension* rendererExtension)
180 {
181 if (context->device->getType() != Cogs::GraphicsDeviceType::OpenGLES30) {
182 return;
183 }
184 auto& atlasBlit = rendererExtension->atlasBlit;
185
186 Cogs::IGraphicsDevice* device = context->device;
187 Cogs::IEffects* effects = device->getEffects();
188 Cogs::IBuffers* buffers = device->getBuffers();
189 Cogs::ITextures* textures = device->getTextures();
190 Cogs::IRenderTargets* renderTargets = device->getRenderTargets();
191
192 atlasBlit.f.effect = effects->loadEffectSource(atlasBlitVS_es30, atlasBlitFloatPS_es30);
193 if (HandleIsValid(atlasBlit.f.effect)) {
194 atlasBlit.f.inputLayout = buffers->loadInputLayout(&rendererExtension->fullScreenTriangle.streamsLayout.vertexFormats[0], 1, atlasBlit.f.effect);
195 atlasBlit.f.srcTexBinding = effects->getTextureBinding(atlasBlit.f.effect, "source", 0);
196 atlasBlit.f.srcSamplerBinding = effects->getSamplerStateBinding(atlasBlit.f.effect, "sourceSampler", 0);
197 atlasBlit.f.paramBinding = effects->getConstantBufferBinding(atlasBlit.f.effect, "Params");
198 }
199
200 atlasBlit.u.effect = effects->loadEffectSource(atlasBlitVS_es30, atlasBlitUIntPS_es30);
201 if (HandleIsValid(atlasBlit.f.effect)) {
202 atlasBlit.u.inputLayout = buffers->loadInputLayout(&rendererExtension->fullScreenTriangle.streamsLayout.vertexFormats[0], 1, atlasBlit.u.effect);
203 atlasBlit.u.srcTexBinding = effects->getTextureBinding(atlasBlit.u.effect, "source", 0);
204 atlasBlit.u.srcSamplerBinding = effects->getSamplerStateBinding(atlasBlit.u.effect, "sourceSampler", 0);
205 atlasBlit.u.paramBinding = effects->getConstantBufferBinding(atlasBlit.u.effect, "Params");
206 }
207
208 atlasBlit.paramBuffer = buffers->loadBuffer(nullptr, sizeof(uint32_t), Cogs::Usage::Dynamic, Cogs::AccessMode::Write, Cogs::BindFlags::ConstantBuffer);
209
210 atlasBlit.samplerState = textures->loadSamplerState({
215 .comparisonFunction = Cogs::SamplerState::ComparisonFunction::Never,
216 .maxAnisotropy = 1,
217 .borderColor = { 0, 0, 0, 1 }
218 });
219
220 atlasBlit.depthStencilState = renderTargets->loadDepthStencilState({
221 .depthEnabled = false,
222 .writeEnabled = true,
223 .depthFunction = Cogs::DepthStencilState::Always
224 });
225
226 atlasBlit.blendState = renderTargets->loadBlendState({
227 .enabled = 0,
228 .sourceBlend = Cogs::BlendState::Blend::One,
229 .destinationBlend = Cogs::BlendState::Blend::Zero,
230 .operation = Cogs::BlendState::BlendOperation::Add
231 });
232 }
233
234 bool atlasTileBlit(Context* context, const Image360::RendererExtension* rendererExtension,
235 Cogs::TextureHandle dstTex, uint32_t dstLayer,
236 Cogs::TextureHandle srcTex, uint32_t srcLayer,
237 uint32_t w, uint32_t h, Cogs::TextureFormat fmt)
238 {
239 bool formatIsFloat = true;
240 switch (fmt) {
241 case Cogs::DataFormat::R8G8B8A8_UNORM:
242 case Cogs::DataFormat::R8G8B8A8_UNORM_SRGB:
243 formatIsFloat = true;
244 if (!HandleIsValid(rendererExtension->atlasBlit.f.effect)) {
245 return false;
246 }
247 break;
248 case Cogs::DataFormat::R16_UINT:
249 formatIsFloat = false;
250 if (!HandleIsValid(rendererExtension->atlasBlit.u.effect)) {
251 return false;
252 }
253 break;
254 default:
255 LOG_ERROR_ONCE(logger, "Trying to blit unsupported format: %d", static_cast<uint32_t>(fmt));
256 return false;
257 }
258
259 Cogs::IGraphicsDevice* device = context->device;
260 Cogs::IRenderTargets* renderTargets = device->getRenderTargets();
261 Cogs::IContext* immediateContext = device->getImmediateContext();
262
264 .texture = dstTex,
265 .layerIndex = static_cast<uint16_t>(dstLayer),
266 .numLayers = 1,
267 .levelIndex = 0
268 };
269 Cogs::RenderTargetHandle renderTarget = renderTargets->createRenderTarget(&view, 1);
270
271 immediateContext->setRenderTarget(renderTarget, Cogs::DepthStencilHandle::NoHandle);
272 immediateContext->setViewport(0.f, 0.f, static_cast<float>(w), static_cast<float>(h));
273 immediateContext->updateBuffer(rendererExtension->atlasBlit.paramBuffer, &srcLayer, sizeof(uint32_t));
274 if (formatIsFloat) {
275 immediateContext->setEffect(rendererExtension->atlasBlit.f.effect);
276 immediateContext->setInputLayout(rendererExtension->atlasBlit.f.inputLayout);
277 immediateContext->setConstantBuffer(rendererExtension->atlasBlit.f.paramBinding, rendererExtension->atlasBlit.paramBuffer);
278 immediateContext->setTexture(rendererExtension->atlasBlit.f.srcTexBinding, srcTex);
279 immediateContext->setSamplerState(rendererExtension->atlasBlit.f.srcSamplerBinding, rendererExtension->atlasBlit.samplerState);
280 }
281 else {
282 immediateContext->setEffect(rendererExtension->atlasBlit.u.effect);
283 immediateContext->setInputLayout(rendererExtension->atlasBlit.u.inputLayout);
284 immediateContext->setConstantBuffer(rendererExtension->atlasBlit.u.paramBinding, rendererExtension->atlasBlit.paramBuffer);
285 immediateContext->setTexture(rendererExtension->atlasBlit.u.srcTexBinding, srcTex);
286 immediateContext->setSamplerState(rendererExtension->atlasBlit.u.srcSamplerBinding, rendererExtension->atlasBlit.samplerState);
287 }
288 immediateContext->setVertexBuffers(&rendererExtension->fullScreenTriangle.vertices, 1);
289 immediateContext->setDepthStencilState(rendererExtension->atlasBlit.depthStencilState);
290 immediateContext->setBlendState(rendererExtension->atlasBlit.blendState);
291 immediateContext->draw(Cogs::PrimitiveType::TriangleStrip, 0, 4);
292
294 renderTargets->releaseRenderTarget(renderTarget);
295
296 return true;
297 }
298
299
300}
301
302
304{
305 this->device = device;
306 this->context = context;
307 im360System = ExtensionRegistry::getExtensionSystem<Image360System>(context);
308
309 IBuffers* buffers = device->getBuffers();
310
311
312 Cogs::VertexElement element{
314 };
315 fullScreenTriangle.streamsLayout.vertexFormats[0] = VertexFormats::createVertexFormat(element);
316 fullScreenTriangle.streamsLayout.numStreams = 1;
317 fullScreenTriangle.streamsLayout.updateHash();
318
319 static const float fullScreenTriangleVertexData[] = {
320 -1.f, -1.f,
321 3.f, -1.f,
322 -1.f, 3.f
323 };
324 fullScreenTriangle.vertices = buffers->loadVertexBuffer(fullScreenTriangleVertexData,
325 sizeof(fullScreenTriangleVertexData) / sizeof(fullScreenTriangleVertexData[0]),
326 fullScreenTriangle.streamsLayout.vertexFormats[0]);
327 atlasBlitInit(context, this);
328}
329
330
331void Cogs::Core::Image360::RendererExtension::release()
332{
333 IGraphicsDevice* device = context->renderer->getDevice();
334 IBuffers* buffers = device->getBuffers();
335 if (HandleIsValid(fullScreenTriangle.vertices)) {
336 buffers->releaseBuffer(fullScreenTriangle.vertices);
337 fullScreenTriangle.vertices = BufferHandle::NoHandle;
338 }
339}
340
341
342void Cogs::Core::Image360::RendererExtension::releaseRenderingResources(RendererExtensionData& rendererData)
343{
344 IGraphicsDevice* device = context->renderer->getDevice();
345 ITextures* textures = device->getTextures();
346 IBuffers* buffers = device->getBuffers();
347
348 if (HandleIsValid(rendererData.constants)) {
349 buffers->releaseBuffer(rendererData.constants);
350 rendererData.constants = Cogs::BufferHandle::NoHandle;
351 }
352
353 if (HandleIsValid(rendererData.encodedTreesTex)) {
354 textures->releaseTexture(rendererData.encodedTreesTex);
355 rendererData.encodedTreesTex = Cogs::TextureHandle::NoHandle;
356 }
357
358 if (HandleIsValid(rendererData.value.tilesTex)) {
359 textures->releaseTexture(rendererData.value.tilesTex);
360 rendererData.value.tilesTex = Cogs::TextureHandle::NoHandle;
361 }
362
363 if (HandleIsValid(rendererData.depth.tilesTex)) {
364 textures->releaseTexture(rendererData.depth.tilesTex);
365 rendererData.depth.tilesTex = Cogs::TextureHandle::NoHandle;
366 }
367 rendererData.depth.tilesData.clear();
368}
369
370
371void Cogs::Core::Image360::RendererExtension::handleEvent(uint32_t eventId, const DrawContext * renderingContext)
372{
373 if (!renderingContext) return;
374
375 switch (eventId) {
377 RenderResources & resources = renderingContext->renderer->getRenderResources();
378
379 IContext* deviceContext = renderingContext->deviceContext;
380 ITextures* textures = renderingContext->device->getTextures();
381 IBuffers* buffers = renderingContext->device->getBuffers();
382
383 for (Image360Component& im360Comp : im360System->pool) {
384
385 Image360Data& im360Data = im360System->getData(&im360Comp);
386 RendererExtensionData& rendererData = im360Data.rendererData;
387
388 if ((im360Data.state == Image360Data::State::WaitingForBaseLevel) || (im360Data.state == Image360Data::State::Running))
389 {
390 im360Data.rendererData.baseSize = im360Data.config.baseSize;
391 im360Data.rendererData.noDataDepth = im360Data.config.noDataDepth;
392 if (im360Data.config.valueChannel < im360Data.config.channels.size()) {
393 const Config::Channel& channel = im360Data.config.channels[im360Data.config.valueChannel];
394 rendererData.value.scale = channel.scale;
395 rendererData.value.bias = channel.bias;
396 switch (channel.dataType) {
397 case Config::Channel::DataType::U16: [[fallthrough]];
399 rendererData.value.sampler = 3;
400 break;
401 default:
402 rendererData.value.sampler = 1;
403 break;
404 }
405 }
406 else {
407 rendererData.value.scale = 1.f;
408 rendererData.value.bias = 0.f;
409 }
410 rendererData.value.scale /= (im360Comp.valueDomainMax - im360Comp.valueDomainMin);
411 rendererData.value.bias = (rendererData.value.bias - im360Comp.valueDomainMin) / (im360Comp.valueDomainMax - im360Comp.valueDomainMin);
412
413
414 if (im360Data.config.hasDepth) {
415 const Config::Channel& channel = im360Data.config.channels[im360Data.config.depthChannel];
416 rendererData.depth.scale = channel.scale;
417 rendererData.depth.bias = channel.bias;
418 switch (channel.dataType) {
419 case Config::Channel::DataType::U16: [[fallthrough]];
421 rendererData.depth.sampler = 3;
422 break;
423 default:
424 rendererData.depth.sampler = 1;
425 break;
426 }
427 }
428
429 if (!HandleIsValid(rendererData.constants)) {
430 rendererData.constants = buffers->loadBuffer(nullptr, sizeof(Constants), Cogs::Usage::Dynamic, Cogs::AccessMode::Write, Cogs::BindFlags::ConstantBuffer, 0);
431 }
432
433 if (HandleIsValid(rendererData.encodedTreesTex)) {
434 textures->releaseTexture(rendererData.encodedTreesTex);
435 rendererData.encodedTreesTex = Cogs::TextureHandle::NoHandle;
436 }
437
438 if(!im360Data.lodTree.data.empty()) {
439 TextureDescription desc{};
440 desc.target = Cogs::ResourceDimensions::Texture2D;
441 desc.width = static_cast<uint32_t>(im360Data.lodTree.data.size());
442 desc.height = 1;
443 desc.format = Cogs::TextureFormat::R16_SINT;
444 desc.flags = Cogs::TextureFlags::Default;
445
446 TextureData textureData(im360Data.lodTree.data.data(), TextureExtent{ desc.width, 1, 1 }, 1, 1, 1, desc.format);
447 rendererData.encodedTreesTex = textures->loadTexture(desc, &textureData);
448
449 if (rendererData.currentTreeSize != desc.width) {
450 rendererData.currentTreeSize = desc.width;
451 LOG_TRACE(logger, "Current tree size: %u", rendererData.currentTreeSize);
452 }
453 }
454
455
456 uint32_t cacheItemCount = std::max(6u, static_cast<uint32_t>(im360Data.cache.items.size()));
457 bool resizeCache = (!HandleIsValid(im360Data.rendererData.value.tilesTex) ||
458 (rendererData.gpuAllocatedCacheItemCount < cacheItemCount) ||
459 (cacheItemCount < rendererData.gpuAllocatedCacheItemCount / 2));
460
461 if (resizeCache) {
462
463 Cogs::ResourceDimensions target = Cogs::ResourceDimensions::Unknown;
464 rendererData.gpuAllocatedCacheItemCount = cacheItemCount + (cacheItemCount + 9) / 10; // No aggressive over-allocation since we don't grow one-by-one.
465
466 rendererData.cacheLayout.cols = 1;
467 rendererData.cacheLayout.rows = 1;
468 rendererData.cacheLayout.layers = rendererData.gpuAllocatedCacheItemCount;
469 target = Cogs::ResourceDimensions::Texture2DArray;
470
471 // ------- Resize value texture
472 {
473 TextureDescription desc{};
474 desc.target = target;
475 desc.width = rendererData.cacheLayout.cols * im360Data.config.baseSize;
476 desc.height = rendererData.cacheLayout.rows * im360Data.config.baseSize;
477 desc.layers = rendererData.cacheLayout.layers;
478 desc.flags = Cogs::TextureFlags::Default;
479
480 assert(im360Data.config.valueChannel < im360Data.config.channels.size());
481 switch (im360Data.config.channels[im360Data.config.valueChannel].dataType) {
482
483 case Config::Channel::DataType::SRGB8_JPEG: [[fallthrough]];
484 case Config::Channel::DataType::SRGB8_PNG: [[fallthrough]]; // D3D11 doesn't support 3-channel 8-bit format, probably promoted in GL anyways.
486 desc.format = Cogs::DataFormat::R8G8B8A8_UNORM_SRGB;
487 break;
488 case Config::Channel::DataType::U16: [[fallthrough]];
490 desc.format = Cogs::DataFormat::R16_UINT;
491 break;
492 default:
493 assert(false && "Invalid enum value");
494 break;
495 }
496 Cogs::TextureHandle tilesValueOldTex = rendererData.value.tilesTex;
497 rendererData.value.tilesTex = textures->loadTexture(desc, nullptr);
498 if (HandleIsValid(tilesValueOldTex)) {
499 uint32_t toCopy = std::min(rendererData.gpuActiveCacheItemCount, rendererData.gpuAllocatedCacheItemCount);
500 for (uint32_t i = 0; i < toCopy; i++) {
501 if (im360Data.cache.items[i].value.state == Cache::Item::State::Resident) {
502 if (!atlasTileBlit(context, this,
503 rendererData.value.tilesTex, i,
504 tilesValueOldTex, i,
505 im360Data.config.baseSize, im360Data.config.baseSize, desc.format))
506 {
507 deviceContext->copyTexture(rendererData.value.tilesTex,
508 i, 0, 0, 0,
509 tilesValueOldTex, i);
510 }
511 }
512 }
513 textures->releaseTexture(tilesValueOldTex);
514 }
515 }
516
517 // ------- Resize depth texture if enabled
518 if (im360Data.config.hasDepth) {
519
520 TextureDescription desc{};
521 desc.target = target;
522 desc.width = rendererData.cacheLayout.cols * im360Data.config.baseSize;
523 desc.height = rendererData.cacheLayout.rows * im360Data.config.baseSize;
524 desc.layers = rendererData.cacheLayout.layers;
525 desc.flags = Cogs::TextureFlags::Default;
526 switch (im360Data.config.channels[im360Data.config.depthChannel].dataType) {
527 case Config::Channel::DataType::U16: [[fallthrough]];
529 desc.format = Cogs::DataFormat::R16_UINT;
530 break;
531 default:
532 assert(false && "Invalid enum value");
533 break;
534 }
535 Cogs::TextureHandle tilesDepthOldTex = rendererData.depth.tilesTex;
536 rendererData.depth.tilesTex = textures->loadTexture(desc, nullptr);
537 if (HandleIsValid(tilesDepthOldTex)) {
538 uint32_t toCopy = std::min(rendererData.gpuActiveCacheItemCount, rendererData.gpuAllocatedCacheItemCount);
539 for (uint32_t i = 0; i < toCopy; i++) {
540 if (im360Data.cache.items[i].depth.state == Cache::Item::State::Resident) {
541 if (!atlasTileBlit(context, this,
542 rendererData.depth.tilesTex, i,
543 tilesDepthOldTex, i,
544 im360Data.config.baseSize, im360Data.config.baseSize, desc.format))
545 {
546 deviceContext->copyTexture(rendererData.depth.tilesTex,
547 i, 0, 0, 0,
548 tilesDepthOldTex, i);
549 }
550 }
551 }
552 textures->releaseTexture(tilesDepthOldTex);
553 }
554
555 rendererData.depth.tilesData.resize(rendererData.gpuAllocatedCacheItemCount);
556 }
557
558 LOG_DEBUG(logger, "gpuAllocatedCacheItemCount=%u", rendererData.gpuAllocatedCacheItemCount);
559 }
560
561 for (Fetcher::LoadItem& loadItem : im360Data.fetcher.itemsUploading) {
562 Cache::Item& item = im360Data.cache.items[loadItem.slotIx];
563
564 bool consumed = false;
565 if (loadItem.channelIx == im360Data.config.valueChannel) {
566 if (item.value.state == Cache::Item::State::Loaded) {
567 uint32_t x = 0;
568 uint32_t y = 0;
569 uint32_t slice = loadItem.slotIx;
570
571 RenderTexture* texture = resources.getRenderTexture(loadItem.texture);
572 deviceContext->copyTexture(rendererData.value.tilesTex,
573 slice, x, y, 0,
574 texture->textureHandle, 0);
575 item.value.state = Cache::Item::State::Resident;
576 }
577 consumed = true;
578 }
579
580 if (loadItem.channelIx == im360Data.config.depthChannel) {
581 if (item.depth.state == Cache::Item::State::Loaded) {
582 uint32_t x = 0;
583 uint32_t y = 0;
584 uint32_t slice = loadItem.slotIx;
585
586 RenderTexture* texture = resources.getRenderTexture(loadItem.texture);
587 deviceContext->copyTexture(rendererData.depth.tilesTex,
588 slice, x, y, 0,
589 texture->textureHandle, 0);
590 item.depth.state = Cache::Item::State::Resident;
591
592 size_t tileByteSize = sizeof(uint16_t) * im360Data.config.baseSize * im360Data.config.baseSize;
593 if (loadItem.buffer && loadItem.buffer->size() == tileByteSize) {
594
595 if (0 <= loadItem.slotIx && size_t(loadItem.slotIx) < rendererData.depth.tilesData.size()) {
596 rendererData.depth.tilesData[loadItem.slotIx] = std::move(loadItem.buffer);
597 }
598 }
599 }
600 consumed = true;
601 }
602
603 if (!consumed) {
604 LOG_WARNING(logger, "Unexpected load item not uploaded to GPU");
605 }
606 }
607 im360Data.fetcher.itemsUploading.clear();
608
609 rendererData.gpuActiveCacheItemCount = static_cast<uint32_t>(im360Data.cache.items.size());
610 }
611 else {
612 releaseRenderingResources(rendererData);
613 }
614 }
615 break;
616 }
617
619 break;
620
621 default:
622 break;
623 }
624}
625
626void Cogs::Core::Image360::RendererExtension::generateCommands(const RenderTaskContext * renderingContext, RenderList * renderList)
627{
628 if (!renderingContext) return;
629 if (!HandleIsValid(im360System->material)) return;
630
631 for (const Image360Component& im360Comp : im360System->pool) {
632 if (!im360Comp.isVisible()) continue;
633
634 Image360Data& im360Data = im360System->getData(&im360Comp);
635 if (im360Data.state != Image360Data::State::Running) continue;
636
637 if (!HandleIsValid(im360Data.materialInstance)) continue;
638 const MaterialInstance* materialInstance = im360Data.materialInstance.resolve();
639
640 RenderItem& renderItem = renderList->createCustom(&fullScreenTriangle.streamsLayout);
641 renderItem.lod = im360Comp.lod;
642 renderItem.layer = im360Comp.layer;
643 renderItem.cullingIndex = ~0u;;
644 renderItem.objectId = im360Comp.objectId;
645 renderItem.flags |= (materialInstance->instanceFlags & MaterialFlags::CustomBucket) != 0 ? RenderItemFlags::CustomBucket : RenderItemFlags::None;
646 renderItem.flags |= materialInstance->hasTransparency() ? RenderItemFlags::Transparent : RenderItemFlags::None;
647 if (materialInstance->isBackdrop() || ((renderItem.layer & RenderLayers::Sky)) != RenderLayers::None) {
648 renderItem.flags |= RenderItemFlags::Backdrop;
649 }
650 renderItem.materialInstance = materialInstance;
651 getTransparencyState(renderingContext->renderer->getRenderStates(), materialInstance, renderItem);
652 renderItem.drawOrder = materialInstance->options.drawOrder != 0 ? materialInstance->options.drawOrder : im360Comp.drawOrder;
653 renderItem.setCallbackData(this);
654 renderItem.setCallbackData2(&im360Data.rendererData);
655 renderItem.callback = image360RenderCallback;
656 }
657}
A Context instance contains all the services, systems and runtime components needed to use Cogs.
Definition: Context.h:83
class IRenderer * renderer
Renderer.
Definition: Context.h:228
std::unique_ptr< class Variables > variables
Variables service instance.
Definition: Context.h:180
virtual IGraphicsDevice * getDevice()=0
Get the graphics device used by the renderer.
RenderLayers layer
Layer mask used to determine visibility for a given camera viewport.
int32_t drawOrder
Draw order within a render bucke.
constexpr bool isVisible() const
Check if the entity is visible or not.
uint32_t objectId
Object identifier passed to rendering commands.
Contains render resources used by the renderer.
Core renderer system.
Definition: Renderer.h:28
RenderStates & getRenderStates() override
Get the reference to the RenderStates structure.
Definition: Renderer.h:68
IGraphicsDevice * getDevice() override
Get the graphics device used by the renderer.
Definition: Renderer.h:45
Represents a graphics device used to manage graphics resources and issue drawing commands.
virtual IEffects * getEffects()=0
Get a pointer to the effect management interface.
virtual ITextures * getTextures()=0
Get a pointer to the texture management interface.
virtual IContext * getImmediateContext()=0
Get a pointer to the immediate context used to issue commands to the graphics device.
virtual IBuffers * getBuffers()=0
Get a pointer to the buffer management interface.
virtual IRenderTargets * getRenderTargets()=0
Get a pointer to the render target management interface.
Log implementation class.
Definition: LogManager.h:140
Contains the Engine, Renderer, resource managers and other systems needed to run Cogs....
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
@ OpenGLES30
Graphics device using the OpenGLES 3.0 API.
@ VertexData
Per vertex data.
@ TriangleStrip
Triangle strip.
@ TriangleList
List of triangles.
@ Position
Position semantic.
@ 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
float valueDomainMin
Set the source domain for scalar values, see 360.json's bias and scale to account for datatype.
float valueDomainMax
Set the source domain for scalar values, see 360.json's bias and scale to account for datatype.
@ SRGB8_JPEG
8-bit colors in SRGB color space stored as JPEG (.jpg).
@ U16_ZST
16-bit unsigned values stored as little endian raw values that are subsequently zstd compressed.
@ SRGBA8_PNG
8-bit colors in SRGB color space and a alpha channel (zero is transparent) stored as PNG (....
@ SRGB8_PNG
8-bit colors in SRGB color space stored as PNG (.png).
@ U16
16-bit unsigned values stored as little endian raw values.
uint32_t noDataDepth
Depth value that corresponds to noData.
Definition: Image360.h:47
uint32_t baseSize
Base image size of a cached tile. From json.
Definition: Image360.h:46
uint8_t valueChannel
Data channel to be used as value data. From component.
Definition: Image360.h:49
uint8_t depthChannel
Data channel that contains depth data. From json.
Definition: Image360.h:50
std::vector< Channel > channels
Data channels to use. From json.
Definition: Image360.h:51
bool hasDepth
If data has depth and component wants depth.
Definition: Image360.h:58
uint32_t gpuAllocatedCacheItemCount
Number of tiles allocated in current GPU cache texture.
Definition: Image360.h:175
uint32_t gpuActiveCacheItemCount
Number of tiles in current GPU cache that contain data.
Definition: Image360.h:174
void handleEvent(uint32_t eventId, const DrawContext *renderingContext) override
Called when rendering events occur.
void initialize(Context *context, IGraphicsDevice *device) override
Initialize the extension using the given context and device.
@ CustomBucket
Items with this flag should be put in Custom rendering buckets.
Definition: Material.h:64
Material instances represent a specialized Material combined with state for all its buffers and prope...
bool hasTransparency() const
Get if this instance has any transparency and should be rendered with blending enabled.
bool isBackdrop() const
Get if geometry rendered with this material instance is to be treated as backdrops.
MaterialOptions options
Material rendering options used by this instance.
uint16_t instanceFlags
Material instance flags.
VertexFormatHandle vertexFormats[maxStreams]
int32_t drawOrder
Ordering of draw items within a bucket.
Definition: RenderList.h:172
uint32_t objectId
Lower 6 of upper 8 bits are instance id bits, lower 24 bits are object id.
Definition: RenderList.h:174
RenderLayers layer
Visibility mask.
Definition: RenderList.h:170
@ PostRender
Rendering has finished for a given rendering context.
Definition: IRenderer.h:101
@ PreRender
Pre rendering happening for a given rendering context.
Definition: IRenderer.h:93
ResourceType * resolve() const
Resolve the handle, returning a pointer to the actual resource.
@ Always
Always evaluates to true.
static const Handle_t NoHandle
Represents a handle to nothing.
Definition: Common.h:78
Provides buffer management functionality.
Definition: IBuffers.h:13
virtual InputLayoutHandle loadInputLayout(const VertexFormatHandle *vertexFormats, const size_t count, EffectHandle effectHandle)=0
Loads a new input layout to map vertex flow between vertex buffers with the given vertexFormats to ef...
virtual BufferHandle loadBuffer(const void *data, const size_t size, Usage::EUsage usage, uint32_t accessMode, uint32_t bindFlags, uint32_t stride=0)=0
Loads a new buffer using the given data to populate the buffer.
virtual void releaseBuffer(BufferHandle bufferHandle)=0
Releases the buffer with the given bufferHandle.
virtual VertexBufferHandle loadVertexBuffer(const void *vertexData, const size_t count, const VertexFormat &vertexFormat)=0
Loads a new vertex buffer and populates it with the given data.
Represents a graphics device context which can receive rendering commands.
Definition: IContext.h:43
virtual void setTexture(const StringView &name, unsigned int unit, TextureHandle textureHandle)=0
Sets the texture slot given by unit with the given name to contain the given texture.
virtual void setRasterizerState(const RasterizerStateHandle handle)=0
Set the current rasterizer state.
virtual void setBlendState(const BlendStateHandle handle, const float *constant=nullptr)=0
Set the current blend state.
virtual void setInputLayout(const InputLayoutHandle inputLayoutHandle)=0
Sets the current input layout.
virtual void setDepthStencilState(const DepthStencilStateHandle handle)=0
Set the current depth stencil state.
virtual void setConstantBuffer(const StringView &name, const BufferHandle bufferHandle, const uint32_t offset=0, const uint32_t size=~0u)=0
Sets a constant buffer to be bound to the given name and slot.
virtual void updateBuffer(BufferHandle bufferHandle, const void *data, size_t size)=0
Replace contents of buffer with new data.
virtual void setViewport(const float x, const float y, const float width, const float height)=0
Sets the current viewport to the given location and dimensions.
virtual void draw(PrimitiveType primitiveType, const size_t startVertex, const size_t numVertexes)=0
Draws non-indexed, non-instanced primitives.
virtual void setSamplerState(const StringView &name, unsigned int unit, SamplerStateHandle samplerStateHandle)=0
Sets the sampler slot given by unit with the given name to contain the given sampler state.
virtual void setVertexBuffers(const VertexBufferHandle *vertexBufferHandles, const size_t count, const uint32_t *strides, const uint32_t *offsets)=0
Sets the current vertex buffers.
virtual void setEffect(EffectHandle handle)=0
Set the current effect.
virtual void setRenderTarget(const RenderTargetHandle handle, const DepthStencilHandle depthStencilHandle)=0
Sets the current render target and an associated depth stencil target.
Provides effects and shader management functionality.
Definition: IEffects.h:148
virtual SamplerStateBindingHandle getSamplerStateBinding(EffectHandle effectHandle, const StringView &name, const unsigned int slot)=0
Get a handle to a sampler state object binding, mapping how to bind the sampler state to the given ef...
virtual ConstantBufferBindingHandle getConstantBufferBinding(EffectHandle effectHandle, const StringView &name)=0
Get a handle to a constant buffer binding, mapping how to bind a constant buffer to the given effect.
virtual TextureBindingHandle getTextureBinding(EffectHandle effectHandle, const StringView &name, const unsigned int slot)=0
Get a handle to a texture object binding, mapping how to bind textures to the given effect.
virtual EffectHandle loadEffectSource(const StringView &vsSource, const StringView &psSource, EffectFlags::EEffectFlags effectFlags=EffectFlags::None)=0
Load an effect created from the vertex and pixel shader sources given.
Provides render target management functionality.
virtual BlendStateHandle loadBlendState(const BlendState &blendState)=0
Load a blend state object.
virtual DepthStencilStateHandle loadDepthStencilState(const DepthStencilState &depthStencilState)=0
Load a depth stencil state object.
virtual void releaseRenderTarget(RenderTargetHandle renderTargetHandle)=0
Release the render target with the given renderTargetHandle.
virtual RenderTargetHandle createRenderTarget(TextureHandle textureHandle)
Create a render target using the given texture to render into.
Provides texture management functionality.
Definition: ITextures.h:40
virtual SamplerStateHandle loadSamplerState(const SamplerState &state)=0
Load a sampler state object.
virtual void releaseTexture(TextureHandle textureHandle)=0
Release the texture with the given textureHandle.
virtual TextureHandle loadTexture(const unsigned char *bytes, unsigned int width, unsigned int height, TextureFormat format, unsigned int flags=0)=0
Load a texture using the given data to populate the texture contents.
Describes a single render target view and which resources to use from the underlying texture.
TextureHandle texture
Texture handle.
@ Clamp
Texture coordinates are clamped to the [0, 1] range.
Definition: SamplerState.h:17
@ MinMagMipPoint
Point sampling for both minification and magnification.
Definition: SamplerState.h:33
@ Default
Default usage, the texture can be loaded once and bound and sampled in shaders.
Definition: Flags.h:116
@ Dynamic
Buffer will be loaded and modified with some frequency.
Definition: Flags.h:30
Vertex element structure used to describe a single data element in a vertex for the input assembler.
Definition: VertexFormat.h:38