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 bool useCamData = 2.f < std::min(camData->viewportSize.x, camData->viewportSize.y);
48
49 Renderer* renderer = taskContext->renderer;
50 float w = useCamData ? camData->viewportSize.x : (drawContext->renderTarget ? drawContext->renderTarget->width : renderer->getSize().x);
51 float h = useCamData ? camData->viewportSize.y : (drawContext->renderTarget ? drawContext->renderTarget->height : renderer->getSize().y);
52
53 Cogs::IGraphicsDevice* device = renderer->getDevice();
54 Cogs::IContext* iContext = device->getImmediateContext();
55 RendererExtension* im360Renderer = renderItem->getCallbackData<RendererExtension>();
56 RendererExtensionData* rendererData = renderItem->getCallbackData2<RendererExtensionData>();
57 if (!HandleIsValid(rendererData->encodedTreesTex)) {
58 return;
59 }
60 if (!HandleIsValid(rendererData->value.tilesTex)) {
61 return;
62 }
63
64 iContext->setViewport(camData->viewportOrigin.x, camData->viewportOrigin.y, w, h);
65 iContext->setDepthStencilState(taskContext->states->commonDepthStates[renderItem->depthState]);
66 iContext->setBlendState(taskContext->states->blendStates[renderItem->blendState].handle);
67
68 const RenderPassOptions passOptions = initRenderPassOptions(*renderItem, *camData);
69 iContext->setRasterizerState(taskContext->states->rasterizerStateHandles[getRasterizerState(renderer, *renderItem, passOptions, camData->flipWindingOrder, true)]);
70
71 // Invokes updateSceneBindings
72 // Invokes updateMaterialBindings(instance=false)
73 applyMaterialPermutation(taskContext, drawContext, renderItem->binding, renderItem->renderMaterialInstance);
74
75 // INvokes updateEnvironmentBindings,
76 // Updates permutation->constant buffers
77 drawContext->task->applyMaterial(*drawContext, *renderItem);
78
79 // Invokes updateMaterialBindings -> applyMaterialProperties
80 applyMaterialInstance(drawContext, renderItem->binding, renderItem->renderMaterialInstance);
81
82 updateSceneBindings(drawContext, drawContext->cameraData, renderItem->binding);
83
84 updateMaterialBindings(drawContext, renderItem->renderMaterialInstance, renderItem->binding, true);
85
86 Cogs::IEffects* effects = device->getEffects();
87
88 const glm::mat3 viewFromLocal = glm::mat3(drawContext->cameraData->viewMatrix) * rendererData->worldFromLocal;
89 const glm::mat3 localFromView = rendererData->localFromWorld * glm::mat3(drawContext->cameraData->inverseViewMatrix);
90 const float clipSpaceNearPlane = drawContext->context->variables->get("renderer.reverseDepth", false) ? 1.f : -1.f;
91 const EffectBinding* bindings = renderItem->binding;
92 const EngineBuffers& engineBuffers = *drawContext->engineBuffers;
93
94 if (Cogs::ConstantBufferBindingHandle constantsBinding = effects->getConstantBufferBinding(renderItem->binding->renderEffect->effectHandle, "Constants"); HandleIsValid(constantsBinding)) {
95 Constants constants{
96 .worldFromLocal = rendererData->worldFromLocal,
97 .localFromWorld = rendererData->localFromWorld,
98 .clipSpaceNearPlane = clipSpaceNearPlane,
99 .valueScale = rendererData->value.scale,
100 .valueBias = rendererData->value.bias,
101 .depthScale = rendererData->depth.scale,
102 .depthBias = rendererData->depth.bias,
103 .baseSize = float(rendererData->baseSize),
104 .noDataDepth = rendererData->noDataDepth
105 };
106 iContext->updateBuffer(rendererData->constants, &constants, sizeof(constants));
107 iContext->setConstantBuffer(constantsBinding, rendererData->constants);
108 }
109
110 if (HandleIsValid(bindings->objectBufferBinding)) {
111 ObjectBuffer objectBuffer = {};
112 objectBuffer.objectId = renderItem->objectId;
113 iContext->updateBuffer(rendererData->constants, &objectBuffer, sizeof(objectBuffer));
114 iContext->setConstantBuffer(bindings->objectBufferBinding, engineBuffers.objectBufferHandle);
115 }
116
117 iContext->setTexture("encodedTrees", 0, rendererData->encodedTreesTex);
118 iContext->setSamplerState("encodedTreesSampler", 0, renderer->getRenderStates().commonSamplerStates[3]);
119
120 iContext->setTexture("tilesValue", 1, rendererData->value.tilesTex);
121 iContext->setSamplerState("tilesValueSampler", 1, renderer->getRenderStates().commonSamplerStates[rendererData->value.sampler]);
122
123 iContext->setTexture("tilesDepth", 2, rendererData->depth.tilesTex);
124 iContext->setSamplerState("tilesDepthSampler", 2, renderer->getRenderStates().commonSamplerStates[rendererData->depth.sampler]);
125
126 iContext->setVertexBuffers(&im360Renderer->fullScreenTriangle.vertices, 1);
128 }
129
130
131 constexpr const char* atlasBlitVS_es30 = R"(#version 300 es
132precision highp float;
133in vec2 a_POSITION;
134void main()
135{
136 gl_Position = vec4(a_POSITION, 0, 1);
137}
138)";
139
140 constexpr const char* atlasBlitFloatPS_es30 = R"(#version 300 es
141precision highp float;
142precision highp sampler2DArray;
143uniform Params {
144 int sourceLayer;
145};
146uniform sampler2DArray source;
147out vec4 destination;
148void main()
149{
150 destination = texelFetch(source, ivec3(floor(gl_FragCoord.xy), sourceLayer), 0);
151}
152)";
153
154 constexpr const char* atlasBlitUIntPS_es30 = R"(#version 300 es
155precision highp float;
156precision highp int;
157precision highp usampler2DArray;
158uniform Params {
159 int sourceLayer;
160};
161uniform usampler2DArray source;
162out uvec4 destination;
163void main()
164{
165 destination = texelFetch(source, ivec3(floor(gl_FragCoord.xy), sourceLayer), 0);
166}
167)";
168
169
170 void atlasBlitInit(Context* context, Image360::RendererExtension* rendererExtension)
171 {
172 if (context->device->getType() != Cogs::GraphicsDeviceType::OpenGLES30) {
173 return;
174 }
175 auto& atlasBlit = rendererExtension->atlasBlit;
176
177 Cogs::IGraphicsDevice* device = context->device;
178 Cogs::IEffects* effects = device->getEffects();
179 Cogs::IBuffers* buffers = device->getBuffers();
180 Cogs::ITextures* textures = device->getTextures();
181 Cogs::IRenderTargets* renderTargets = device->getRenderTargets();
182
183 atlasBlit.f.effect = effects->loadEffectSource(atlasBlitVS_es30, atlasBlitFloatPS_es30);
184 if (HandleIsValid(atlasBlit.f.effect)) {
185 atlasBlit.f.inputLayout = buffers->loadInputLayout(&rendererExtension->fullScreenTriangle.streamsLayout.vertexFormats[0], 1, atlasBlit.f.effect);
186 atlasBlit.f.srcTexBinding = effects->getTextureBinding(atlasBlit.f.effect, "source", 0);
187 atlasBlit.f.srcSamplerBinding = effects->getSamplerStateBinding(atlasBlit.f.effect, "sourceSampler", 0);
188 atlasBlit.f.paramBinding = effects->getConstantBufferBinding(atlasBlit.f.effect, "Params");
189 }
190
191 atlasBlit.u.effect = effects->loadEffectSource(atlasBlitVS_es30, atlasBlitUIntPS_es30);
192 if (HandleIsValid(atlasBlit.f.effect)) {
193 atlasBlit.u.inputLayout = buffers->loadInputLayout(&rendererExtension->fullScreenTriangle.streamsLayout.vertexFormats[0], 1, atlasBlit.u.effect);
194 atlasBlit.u.srcTexBinding = effects->getTextureBinding(atlasBlit.u.effect, "source", 0);
195 atlasBlit.u.srcSamplerBinding = effects->getSamplerStateBinding(atlasBlit.u.effect, "sourceSampler", 0);
196 atlasBlit.u.paramBinding = effects->getConstantBufferBinding(atlasBlit.u.effect, "Params");
197 }
198
199 atlasBlit.paramBuffer = buffers->loadBuffer(nullptr, sizeof(uint32_t), Cogs::Usage::Dynamic, Cogs::AccessMode::Write, Cogs::BindFlags::ConstantBuffer);
200
201 atlasBlit.samplerState = textures->loadSamplerState({
206 .comparisonFunction = Cogs::SamplerState::ComparisonFunction::Never,
207 .maxAnisotropy = 1,
208 .borderColor = { 0, 0, 0, 1 }
209 });
210
211 atlasBlit.depthStencilState = renderTargets->loadDepthStencilState({
212 .depthEnabled = false,
213 .writeEnabled = true,
214 .depthFunction = Cogs::DepthStencilState::Always
215 });
216
217 atlasBlit.blendState = renderTargets->loadBlendState({
218 .enabled = 0,
219 .sourceBlend = Cogs::BlendState::Blend::One,
220 .destinationBlend = Cogs::BlendState::Blend::Zero,
221 .operation = Cogs::BlendState::BlendOperation::Add
222 });
223 }
224
225 bool atlasTileBlit(Context* context, const Image360::RendererExtension* rendererExtension,
226 Cogs::TextureHandle dstTex, uint32_t dstLayer,
227 Cogs::TextureHandle srcTex, uint32_t srcLayer,
228 uint32_t w, uint32_t h, Cogs::TextureFormat fmt)
229 {
230 bool formatIsFloat = true;
231 switch (fmt) {
232 case Cogs::DataFormat::R8G8B8A8_UNORM:
233 case Cogs::DataFormat::R8G8B8A8_UNORM_SRGB:
234 formatIsFloat = true;
235 if (!HandleIsValid(rendererExtension->atlasBlit.f.effect)) {
236 return false;
237 }
238 break;
239 case Cogs::DataFormat::R16_UINT:
240 formatIsFloat = false;
241 if (!HandleIsValid(rendererExtension->atlasBlit.u.effect)) {
242 return false;
243 }
244 break;
245 default:
246 LOG_ERROR_ONCE(logger, "Trying to blit unsupported format: %d", static_cast<uint32_t>(fmt));
247 return false;
248 }
249
250 Cogs::IGraphicsDevice* device = context->device;
251 Cogs::IRenderTargets* renderTargets = device->getRenderTargets();
252 Cogs::IContext* immediateContext = device->getImmediateContext();
253
255 .texture = dstTex,
256 .layerIndex = static_cast<uint16_t>(dstLayer),
257 .numLayers = 1,
258 .levelIndex = 0
259 };
260 Cogs::RenderTargetHandle renderTarget = renderTargets->createRenderTarget(&view, 1);
261
262 immediateContext->setRenderTarget(renderTarget, Cogs::DepthStencilHandle::NoHandle);
263 immediateContext->setViewport(0.f, 0.f, static_cast<float>(w), static_cast<float>(h));
264 immediateContext->updateBuffer(rendererExtension->atlasBlit.paramBuffer, &srcLayer, sizeof(uint32_t));
265 if (formatIsFloat) {
266 immediateContext->setEffect(rendererExtension->atlasBlit.f.effect);
267 immediateContext->setInputLayout(rendererExtension->atlasBlit.f.inputLayout);
268 immediateContext->setConstantBuffer(rendererExtension->atlasBlit.f.paramBinding, rendererExtension->atlasBlit.paramBuffer);
269 immediateContext->setTexture(rendererExtension->atlasBlit.f.srcTexBinding, srcTex);
270 immediateContext->setSamplerState(rendererExtension->atlasBlit.f.srcSamplerBinding, rendererExtension->atlasBlit.samplerState);
271 }
272 else {
273 immediateContext->setEffect(rendererExtension->atlasBlit.u.effect);
274 immediateContext->setInputLayout(rendererExtension->atlasBlit.u.inputLayout);
275 immediateContext->setConstantBuffer(rendererExtension->atlasBlit.u.paramBinding, rendererExtension->atlasBlit.paramBuffer);
276 immediateContext->setTexture(rendererExtension->atlasBlit.u.srcTexBinding, srcTex);
277 immediateContext->setSamplerState(rendererExtension->atlasBlit.u.srcSamplerBinding, rendererExtension->atlasBlit.samplerState);
278 }
279 immediateContext->setVertexBuffers(&rendererExtension->fullScreenTriangle.vertices, 1);
280 immediateContext->setDepthStencilState(rendererExtension->atlasBlit.depthStencilState);
281 immediateContext->setBlendState(rendererExtension->atlasBlit.blendState);
282 immediateContext->draw(Cogs::PrimitiveType::TriangleStrip, 0, 4);
283
285 renderTargets->releaseRenderTarget(renderTarget);
286
287 return true;
288 }
289
290
291}
292
293
295{
296 this->device = device;
297 this->context = context;
298 im360System = ExtensionRegistry::getExtensionSystem<Image360System>(context);
299
300 IBuffers* buffers = device->getBuffers();
301
302
303 Cogs::VertexElement element{
305 };
306 fullScreenTriangle.streamsLayout.vertexFormats[0] = VertexFormats::createVertexFormat(element);
307 fullScreenTriangle.streamsLayout.numStreams = 1;
308 fullScreenTriangle.streamsLayout.updateHash();
309
310 static const float fullScreenTriangleVertexData[] = {
311 -1.f, -1.f,
312 3.f, -1.f,
313 -1.f, 3.f
314 };
315 fullScreenTriangle.vertices = buffers->loadVertexBuffer(fullScreenTriangleVertexData,
316 sizeof(fullScreenTriangleVertexData) / sizeof(fullScreenTriangleVertexData[0]),
317 fullScreenTriangle.streamsLayout.vertexFormats[0]);
318 atlasBlitInit(context, this);
319}
320
321
322void Cogs::Core::Image360::RendererExtension::release()
323{
324 IGraphicsDevice* device = context->renderer->getDevice();
325 IBuffers* buffers = device->getBuffers();
326 if (HandleIsValid(fullScreenTriangle.vertices)) {
327 buffers->releaseBuffer(fullScreenTriangle.vertices);
328 fullScreenTriangle.vertices = BufferHandle::NoHandle;
329 }
330}
331
332
333void Cogs::Core::Image360::RendererExtension::releaseRenderingResources(RendererExtensionData& rendererData)
334{
335 IGraphicsDevice* device = context->renderer->getDevice();
336 ITextures* textures = device->getTextures();
337 IBuffers* buffers = device->getBuffers();
338
339 if (HandleIsValid(rendererData.constants)) {
340 buffers->releaseBuffer(rendererData.constants);
341 rendererData.constants = Cogs::BufferHandle::NoHandle;
342 }
343
344 if (HandleIsValid(rendererData.encodedTreesTex)) {
345 textures->releaseTexture(rendererData.encodedTreesTex);
346 rendererData.encodedTreesTex = Cogs::TextureHandle::NoHandle;
347 }
348
349 if (HandleIsValid(rendererData.value.tilesTex)) {
350 textures->releaseTexture(rendererData.value.tilesTex);
351 rendererData.value.tilesTex = Cogs::TextureHandle::NoHandle;
352 }
353
354 if (HandleIsValid(rendererData.depth.tilesTex)) {
355 textures->releaseTexture(rendererData.depth.tilesTex);
356 rendererData.depth.tilesTex = Cogs::TextureHandle::NoHandle;
357 }
358 rendererData.depth.tilesData.clear();
359}
360
361
362void Cogs::Core::Image360::RendererExtension::handleEvent(uint32_t eventId, const DrawContext * renderingContext)
363{
364 if (!renderingContext) return;
365
366 switch (eventId) {
368 RenderResources & resources = renderingContext->renderer->getRenderResources();
369
370 IContext* deviceContext = renderingContext->deviceContext;
371 ITextures* textures = renderingContext->device->getTextures();
372 IBuffers* buffers = renderingContext->device->getBuffers();
373
374 for (Image360Component& im360Comp : im360System->pool) {
375
376 Image360Data& im360Data = im360System->getData(&im360Comp);
377 RendererExtensionData& rendererData = im360Data.rendererData;
378
379 if ((im360Data.state == Image360Data::State::WaitingForBaseLevel) || (im360Data.state == Image360Data::State::Running))
380 {
381 im360Data.rendererData.baseSize = im360Data.config.baseSize;
382 im360Data.rendererData.noDataDepth = im360Data.config.noDataDepth;
383 if (im360Data.config.valueChannel < im360Data.config.channels.size()) {
384 const Config::Channel& channel = im360Data.config.channels[im360Data.config.valueChannel];
385 rendererData.value.scale = channel.scale;
386 rendererData.value.bias = channel.bias;
387 switch (channel.dataType) {
388 case Config::Channel::DataType::U16: [[fallthrough]];
390 rendererData.value.sampler = 3;
391 break;
392 default:
393 rendererData.value.sampler = 1;
394 break;
395 }
396 }
397 else {
398 rendererData.value.scale = 1.f;
399 rendererData.value.bias = 0.f;
400 }
401 rendererData.value.scale /= (im360Comp.valueDomainMax - im360Comp.valueDomainMin);
402 rendererData.value.bias = (rendererData.value.bias - im360Comp.valueDomainMin) / (im360Comp.valueDomainMax - im360Comp.valueDomainMin);
403
404
405 if (im360Data.config.hasDepth) {
406 const Config::Channel& channel = im360Data.config.channels[im360Data.config.depthChannel];
407 rendererData.depth.scale = channel.scale;
408 rendererData.depth.bias = channel.bias;
409 switch (channel.dataType) {
410 case Config::Channel::DataType::U16: [[fallthrough]];
412 rendererData.depth.sampler = 3;
413 break;
414 default:
415 rendererData.depth.sampler = 1;
416 break;
417 }
418 }
419
420 if (!HandleIsValid(rendererData.constants)) {
421 rendererData.constants = buffers->loadBuffer(nullptr, sizeof(Constants), Cogs::Usage::Dynamic, Cogs::AccessMode::Write, Cogs::BindFlags::ConstantBuffer, 0);
422 }
423
424 if (HandleIsValid(rendererData.encodedTreesTex)) {
425 textures->releaseTexture(rendererData.encodedTreesTex);
426 rendererData.encodedTreesTex = Cogs::TextureHandle::NoHandle;
427 }
428
429 if(!im360Data.lodTree.data.empty()) {
430 TextureDescription desc{};
431 desc.target = Cogs::ResourceDimensions::Texture2D;
432 desc.width = static_cast<uint32_t>(im360Data.lodTree.data.size());
433 desc.height = 1;
434 desc.format = Cogs::TextureFormat::R16_SINT;
435 desc.flags = Cogs::TextureFlags::Default;
436
437 TextureData textureData(im360Data.lodTree.data.data(), TextureExtent{ desc.width, 1, 1 }, 1, 1, 1, desc.format);
438 rendererData.encodedTreesTex = textures->loadTexture(desc, &textureData);
439
440 if (rendererData.currentTreeSize != desc.width) {
441 rendererData.currentTreeSize = desc.width;
442 LOG_TRACE(logger, "Current tree size: %u", rendererData.currentTreeSize);
443 }
444 }
445
446
447 uint32_t cacheItemCount = std::max(6u, static_cast<uint32_t>(im360Data.cache.items.size()));
448 bool resizeCache = (!HandleIsValid(im360Data.rendererData.value.tilesTex) ||
449 (rendererData.gpuAllocatedCacheItemCount < cacheItemCount) ||
450 (cacheItemCount < rendererData.gpuAllocatedCacheItemCount / 2));
451
452 if (resizeCache) {
453
454 Cogs::ResourceDimensions target = Cogs::ResourceDimensions::Unknown;
455 rendererData.gpuAllocatedCacheItemCount = cacheItemCount + (cacheItemCount + 9) / 10; // No aggressive over-allocation since we don't grow one-by-one.
456
457 rendererData.cacheLayout.cols = 1;
458 rendererData.cacheLayout.rows = 1;
459 rendererData.cacheLayout.layers = rendererData.gpuAllocatedCacheItemCount;
460 target = Cogs::ResourceDimensions::Texture2DArray;
461
462 // ------- Resize value texture
463 {
464 TextureDescription desc{};
465 desc.target = target;
466 desc.width = rendererData.cacheLayout.cols * im360Data.config.baseSize;
467 desc.height = rendererData.cacheLayout.rows * im360Data.config.baseSize;
468 desc.layers = rendererData.cacheLayout.layers;
469 desc.flags = Cogs::TextureFlags::Default;
470
471 assert(im360Data.config.valueChannel < im360Data.config.channels.size());
472 switch (im360Data.config.channels[im360Data.config.valueChannel].dataType) {
473
474 case Config::Channel::DataType::SRGB8_JPEG: [[fallthrough]];
475 case Config::Channel::DataType::SRGB8_PNG: [[fallthrough]]; // D3D11 doesn't support 3-channel 8-bit format, probably promoted in GL anyways.
477 desc.format = Cogs::DataFormat::R8G8B8A8_UNORM_SRGB;
478 break;
479 case Config::Channel::DataType::U16: [[fallthrough]];
481 desc.format = Cogs::DataFormat::R16_UINT;
482 break;
483 default:
484 assert(false && "Invalid enum value");
485 break;
486 }
487 Cogs::TextureHandle tilesValueOldTex = rendererData.value.tilesTex;
488 rendererData.value.tilesTex = textures->loadTexture(desc, nullptr);
489 if (HandleIsValid(tilesValueOldTex)) {
490 uint32_t toCopy = std::min(rendererData.gpuActiveCacheItemCount, rendererData.gpuAllocatedCacheItemCount);
491 for (uint32_t i = 0; i < toCopy; i++) {
492 if (im360Data.cache.items[i].value.state == Cache::Item::State::Resident) {
493 if (!atlasTileBlit(context, this,
494 rendererData.value.tilesTex, i,
495 tilesValueOldTex, i,
496 im360Data.config.baseSize, im360Data.config.baseSize, desc.format))
497 {
498 deviceContext->copyTexture(rendererData.value.tilesTex,
499 i, 0, 0, 0,
500 tilesValueOldTex, i);
501 }
502 }
503 }
504 textures->releaseTexture(tilesValueOldTex);
505 }
506 }
507
508 // ------- Resize depth texture if enabled
509 if (im360Data.config.hasDepth) {
510
511 TextureDescription desc{};
512 desc.target = target;
513 desc.width = rendererData.cacheLayout.cols * im360Data.config.baseSize;
514 desc.height = rendererData.cacheLayout.rows * im360Data.config.baseSize;
515 desc.layers = rendererData.cacheLayout.layers;
516 desc.flags = Cogs::TextureFlags::Default;
517 switch (im360Data.config.channels[im360Data.config.depthChannel].dataType) {
518 case Config::Channel::DataType::U16: [[fallthrough]];
520 desc.format = Cogs::DataFormat::R16_UINT;
521 break;
522 default:
523 assert(false && "Invalid enum value");
524 break;
525 }
526 Cogs::TextureHandle tilesDepthOldTex = rendererData.depth.tilesTex;
527 rendererData.depth.tilesTex = textures->loadTexture(desc, nullptr);
528 if (HandleIsValid(tilesDepthOldTex)) {
529 uint32_t toCopy = std::min(rendererData.gpuActiveCacheItemCount, rendererData.gpuAllocatedCacheItemCount);
530 for (uint32_t i = 0; i < toCopy; i++) {
531 if (im360Data.cache.items[i].depth.state == Cache::Item::State::Resident) {
532 if (!atlasTileBlit(context, this,
533 rendererData.depth.tilesTex, i,
534 tilesDepthOldTex, i,
535 im360Data.config.baseSize, im360Data.config.baseSize, desc.format))
536 {
537 deviceContext->copyTexture(rendererData.depth.tilesTex,
538 i, 0, 0, 0,
539 tilesDepthOldTex, i);
540 }
541 }
542 }
543 textures->releaseTexture(tilesDepthOldTex);
544 }
545
546 rendererData.depth.tilesData.resize(rendererData.gpuAllocatedCacheItemCount);
547 }
548
549 LOG_DEBUG(logger, "gpuAllocatedCacheItemCount=%u", rendererData.gpuAllocatedCacheItemCount);
550 }
551
552 for (Fetcher::LoadItem& loadItem : im360Data.fetcher.itemsUploading) {
553 Cache::Item& item = im360Data.cache.items[loadItem.slotIx];
554
555 bool consumed = false;
556 if (loadItem.channelIx == im360Data.config.valueChannel) {
557 if (item.value.state == Cache::Item::State::Loaded) {
558 uint32_t x = 0;
559 uint32_t y = 0;
560 uint32_t slice = loadItem.slotIx;
561
562 RenderTexture* texture = resources.getRenderTexture(loadItem.texture);
563 deviceContext->copyTexture(rendererData.value.tilesTex,
564 slice, x, y, 0,
565 texture->textureHandle, 0);
566 item.value.state = Cache::Item::State::Resident;
567 }
568 consumed = true;
569 }
570
571 if (loadItem.channelIx == im360Data.config.depthChannel) {
572 if (item.depth.state == Cache::Item::State::Loaded) {
573 uint32_t x = 0;
574 uint32_t y = 0;
575 uint32_t slice = loadItem.slotIx;
576
577 RenderTexture* texture = resources.getRenderTexture(loadItem.texture);
578 deviceContext->copyTexture(rendererData.depth.tilesTex,
579 slice, x, y, 0,
580 texture->textureHandle, 0);
581 item.depth.state = Cache::Item::State::Resident;
582
583 size_t tileByteSize = sizeof(uint16_t) * im360Data.config.baseSize * im360Data.config.baseSize;
584 if (loadItem.buffer && loadItem.buffer->size() == tileByteSize) {
585
586 if (0 <= loadItem.slotIx && size_t(loadItem.slotIx) < rendererData.depth.tilesData.size()) {
587 rendererData.depth.tilesData[loadItem.slotIx] = std::move(loadItem.buffer);
588 }
589 }
590 }
591 consumed = true;
592 }
593
594 if (!consumed) {
595 LOG_WARNING(logger, "Unexpected load item not uploaded to GPU");
596 }
597 }
598 im360Data.fetcher.itemsUploading.clear();
599
600 rendererData.gpuActiveCacheItemCount = static_cast<uint32_t>(im360Data.cache.items.size());
601 }
602 else {
603 releaseRenderingResources(rendererData);
604 }
605 }
606 break;
607 }
608
610 break;
611
612 default:
613 break;
614 }
615}
616
617void Cogs::Core::Image360::RendererExtension::generateCommands(const RenderTaskContext * renderingContext, RenderList * renderList)
618{
619 if (!renderingContext) return;
620 if (!HandleIsValid(im360System->material)) return;
621
622 for (const Image360Component& im360Comp : im360System->pool) {
623 if (!im360Comp.isVisible()) continue;
624
625 Image360Data& im360Data = im360System->getData(&im360Comp);
626 if (im360Data.state != Image360Data::State::Running) continue;
627
628 if (!HandleIsValid(im360Data.materialInstance)) continue;
629 const MaterialInstance* materialInstance = im360Data.materialInstance.resolve();
630
631 RenderItem& renderItem = renderList->createCustom(&fullScreenTriangle.streamsLayout);
632 renderItem.lod = im360Comp.lod;
633 renderItem.layer = im360Comp.layer;
634 renderItem.cullingIndex = ~0u;;
635 renderItem.objectId = im360Comp.objectId;
636 renderItem.flags |= (materialInstance->instanceFlags & MaterialFlags::CustomBucket) != 0 ? RenderItemFlags::CustomBucket : RenderItemFlags::None;
637 renderItem.flags |= materialInstance->hasTransparency() ? RenderItemFlags::Transparent : RenderItemFlags::None;
638 if (materialInstance->isBackdrop() || ((renderItem.layer & RenderLayers::Sky)) != RenderLayers::None) {
639 renderItem.flags |= RenderItemFlags::Backdrop;
640 }
641 renderItem.materialInstance = materialInstance;
642 getTransparencyState(renderingContext->renderer->getRenderStates(), materialInstance, renderItem);
643 renderItem.drawOrder = materialInstance->options.drawOrder != 0 ? materialInstance->options.drawOrder : im360Comp.drawOrder;
644 renderItem.setCallbackData(this);
645 renderItem.setCallbackData2(&im360Data.rendererData);
646 renderItem.callback = image360RenderCallback;
647 }
648}
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
glm::vec2 getSize() const override
Get the output surface size of the renderer.
Definition: Renderer.h:44
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:139
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:180
@ OpenGLES30
Graphics device using the OpenGLES 3.0 API.
@ VertexData
Per vertex data.
@ 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:77
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::EPrimitiveType 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.
@ TriangleStrip
Triangle strip.
Definition: Common.h:118
@ TriangleList
List of triangles.
Definition: Common.h:116
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