Divide Framework 0.1
A free and open-source 3D Framework under heavy development
Loading...
Searching...
No Matches
SceneEnvironmentProbePool.cpp
Go to the documentation of this file.
1
2
4
20
22
23namespace Divide {
24namespace {
25
26 constexpr bool s_AlwaysRefreshSkyLight = false;
28
31 constexpr U16 s_LUTTextureSize = 128u;
32
33 NO_DESTROY eastl::queue<U16> s_computationQueue;
36
38}
39
42
43std::array<SceneEnvironmentProbePool::ProbeSlice, Config::MAX_REFLECTIVE_PROBES_PER_PASS> SceneEnvironmentProbePool::s_availableSlices;
57
59 : SceneComponent(parentScene)
60{
61
62}
63
65{
66}
67
69{
71
73 {
74 if (s_availableSlices[i]._available)
75 {
76 s_availableSlices[i] = { false, lock };
77 return i;
78 }
79 }
80
82 {
84 }
85
87}
88
90{
91 s_availableSlices[slice] = { true, false };
92}
93
96
97 s_availableSlices.fill({});
98
99 // Reflection Targets
100 const SamplerDescriptor reflectionSampler = {
105 ._anisotropyLevel = context.context().config().rendering.maxAnisotropicFilteringLevel
106 };
107
108 const U32 reflectRes = to_U32(context.context().config().rendering.reflectionProbeResolution);
109 {
110 TextureDescriptor environmentDescriptor{};
111 environmentDescriptor._texType = TextureType::TEXTURE_CUBE_ARRAY;
112 environmentDescriptor._layerCount = Config::MAX_REFLECTIVE_PROBES_PER_PASS + 1u;
113 environmentDescriptor._mipMappingState = MipMappingState::MANUAL;
114
115 TextureDescriptor depthDescriptor{};
117 depthDescriptor._dataType = GFXDataFormat::UNSIGNED_INT;
118 depthDescriptor._baseFormat = GFXImageFormat::RED;
119 depthDescriptor._packing = GFXImagePacking::DEPTH;
120 depthDescriptor._layerCount = Config::MAX_REFLECTIVE_PROBES_PER_PASS + 1u;
121 depthDescriptor._mipMappingState = MipMappingState::MANUAL;
122
123 RenderTargetDescriptor desc = {};
124 desc._attachments =
125 {
128 };
129
130 desc._name = "ReflectionEnvMap";
131 desc._resolution.set(reflectRes, reflectRes);
132 s_reflection = context.renderTargetPool().allocateRT(desc);
133 }
134 {
135 TextureDescriptor environmentDescriptor{};
136 environmentDescriptor._texType = TextureType::TEXTURE_CUBE_ARRAY;
137 environmentDescriptor._dataType = GFXDataFormat::FLOAT_16;
138 environmentDescriptor._packing = GFXImagePacking::UNNORMALIZED;
139 environmentDescriptor._layerCount = Config::MAX_REFLECTIVE_PROBES_PER_PASS + 1u;
140 environmentDescriptor._mipMappingState = MipMappingState::MANUAL;
141 AddImageUsageFlag( environmentDescriptor, ImageUsage::SHADER_WRITE);
142
143 RenderTargetDescriptor desc = {};
144 desc._attachments =
145 {
147 };
148 desc._name = "PrefilteredEnvMap";
149 desc._resolution.set(reflectRes, reflectRes);
150 s_prefiltered = context.renderTargetPool().allocateRT(desc);
151 desc._name = "IrradianceEnvMap";
152 desc._resolution.set(s_IrradianceTextureSize, s_IrradianceTextureSize);
153 s_irradiance = context.renderTargetPool().allocateRT(desc);
154 }
155 {
156 TextureDescriptor environmentDescriptor{};
157 environmentDescriptor._dataType = GFXDataFormat::FLOAT_16;
158 environmentDescriptor._baseFormat = GFXImageFormat::RG;
159 environmentDescriptor._packing = GFXImagePacking::UNNORMALIZED;
160 environmentDescriptor._mipMappingState = MipMappingState::OFF;
161 AddImageUsageFlag( environmentDescriptor, ImageUsage::SHADER_WRITE);
162
163 RenderTargetDescriptor desc = {};
164 desc._attachments =
165 {
167 };
168 desc._name = "BrdfLUT";
169 desc._resolution.set(s_LUTTextureSize, s_LUTTextureSize);
170 s_brdfLUT = context.renderTargetPool().allocateRT(desc);
171 }
172 {
173 ShaderModuleDescriptor vertModule = {};
174 vertModule._moduleType = ShaderType::VERTEX;
175 vertModule._sourceFile = "baseVertexShaders.glsl";
176 vertModule._variant = "FullScreenQuad";
177
178 ShaderModuleDescriptor fragModule = {};
180 fragModule._sourceFile = "fbPreview.glsl";
181 fragModule._variant = "Cube";
182
183 ShaderProgramDescriptor shaderDescriptor = {};
184 shaderDescriptor._modules.push_back(vertModule);
185 shaderDescriptor._modules.push_back(fragModule);
186
187 ResourceDescriptor<ShaderProgram> shadowPreviewShader("fbPreview.Cube", shaderDescriptor );
188 shadowPreviewShader.waitForReady(true);
189 s_previewShader = CreateResource(shadowPreviewShader);
190 }
191 {
192 ShaderModuleDescriptor computeModule = {};
193 computeModule._moduleType = ShaderType::COMPUTE;
194 computeModule._sourceFile = "irradianceCalc.glsl";
195
196 ShaderProgramDescriptor shaderDescriptor = {};
197 shaderDescriptor._modules.push_back(computeModule);
198 shaderDescriptor._globalDefines.emplace_back( "imgSizeX PushData0[0].x" );
199 shaderDescriptor._globalDefines.emplace_back( "imgSizeY PushData0[0].y" );
200 shaderDescriptor._globalDefines.emplace_back( "layerIndex PushData0[0].z" );
201
202 {
203 shaderDescriptor._modules.back()._variant = "Irradiance";
204
205 ResourceDescriptor<ShaderProgram> irradianceShader("IrradianceCalc", shaderDescriptor );
206 irradianceShader.waitForReady(true);
207 s_irradianceComputeShader = CreateResource(irradianceShader);
208 }
209 {
210 shaderDescriptor._modules.back()._variant = "LUT";
211 ResourceDescriptor<ShaderProgram> lutShader("LUTCalc", shaderDescriptor );
212 lutShader.waitForReady(true);
214 }
215 {
216 shaderDescriptor._modules.back()._variant = "PreFilter";
217 shaderDescriptor._globalDefines.emplace_back( "mipLevel uint(PushData0[1].x)" );
218 shaderDescriptor._globalDefines.emplace_back( "roughness PushData0[1].y" );
219 ResourceDescriptor<ShaderProgram> prefilterShader("PrefilterEnv", shaderDescriptor );
220 prefilterShader.waitForReady(true);
221 s_prefilterComputeShader = CreateResource(prefilterShader);
222 }
223 }
224 {
225 PipelineDescriptor pipelineDescriptor{};
226 pipelineDescriptor._stateBlock = context.get2DStateBlock();
227 pipelineDescriptor._shaderProgramHandle = s_prefilterComputeShader;
228 pipelineDescriptor._primitiveTopology = PrimitiveTopology::COMPUTE;
229 s_pipelineCalcPrefiltered = context.newPipeline(pipelineDescriptor);
230 }
231 {
232 PipelineDescriptor pipelineDescriptor{};
233 pipelineDescriptor._stateBlock = context.get2DStateBlock();
234 pipelineDescriptor._shaderProgramHandle = s_irradianceComputeShader;
235 pipelineDescriptor._primitiveTopology = PrimitiveTopology::COMPUTE;
236 s_pipelineCalcIrradiance = context.newPipeline(pipelineDescriptor);
237 }
238}
239
245
250 {
252 }
253
254 // Remove old views
255 if (!s_debugViews.empty()) {
256 for (const DebugView_ptr& view : s_debugViews) {
257 context.removeDebugView(view.get());
258 }
259 s_debugViews.clear();
260 }
262 s_pipelineCalcIrradiance = nullptr;
263
264 s_computationQueue = {};
265 s_computationSet.clear();
266 s_queuedLayer = 0u;
268}
269
271 return s_reflection;
272}
273
275 return s_prefiltered;
276}
277
279 return s_irradiance;
280}
281
283 return s_brdfLUT;
284}
285
287 eastl::sort(begin(_envProbes),
288 end(_envProbes),
289 [&position](const auto& a, const auto& b) noexcept -> bool {
290 return a->distanceSqTo(position) < b->distanceSqTo(position);
291 });
292
293 return _envProbes;
294}
295
297 for (U16 i = 0u; i < Config::MAX_REFLECTIVE_PROBES_PER_PASS; ++i) {
298 if (!s_availableSlices[i]._locked) {
299 s_availableSlices[i]._available = true;
300 }
301 }
302
303 if (ProbesDirty()) {
304 GFX::BeginRenderPassCommand* renderPassCmd = GFX::EnqueueCommand<GFX::BeginRenderPassCommand>(bufferInOut);
305 renderPassCmd->_name = "DO_REFLECTION_PROBE_CLEAR";
306 renderPassCmd->_target = s_reflection._targetID;
310
311
312 GFX::EnqueueCommand<GFX::EndRenderPassCommand>(bufferInOut);
313 ProbesDirty(false);
314 }
315}
316
319
321 {
322
324
325 PipelineDescriptor pipelineDescriptor{};
326 pipelineDescriptor._stateBlock = context.get2DStateBlock();
327 pipelineDescriptor._shaderProgramHandle = s_lutComputeShader;
328 pipelineDescriptor._primitiveTopology = PrimitiveTopology::COMPUTE;
329
330 const Pipeline* pipelineCalcLut = context.newPipeline(pipelineDescriptor);
331
332 GFX::EnqueueCommand<GFX::BindPipelineCommand>(bufferInOut)->_pipeline = pipelineCalcLut;
333
335 auto cmd = GFX::EnqueueCommand<GFX::BindShaderResourcesCommand>(bufferInOut);
336 cmd->_usage = DescriptorSetUsage::PER_DRAW;
337
338 const ImageView targetView = Get(brdfLutTexture)->getView( TextureType::TEXTURE_2D, { 0u, 1u }, { 0u, 1u });
339
340 GFX::EnqueueCommand<GFX::MemoryBarrierCommand>( bufferInOut )->_textureLayoutChanges.emplace_back(TextureLayoutChange
341 {
342 ._targetView = targetView,
343 ._sourceLayout = ImageUsage::SHADER_READ,
344 ._targetLayout = ImageUsage::SHADER_WRITE
345 });
346
348 Set(binding._data, targetView, ImageUsage::SHADER_WRITE);
349
350 const U32 groupsX = to_U32(std::ceil(s_LUTTextureSize / to_F32(8)));
351 const U32 groupsY = to_U32(std::ceil(s_LUTTextureSize / to_F32(8)));
352 GFX::EnqueueCommand<GFX::DispatchComputeCommand>(bufferInOut)->_computeGroupSize = { groupsX, groupsY, 1 };
353
354 GFX::EnqueueCommand<GFX::MemoryBarrierCommand>( bufferInOut )->_textureLayoutChanges.emplace_back(TextureLayoutChange
355 {
356 ._targetView = targetView,
357 ._sourceLayout = ImageUsage::SHADER_WRITE,
358 ._targetLayout = ImageUsage::SHADER_READ
359 });
360
361 GFX::ComputeMipMapsCommand computeMipMapsCommand{};
362 computeMipMapsCommand._texture = brdfLutTexture;
363 computeMipMapsCommand._usage = ImageUsage::SHADER_READ;
364 GFX::EnqueueCommand( bufferInOut, computeMipMapsCommand );
365
366 s_lutTextureDirty = false;
367 }
368
369 if (SkyLightNeedsRefresh() && s_queuedLayer != SkyProbeLayerIndex())
370 {
371 PROFILE_SCOPE( "Upadate Sky Probe", Profiler::Category::Graphics );
372
373 GFX::EnqueueCommand<GFX::BeginDebugScopeCommand>(bufferInOut)->_scopeName = "SkyLight Pass";
374
375 RenderPassParams params = {};
376
379
383
386
389
390 context.generateCubeMap(params,
393 vec2<F32>(0.1f, 100.f),
394 bufferInOut,
395 memCmdInOut);
396
397
398 GFX::EnqueueCommand<GFX::EndDebugScopeCommand>(bufferInOut);
399
401
403 }
404 {
405 LockGuard<Mutex> w_lock(s_queueLock);
406 if (s_queuedStage == ComputationStages::COUNT && !s_computationQueue.empty())
407 {
408 s_queuedLayer = s_computationQueue.front();
409 s_queuedStage = ComputationStages::MIP_MAP_SOURCE;
410 s_computationQueue.pop();
411 s_computationSet.erase(s_queuedLayer);
412 }
413
414 while (s_queuedStage != ComputationStages::COUNT)
415 {
416 ProcessEnvironmentMapInternal(s_queuedLayer, s_queuedStage, bufferInOut);
417 if constexpr ( !s_AlwaysProcessFullProbeRefreshPerFrame )
418 {
419 break;
420 }
421 }
422 }
423 {
424 PROFILE_SCOPE( "Upadate Descriptor Sets", Profiler::Category::Graphics );
425
429
430 auto cmd = GFX::EnqueueCommand<GFX::BindShaderResourcesCommand>(bufferInOut);
431 cmd->_usage = DescriptorSetUsage::PER_FRAME;
432 {
434 Set( binding._data, prefiltered->texture(), prefiltered->_descriptor._sampler );
435 }
436 {
438 Set( binding._data, irradiance->texture(), irradiance->_descriptor._sampler );
439 }
440 {
442 Set( binding._data, brdfLut->texture(), brdfLut->_descriptor._sampler );
443 }
444 {
447 Set( binding._data, targetAtt->texture(), targetAtt->_descriptor._sampler );
448 }
449 }
450}
451
452void SceneEnvironmentProbePool::ProcessEnvironmentMap(const U16 layerID, [[maybe_unused]] const bool highPriority)
453{
454 LockGuard<Mutex> w_lock(s_queueLock);
455 if (s_computationSet.insert(layerID).second)
456 {
457 s_computationQueue.push(layerID);
458 }
459}
460
462{
464
465 // This entire sequence is based on this awesome blog post by Bruno Opsenica: https://bruop.github.io/ibl/
466 switch (stage)
467 {
469 {
470 PROFILE_SCOPE( "Generate Mipmaps", Profiler::Category::Graphics );
471
472 auto scopeCmd = GFX::EnqueueCommand<GFX::BeginDebugScopeCommand>(bufferInOut );
473 Util::StringFormat( scopeCmd->_scopeName, "Process environment map #{}-MipMapsSource", layerID);
475
476 GFX::ComputeMipMapsCommand computeMipMapsCommand = {};
477 computeMipMapsCommand._layerRange = { layerID, 1 };
478 computeMipMapsCommand._texture = sourceAtt->texture();
479 computeMipMapsCommand._usage = ImageUsage::SHADER_READ;
480 GFX::EnqueueCommand(bufferInOut, computeMipMapsCommand);
481
482 GFX::EnqueueCommand<GFX::EndDebugScopeCommand>(bufferInOut);
483
485 } break;
487 {
488 PrefilterEnvMap(layerID, bufferInOut);
490 } break;
492 {
493 ComputeIrradianceMap(layerID, bufferInOut);
495 s_queuedLayer = 0u;
496 } break;
499 break;
500
501 }
502}
503
505{
507
510 const ResourcePtr<Texture> sourceTex = Get(sourceAtt->texture());
511
512 auto scopeCmd = GFX::EnqueueCommand<GFX::BeginDebugScopeCommand>(bufferInOut);
513 Util::StringFormat( scopeCmd->_scopeName, "PreFilter environment map #{}", layerID);
514
515 GFX::EnqueueCommand<GFX::BindPipelineCommand>(bufferInOut)->_pipeline = s_pipelineCalcPrefiltered;
516
517 // width is the width/length of a single face of our cube map
518 const U16 width = sourceTex->width();
519 {
520 auto cmd = GFX::EnqueueCommand<GFX::BindShaderResourcesCommand>(bufferInOut);
521 cmd->_usage = DescriptorSetUsage::PER_DRAW;
523 Set( binding._data, sourceTex->getView(), sourceAtt->_descriptor._sampler );
524 }
525
526 ImageView destinationImage = Get(destinationAtt->texture())->getView(TextureType::TEXTURE_CUBE_ARRAY, { 0u, 1u }, { 0u , U16_MAX });
527
528 const F32 fWidth = to_F32(width);
529
530 PushConstantsStruct fastData{};
531 fastData.data[0]._vec[0].xyz.set(fWidth, fWidth, to_F32(layerID));
532
533 const F32 maxMipLevel = to_F32(std::log2(fWidth));
534 for (F32 mipLevel = 0u; mipLevel <= maxMipLevel; ++mipLevel) {
535 destinationImage._subRange._mipLevels = { to_U8(mipLevel), 1u };
536
537 const F32 roughness = mipLevel / maxMipLevel;
538 fastData.data[0]._vec[1].xy.set(mipLevel, roughness);
539 GFX::EnqueueCommand<GFX::SendPushConstantsCommand>(bufferInOut)->_fastData = fastData;
540 auto cmd = GFX::EnqueueCommand<GFX::BindShaderResourcesCommand>(bufferInOut);
541 cmd->_usage = DescriptorSetUsage::PER_DRAW;
542
543 GFX::EnqueueCommand<GFX::MemoryBarrierCommand>( bufferInOut )->_textureLayoutChanges.emplace_back(TextureLayoutChange
544 {
545 ._targetView = destinationImage,
546 ._sourceLayout = ImageUsage::SHADER_READ,
547 ._targetLayout = ImageUsage::SHADER_WRITE
548 });
549
551 Set(binding._data, destinationImage, ImageUsage::SHADER_WRITE);
552
553 // Dispatch enough groups to cover the entire _mipped_ face
554 const U16 mipWidth = width / to_U16(std::pow(2.f, mipLevel));
555 GFX::EnqueueCommand<GFX::DispatchComputeCommand>(bufferInOut)->_computeGroupSize = { std::max(1u, mipWidth / 8u), std::max(1u, mipWidth / 8u), 1 };
556
557 GFX::EnqueueCommand<GFX::MemoryBarrierCommand>( bufferInOut )->_textureLayoutChanges.emplace_back(TextureLayoutChange
558 {
559 ._targetView = destinationImage,
560 ._sourceLayout = ImageUsage::SHADER_WRITE,
561 ._targetLayout = ImageUsage::SHADER_READ
562 });
563 }
564
565 GFX::ComputeMipMapsCommand computeMipMapsCommand = {};
566 computeMipMapsCommand._layerRange = { layerID, 1 };
567 computeMipMapsCommand._texture = destinationAtt->texture();
568 computeMipMapsCommand._usage = ImageUsage::SHADER_READ;
569 GFX::EnqueueCommand(bufferInOut, computeMipMapsCommand);
570
571 GFX::EnqueueCommand<GFX::EndDebugScopeCommand>(bufferInOut);
572}
573
575{
577
580
581 auto scopeCmd = GFX::EnqueueCommand<GFX::BeginDebugScopeCommand>(bufferInOut);
582 Util::StringFormat( scopeCmd->_scopeName, "Compute Irradiance #{}", layerID);
583
584 GFX::EnqueueCommand<GFX::BindPipelineCommand>(bufferInOut)->_pipeline = s_pipelineCalcIrradiance;
585
586 ImageView destinationView = Get(destinationAtt->texture())->getView( TextureType::TEXTURE_CUBE_ARRAY, { 0u, 1u }, { 0u , U16_MAX });
587
588 GFX::EnqueueCommand<GFX::MemoryBarrierCommand>( bufferInOut )->_textureLayoutChanges.emplace_back( TextureLayoutChange
589 {
590 ._targetView = destinationView,
591 ._sourceLayout = ImageUsage::SHADER_READ,
592 ._targetLayout = ImageUsage::SHADER_WRITE
593 });
594
595 auto cmd = GFX::EnqueueCommand<GFX::BindShaderResourcesCommand>(bufferInOut);
596 cmd->_usage = DescriptorSetUsage::PER_DRAW;
597 {
599 Set( binding._data, sourceAtt->texture(), sourceAtt->_descriptor._sampler );
600 }
601 {
603 Set(binding._data, destinationView, ImageUsage::SHADER_WRITE );
604 }
605
606 PushConstantsStruct& fastData = GFX::EnqueueCommand<GFX::SendPushConstantsCommand>(bufferInOut)->_fastData;
607 fastData.data[0]._vec[0].xyz.set(to_F32(s_IrradianceTextureSize), to_F32(s_IrradianceTextureSize), to_F32(layerID));
608
609 const U32 groupsX = to_U32(std::ceil(s_IrradianceTextureSize / to_F32(8)));
610 const U32 groupsY = to_U32(std::ceil(s_IrradianceTextureSize / to_F32(8)));
611 GFX::EnqueueCommand<GFX::DispatchComputeCommand>(bufferInOut)->_computeGroupSize = { groupsX, groupsY, 1 };
612
613 GFX::EnqueueCommand<GFX::MemoryBarrierCommand>( bufferInOut )->_textureLayoutChanges.emplace_back( TextureLayoutChange
614 {
615 ._targetView = destinationView,
616 ._sourceLayout = ImageUsage::SHADER_WRITE,
617 ._targetLayout = ImageUsage::SHADER_READ
618 });
619
620 GFX::ComputeMipMapsCommand computeMipMapsCommand = {};
621 computeMipMapsCommand._layerRange = { layerID, 1 };
622 computeMipMapsCommand._texture = destinationAtt->texture();
623 computeMipMapsCommand._usage = ImageUsage::SHADER_READ;
624 GFX::EnqueueCommand(bufferInOut, computeMipMapsCommand);
625
626 GFX::EnqueueCommand<GFX::EndDebugScopeCommand>(bufferInOut);
627}
628
630{
631 _probeLock.lock();
632}
633
635{
636 _probeLock.unlock();
637}
638
640{
641 return _envProbes;
642}
643
645{
646 DebuggingSkyLight(false);
647
649
650 assert(_envProbes.size() < U16_MAX - 2u);
651 _envProbes.emplace_back(probe);
652 probe->poolIndex(to_U16(_envProbes.size() - 1u));
653}
654
656{
657 if (probe != nullptr) {
659 auto it = _envProbes.erase(eastl::remove_if(begin(_envProbes), end(_envProbes),
660 [probeGUID = probe->getGUID()](const auto& p) noexcept { return p->getGUID() == probeGUID; }),
661 end(_envProbes));
662 while (it != cend(_envProbes)) {
663 (*it)->poolIndex((*it)->poolIndex() - 1);
664 it++;
665 }
666 }
667
668 if (probe == _debugProbe)
669 {
670 _debugProbe = nullptr;
671 }
672}
673
674namespace
675{
676 constexpr I16 g_debugViewBase = 10;
677}
678
680 const bool enableSkyLightDebug = DebuggingSkyLight();
681 const bool enableProbeDebugging = _debugProbe != nullptr;
682 const I16 skyLightGroupID = g_debugViewBase + SkyProbeLayerIndex();
683 const I16 probeID = enableProbeDebugging ? g_debugViewBase + _debugProbe->rtLayerIndex() : -1;
684
685 bool addSkyLightViews = true, addProbeViews = true;
686 for (const DebugView_ptr& view : s_debugViews) {
687 if (view->_groupID == skyLightGroupID) {
688 addSkyLightViews = false;
689 view->_enabled = enableSkyLightDebug;
690 } else if (enableProbeDebugging && view->_groupID == probeID) {
691 addProbeViews = false;
692 view->_enabled = true;
693 } else {
694 view->_enabled = false;
695 }
696 }
697
698 if (enableSkyLightDebug && addSkyLightViews)
699 {
701 }
702 if (enableProbeDebugging && addProbeViews)
703 {
704 createDebugView(_debugProbe->rtLayerIndex());
705 }
706}
707
709{
710 for (U32 i = 0u; i < 18u; ++i)
711 {
712 DebugView_ptr& probeView = s_debugViews.emplace_back(std::make_shared<DebugView>(to_I16(I16_MAX - layerIndex - i)));
713 probeView->_cycleMips = true;
714
715 if (i > 11)
716 {
719 }
720 else if (i > 5)
721 {
724 }
725 else
726 {
729 }
730
731 probeView->_shader = s_previewShader;
732 probeView->_shaderData.set(_ID("layer"), PushConstantType::INT, layerIndex);
733 probeView->_shaderData.set(_ID("face"), PushConstantType::INT, i % 6u);
734 if (i > 11)
735 {
736 Util::StringFormat( probeView->_name, "Probe_{}_Filtered_face_{}", layerIndex, i % 6u );
737 }
738 else if (i > 5)
739 {
740 Util::StringFormat( probeView->_name, "Probe_{}_Irradiance_face_{}", layerIndex, i % 6u );
741 }
742 else
743 {
744 Util::StringFormat( probeView->_name, "Probe_{}_Reference_face_{}", layerIndex, i % 6u );
745 }
746
747 probeView->_groupID = g_debugViewBase + layerIndex;
748 probeView->_enabled = true;
749 parentScene().context().gfx().addDebugView(probeView);
750 }
751}
752
754{
756
757 const BoundingSphere& bSphere = node.get<BoundsComponent>()->getBoundingSphere();
758 lockProbeList();
759 const EnvironmentProbeList& probes = getLocked();
760 for (const auto& probe : probes)
761 {
762 if (probe->checkCollisionAndQueueUpdate(bSphere))
763 {
764 NOP();
765 }
766 }
767
768 unlockProbeList();
769 if (node.getNode().type() == SceneNodeType::TYPE_SKY) {
770 SkyLightNeedsRefresh(true);
771 }
772}
773
775{
777
778 probePool.lockProbeList();
779 const EnvironmentProbeList& probes = probePool.getLocked();
780 for (const auto& probe : probes)
781 {
782 if (probe->updateType() != EnvironmentProbeComponent::UpdateType::ONCE)
783 {
784 probe->dirty(true);
785 }
786 }
787 probePool.unlockProbeList();
788 SkyLightNeedsRefresh(true);
789}
790
792{
793 return s_debuggingSkyLight;
794}
795
796void SceneEnvironmentProbePool::DebuggingSkyLight(const bool state) noexcept
797{
798 s_debuggingSkyLight = state;
799}
800
802{
803 return s_skyLightNeedsRefresh || s_AlwaysRefreshSkyLight;
804}
805
807{
808 s_skyLightNeedsRefresh = state;
809}
810
812{
814}
815} //namespace Divide
#define NO_DESTROY
#define DIVIDE_UNEXPECTED_CALL()
#define NOP()
#define PROFILE_SCOPE_AUTO(CATEGORY)
Definition: Profiler.h:87
#define PROFILE_SCOPE(NAME, CATEGORY)
Definition: Profiler.h:86
Rough around the edges Adapter pattern abstracting the actual rendering API and access to the GPU.
Definition: GFXDevice.h:215
void generateCubeMap(RenderPassParams &params, U16 arrayOffset, const vec3< F32 > &pos, vec2< F32 > zPlanes, GFX::CommandBuffer &commandsInOut, GFX::MemoryBarrierCommand &memCmdInOut, mat4< F32 > *viewProjectionOut=nullptr)
Generate a cube texture and store it in the provided RenderTarget.
Definition: GFXDevice.cpp:1501
GFXRTPool & renderTargetPool() noexcept
Definition: GFXDevice.inl:133
Pipeline * newPipeline(const PipelineDescriptor &descriptor)
Create and return a new graphics pipeline. This is only used for caching and doesn't use the object a...
Definition: GFXDevice.cpp:3074
bool removeDebugView(DebugView *view)
Definition: GFXDevice.cpp:2770
const RenderStateBlock & get2DStateBlock() const noexcept
Definition: GFXDevice.inl:123
DebugView * addDebugView(const std::shared_ptr< DebugView > &view)
Definition: GFXDevice.cpp:2740
RenderTarget * getRenderTarget(const RenderTargetID target) const
Definition: GFXRTPool.cpp:50
RenderTargetHandle allocateRT(const RenderTargetDescriptor &descriptor)
Definition: GFXRTPool.cpp:17
bool deallocateRT(RenderTargetHandle &handle)
Definition: GFXRTPool.cpp:33
FORCE_INLINE I64 getGUID() const noexcept
Definition: GUIDWrapper.h:51
PlatformContext & context() noexcept
GFXDevice & gfx() noexcept
Configuration & config() noexcept
Handle< Texture > texture() const
RTAttachmentDescriptor _descriptor
Definition: RTAttachment.h:128
RTAttachment * getAttachment(RTAttachmentType type, RTColourAttachmentSlot slot=RTColourAttachmentSlot::SLOT_0) const
Scene & parentScene() noexcept
void onNodeUpdated(const SceneGraphNode &node) noexcept
static RenderTargetHandle ReflectionTarget() noexcept
static void UpdateSkyLight(GFXDevice &context, GFX::CommandBuffer &bufferInOut, GFX::MemoryBarrierCommand &memCmdInOut)
void registerProbe(EnvironmentProbeComponent *probe)
SceneEnvironmentProbePool(Scene &parentScene) noexcept
static std::array< ProbeSlice, Config::MAX_REFLECTIVE_PROBES_PER_PASS > s_availableSlices
static Handle< ShaderProgram > s_lutComputeShader
const EnvironmentProbeList & getLocked() const noexcept
static RenderTargetHandle BRDFLUTTarget() noexcept
const EnvironmentProbeList & sortAndGetLocked(const vec3< F32 > &position)
static void Prepare(GFX::CommandBuffer &bufferInOut)
static Handle< ShaderProgram > s_irradianceComputeShader
static Handle< ShaderProgram > s_previewShader
static RenderTargetHandle IrradianceTarget() noexcept
static void PrefilterEnvMap(const U16 layerID, GFX::CommandBuffer &bufferInOut)
static void ProcessEnvironmentMapInternal(const U16 layerID, ComputationStages &stage, GFX::CommandBuffer &bufferInOut)
static void OnStartup(GFXDevice &context)
static vector< DebugView_ptr > s_debugViews
static void ComputeIrradianceMap(const U16 layerID, GFX::CommandBuffer &bufferInOut)
static void OnTimeOfDayChange(const SceneEnvironmentProbePool &probePool) noexcept
static Handle< ShaderProgram > s_prefilterComputeShader
static RenderTargetHandle PrefilteredTarget() noexcept
static void OnShutdown(GFXDevice &context)
void unregisterProbe(const EnvironmentProbeComponent *probe)
static void UnlockSlice(U16 slice) noexcept
static void ProcessEnvironmentMap(U16 layerID, bool highPriority)
vec4< T > _vec[4]
Definition: MathMatrices.h:709
void set(const T *v) noexcept
set the 2 components of the vector manually using a source pointer to a (large enough) array
Definition: MathVectors.h:335
void set(const T *v) noexcept
set the 3 components of the vector manually using a source pointer to a (large enough) array
Definition: MathVectors.h:707
vec3< T > xyz
Definition: MathVectors.h:1374
constexpr bool IS_DEBUG_BUILD
Definition: config.h:55
constexpr U8 MAX_REFLECTIVE_NODES_IN_VIEW
Definition: config.h:135
constexpr U8 MAX_REFLECTIVE_PROBES_PER_PASS
Maximum number of environment probes we are allowed to update per frame.
Definition: config.h:141
FORCE_INLINE T * EnqueueCommand(CommandBuffer &buffer)
constexpr Optick::Category::Type GameLogic
Definition: Profiler.h:63
constexpr Optick::Category::Type Graphics
Definition: Profiler.h:60
Str StringFormat(const char *fmt, Args &&...args)
static SceneEnvironmentProbePool::ComputationStages s_queuedStage
Handle console commands that start with a forward slash.
Definition: AIProcessor.cpp:7
std::lock_guard< mutex > LockGuard
Definition: SharedMutex.h:55
constexpr U32 to_U32(const T value)
FORCE_INLINE void DestroyResource(Handle< T > &handle, const bool immediate=false)
static constexpr U32 RT_DEPTH_ATTACHMENT_IDX
Definition: RTAttachment.h:71
std::mutex Mutex
Definition: SharedMutex.h:40
constexpr U16 to_U16(const T value)
T * ResourcePtr
Definition: Resource.h:112
int16_t I16
constexpr F32 to_F32(const T value)
void AddImageUsageFlag(PropertyDescriptor< Texture > &descriptor, const ImageUsage usage) noexcept
eastl::vector< Type > vector
Definition: Vector.h:42
constexpr I16 I16_MAX
constexpr U16 U16_MAX
uint16_t U16
void Set(DescriptorSetBindingData &dataInOut, ShaderBuffer *buffer, const BufferRange range) noexcept
constexpr U64 _ID(const char *const str, const U64 value=val_64_const) noexcept
DescriptorSetBinding & AddBinding(DescriptorSet &setInOut, U8 slot, U16 stageVisibilityMask)
FORCE_INLINE Handle< T > CreateResource(const ResourceDescriptor< T > &descriptor, bool &wasInCache, std::atomic_uint &taskCounter)
constexpr U8 to_U8(const T value)
constexpr I16 to_I16(const T value)
RTClearEntry DEFAULT_CLEAR_ENTRY
vector< EnvironmentProbeComponent * > EnvironmentProbeList
static const vec3< F32 > VECTOR3_ZERO
Definition: MathVectors.h:1434
FORCE_INLINE T * Get(const Handle< T > handle)
uint32_t U32
constexpr auto to_base(const Type value) -> Type
struct Divide::Configuration::Rendering rendering
DescriptorSetBindingData _data
RTClearDescriptor _clearDescriptor
Definition: Commands.inl:97
ImageSubRange _subRange
RenderStateBlock _stateBlock
Definition: Pipeline.h:46
vector< ShaderModuleDescriptor > _modules
SamplerDescriptor _sampler
Definition: RTAttachment.h:64
RTClearDescriptor _clearDescriptorPrePass
RTDrawDescriptor _targetDescriptorPrePass
RTDrawDescriptor _targetDescriptorMainPass
RTClearDescriptor _clearDescriptorMainPass
InternalRTAttachmentDescriptors _attachments
Definition: RenderTarget.h:52
RenderTargetID _targetID
Definition: RenderTarget.h:47
static RenderTargetID REFLECTION_CUBE
Definition: GFXDevice.h:207
TextureMipSampling _mipSampling