|
|
@@ -3,7 +3,7 @@
|
|
|
// Code licensed under the BSD License.
|
|
|
// http://www.anki3d.org/LICENSE
|
|
|
|
|
|
-#include <anki/renderer/Indirect.h>
|
|
|
+#include <anki/renderer/ProbeReflections.h>
|
|
|
#include <anki/renderer/LightShading.h>
|
|
|
#include <anki/renderer/FinalComposite.h>
|
|
|
#include <anki/renderer/GBuffer.h>
|
|
|
@@ -16,23 +16,23 @@
|
|
|
namespace anki
|
|
|
{
|
|
|
|
|
|
-Indirect::Indirect(Renderer* r)
|
|
|
+ProbeReflections::ProbeReflections(Renderer* r)
|
|
|
: RendererObject(r)
|
|
|
, m_lightShading(r)
|
|
|
{
|
|
|
}
|
|
|
|
|
|
-Indirect::~Indirect()
|
|
|
+ProbeReflections::~ProbeReflections()
|
|
|
{
|
|
|
m_cacheEntries.destroy(getAllocator());
|
|
|
m_probeUuidToCacheEntryIdx.destroy(getAllocator());
|
|
|
}
|
|
|
|
|
|
-Error Indirect::init(const ConfigSet& config)
|
|
|
+Error ProbeReflections::init(const ConfigSet& config)
|
|
|
{
|
|
|
ANKI_R_LOGI("Initializing image reflections");
|
|
|
|
|
|
- Error err = initInternal(config);
|
|
|
+ const Error err = initInternal(config);
|
|
|
if(err)
|
|
|
{
|
|
|
ANKI_R_LOGE("Failed to initialize image reflections");
|
|
|
@@ -41,7 +41,7 @@ Error Indirect::init(const ConfigSet& config)
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
-Error Indirect::initInternal(const ConfigSet& config)
|
|
|
+Error ProbeReflections::initInternal(const ConfigSet& config)
|
|
|
{
|
|
|
// Init cache entries
|
|
|
m_cacheEntries.create(getAllocator(), config.getNumber("r.indirect.maxSimultaneousProbeCount"));
|
|
|
@@ -66,27 +66,30 @@ Error Indirect::initInternal(const ConfigSet& config)
|
|
|
return Error::NONE;
|
|
|
}
|
|
|
|
|
|
-Error Indirect::initGBuffer(const ConfigSet& config)
|
|
|
+Error ProbeReflections::initGBuffer(const ConfigSet& config)
|
|
|
{
|
|
|
m_gbuffer.m_tileSize = config.getNumber("r.indirect.reflectionResolution");
|
|
|
|
|
|
// Create RT descriptions
|
|
|
{
|
|
|
- RenderTargetDescription texinit = m_r->create2DRenderTargetDescription(
|
|
|
- m_gbuffer.m_tileSize * 6, m_gbuffer.m_tileSize, MS_COLOR_ATTACHMENT_PIXEL_FORMATS[0], "GI GBuffer");
|
|
|
+ RenderTargetDescription texinit = m_r->create2DRenderTargetDescription(m_gbuffer.m_tileSize * 6,
|
|
|
+ m_gbuffer.m_tileSize,
|
|
|
+ GBUFFER_COLOR_ATTACHMENT_PIXEL_FORMATS[0],
|
|
|
+ "CubeRefl GBuffer");
|
|
|
|
|
|
// Create color RT descriptions
|
|
|
for(U i = 0; i < GBUFFER_COLOR_ATTACHMENT_COUNT; ++i)
|
|
|
{
|
|
|
- texinit.m_format = MS_COLOR_ATTACHMENT_PIXEL_FORMATS[i];
|
|
|
+ texinit.m_format = GBUFFER_COLOR_ATTACHMENT_PIXEL_FORMATS[i];
|
|
|
m_gbuffer.m_colorRtDescrs[i] = texinit;
|
|
|
- m_gbuffer.m_colorRtDescrs[i].setName(StringAuto(getAllocator()).sprintf("GI GBuff Col #%u", i).toCString());
|
|
|
+ m_gbuffer.m_colorRtDescrs[i].setName(
|
|
|
+ StringAuto(getAllocator()).sprintf("CubeRefl GBuff Col #%u", i).toCString());
|
|
|
m_gbuffer.m_colorRtDescrs[i].bake();
|
|
|
}
|
|
|
|
|
|
// Create depth RT
|
|
|
texinit.m_format = GBUFFER_DEPTH_ATTACHMENT_PIXEL_FORMAT;
|
|
|
- texinit.setName("GI GBuff Depth");
|
|
|
+ texinit.setName("CubeRefl GBuff Depth");
|
|
|
m_gbuffer.m_depthRtDescr = texinit;
|
|
|
m_gbuffer.m_depthRtDescr.bake();
|
|
|
}
|
|
|
@@ -110,7 +113,7 @@ Error Indirect::initGBuffer(const ConfigSet& config)
|
|
|
return Error::NONE;
|
|
|
}
|
|
|
|
|
|
-Error Indirect::initLightShading(const ConfigSet& config)
|
|
|
+Error ProbeReflections::initLightShading(const ConfigSet& config)
|
|
|
{
|
|
|
m_lightShading.m_tileSize = config.getNumber("r.indirect.reflectionResolution");
|
|
|
m_lightShading.m_mipCount = computeMaxMipmapCount2d(m_lightShading.m_tileSize, m_lightShading.m_tileSize, 8);
|
|
|
@@ -121,8 +124,9 @@ Error Indirect::initLightShading(const ConfigSet& config)
|
|
|
m_lightShading.m_tileSize,
|
|
|
LIGHT_SHADING_COLOR_ATTACHMENT_PIXEL_FORMAT,
|
|
|
TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::SAMPLED_COMPUTE
|
|
|
- | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE | TextureUsageBit::GENERATE_MIPMAPS,
|
|
|
- "GI refl");
|
|
|
+ | TextureUsageBit::IMAGE_COMPUTE_READ_WRITE | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE
|
|
|
+ | TextureUsageBit::GENERATE_MIPMAPS,
|
|
|
+ "CubeRefl refl");
|
|
|
texinit.m_mipmapCount = m_lightShading.m_mipCount;
|
|
|
texinit.m_type = TextureType::CUBE_ARRAY;
|
|
|
texinit.m_layerCount = m_cacheEntries.getSize();
|
|
|
@@ -137,44 +141,39 @@ Error Indirect::initLightShading(const ConfigSet& config)
|
|
|
return Error::NONE;
|
|
|
}
|
|
|
|
|
|
-Error Indirect::initIrradiance(const ConfigSet& config)
|
|
|
+Error ProbeReflections::initIrradiance(const ConfigSet& config)
|
|
|
{
|
|
|
- // Init atlas
|
|
|
- {
|
|
|
- TextureInitInfo texinit = m_r->create2DRenderTargetInitInfo(m_irradiance.m_tileSize,
|
|
|
- m_irradiance.m_tileSize,
|
|
|
- LIGHT_SHADING_COLOR_ATTACHMENT_PIXEL_FORMAT,
|
|
|
- TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::SAMPLED_COMPUTE
|
|
|
- | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE,
|
|
|
- "GI irr");
|
|
|
-
|
|
|
- texinit.m_layerCount = m_cacheEntries.getSize();
|
|
|
- texinit.m_type = TextureType::CUBE_ARRAY;
|
|
|
- texinit.m_initialUsage = TextureUsageBit::SAMPLED_FRAGMENT;
|
|
|
-
|
|
|
- m_irradiance.m_cubeArr = m_r->createAndClearRenderTarget(texinit);
|
|
|
- }
|
|
|
+ m_irradiance.m_workgroupSize = config.getNumber("r.indirect.irradianceResolution");
|
|
|
|
|
|
// Create prog
|
|
|
{
|
|
|
- ANKI_CHECK(m_r->getResourceManager().loadResource("shaders/Irradiance.glslp", m_irradiance.m_prog));
|
|
|
+ ANKI_CHECK(m_r->getResourceManager().loadResource("shaders/IrradianceDice.glslp", m_irradiance.m_prog));
|
|
|
|
|
|
- const F32 envMapReadMip = computeMaxMipmapCount2d(
|
|
|
- m_lightShading.m_tileSize, m_lightShading.m_tileSize, m_irradiance.m_envMapReadSize);
|
|
|
+ ShaderProgramResourceConstantValueInitList<1> consts(m_irradiance.m_prog);
|
|
|
+ consts.add("WORKGROUP_SIZE", U32(m_irradiance.m_workgroupSize));
|
|
|
|
|
|
- ShaderProgramResourceConstantValueInitList<2> consts(m_irradiance.m_prog);
|
|
|
- consts.add("ENV_TEX_TILE_SIZE", U32(m_irradiance.m_envMapReadSize));
|
|
|
- consts.add("ENV_TEX_MIP", envMapReadMip);
|
|
|
+ ShaderProgramResourceMutationInitList<3> mutations(m_irradiance.m_prog);
|
|
|
+ mutations.add("LIGHT_SHADING_TEX", 1);
|
|
|
+ mutations.add("STORE_LOCATION", 1);
|
|
|
+ mutations.add("SECOND_BOUNCE", 0);
|
|
|
|
|
|
const ShaderProgramResourceVariant* variant;
|
|
|
- m_irradiance.m_prog->getOrCreateVariant(consts.get(), variant);
|
|
|
+ m_irradiance.m_prog->getOrCreateVariant(mutations.get(), consts.get(), variant);
|
|
|
m_irradiance.m_grProg = variant->getProgram();
|
|
|
}
|
|
|
|
|
|
+ // Create buff
|
|
|
+ {
|
|
|
+ BufferInitInfo init;
|
|
|
+ init.m_usage = BufferUsageBit::STORAGE_ALL;
|
|
|
+ init.m_size = 6 * sizeof(Vec4);
|
|
|
+ m_irradiance.m_diceValuesBuff = getGrManager().newBuffer(init);
|
|
|
+ }
|
|
|
+
|
|
|
return Error::NONE;
|
|
|
}
|
|
|
|
|
|
-Error Indirect::initIrradianceToRefl(const ConfigSet& cfg)
|
|
|
+Error ProbeReflections::initIrradianceToRefl(const ConfigSet& cfg)
|
|
|
{
|
|
|
// Create program
|
|
|
ANKI_CHECK(
|
|
|
@@ -187,14 +186,14 @@ Error Indirect::initIrradianceToRefl(const ConfigSet& cfg)
|
|
|
return Error::NONE;
|
|
|
}
|
|
|
|
|
|
-Error Indirect::initShadowMapping(const ConfigSet& cfg)
|
|
|
+Error ProbeReflections::initShadowMapping(const ConfigSet& cfg)
|
|
|
{
|
|
|
const U resolution = cfg.getNumber("r.indirect.shadowMapResolution");
|
|
|
ANKI_ASSERT(resolution > 8);
|
|
|
|
|
|
// RT descr
|
|
|
m_shadowMapping.m_rtDescr =
|
|
|
- m_r->create2DRenderTargetDescription(resolution * 6, resolution, Format::D32_SFLOAT, "GI SM");
|
|
|
+ m_r->create2DRenderTargetDescription(resolution * 6, resolution, Format::D32_SFLOAT, "CubeRefl SM");
|
|
|
m_shadowMapping.m_rtDescr.bake();
|
|
|
|
|
|
// FB descr
|
|
|
@@ -217,52 +216,29 @@ Error Indirect::initShadowMapping(const ConfigSet& cfg)
|
|
|
return Error::NONE;
|
|
|
}
|
|
|
|
|
|
-void Indirect::initCacheEntry(U32 cacheEntryIdx)
|
|
|
+void ProbeReflections::initCacheEntry(U32 cacheEntryIdx)
|
|
|
{
|
|
|
CacheEntry& cacheEntry = m_cacheEntries[cacheEntryIdx];
|
|
|
|
|
|
for(U faceIdx = 0; faceIdx < 6; ++faceIdx)
|
|
|
{
|
|
|
// Light pass FB
|
|
|
- {
|
|
|
- FramebufferDescription& fbDescr = cacheEntry.m_lightShadingFbDescrs[faceIdx];
|
|
|
- ANKI_ASSERT(!fbDescr.isBacked());
|
|
|
- fbDescr.m_colorAttachmentCount = 1;
|
|
|
- fbDescr.m_colorAttachments[0].m_surface.m_layer = cacheEntryIdx;
|
|
|
- fbDescr.m_colorAttachments[0].m_surface.m_face = faceIdx;
|
|
|
- fbDescr.m_colorAttachments[0].m_loadOperation = AttachmentLoadOperation::CLEAR;
|
|
|
- fbDescr.bake();
|
|
|
- }
|
|
|
-
|
|
|
- // Irradiance FB
|
|
|
- {
|
|
|
- FramebufferDescription& fbDescr = cacheEntry.m_irradianceFbDescrs[faceIdx];
|
|
|
- ANKI_ASSERT(!fbDescr.isBacked());
|
|
|
- fbDescr.m_colorAttachmentCount = 1;
|
|
|
- fbDescr.m_colorAttachments[0].m_surface.m_layer = cacheEntryIdx;
|
|
|
- fbDescr.m_colorAttachments[0].m_surface.m_face = faceIdx;
|
|
|
- fbDescr.m_colorAttachments[0].m_loadOperation = AttachmentLoadOperation::DONT_CARE;
|
|
|
- fbDescr.bake();
|
|
|
- }
|
|
|
-
|
|
|
- // Irradiance to Refl FB
|
|
|
- {
|
|
|
- FramebufferDescription& fbDescr = cacheEntry.m_irradianceToReflFbDescrs[faceIdx];
|
|
|
- ANKI_ASSERT(!fbDescr.isBacked());
|
|
|
- fbDescr.m_colorAttachmentCount = 1;
|
|
|
- fbDescr.m_colorAttachments[0].m_surface.m_layer = cacheEntryIdx;
|
|
|
- fbDescr.m_colorAttachments[0].m_surface.m_face = faceIdx;
|
|
|
- fbDescr.m_colorAttachments[0].m_loadOperation = AttachmentLoadOperation::LOAD;
|
|
|
- fbDescr.bake();
|
|
|
- }
|
|
|
+ FramebufferDescription& fbDescr = cacheEntry.m_lightShadingFbDescrs[faceIdx];
|
|
|
+ ANKI_ASSERT(!fbDescr.isBacked());
|
|
|
+ fbDescr.m_colorAttachmentCount = 1;
|
|
|
+ fbDescr.m_colorAttachments[0].m_surface.m_layer = cacheEntryIdx;
|
|
|
+ fbDescr.m_colorAttachments[0].m_surface.m_face = faceIdx;
|
|
|
+ fbDescr.m_colorAttachments[0].m_loadOperation = AttachmentLoadOperation::CLEAR;
|
|
|
+ fbDescr.bake();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-void Indirect::prepareProbes(
|
|
|
- RenderingContext& ctx, ReflectionProbeQueueElement*& probeToUpdate, U32& probeToUpdateCacheEntryIdx)
|
|
|
+void ProbeReflections::prepareProbes(RenderingContext& ctx,
|
|
|
+ ReflectionProbeQueueElement*& probeToUpdateThisFrame,
|
|
|
+ U32& probeToUpdateThisFrameCacheEntryIdx)
|
|
|
{
|
|
|
- probeToUpdate = nullptr;
|
|
|
- probeToUpdateCacheEntryIdx = MAX_U32;
|
|
|
+ probeToUpdateThisFrame = nullptr;
|
|
|
+ probeToUpdateThisFrameCacheEntryIdx = MAX_U32;
|
|
|
|
|
|
if(ANKI_UNLIKELY(ctx.m_renderQueue->m_reflectionProbes.getSize() == 0))
|
|
|
{
|
|
|
@@ -276,44 +252,55 @@ void Indirect::prepareProbes(
|
|
|
DynamicArray<ReflectionProbeQueueElement> newListOfProbes;
|
|
|
newListOfProbes.create(ctx.m_tempAllocator, ctx.m_renderQueue->m_reflectionProbes.getSize());
|
|
|
U newListOfProbeCount = 0;
|
|
|
-
|
|
|
- Bool foundProbeToRenderNextFrame = false;
|
|
|
+ Bool foundProbeToUpdateNextFrame = false;
|
|
|
for(U32 probeIdx = 0; probeIdx < ctx.m_renderQueue->m_reflectionProbes.getSize(); ++probeIdx)
|
|
|
{
|
|
|
ReflectionProbeQueueElement& probe = ctx.m_renderQueue->m_reflectionProbes[probeIdx];
|
|
|
|
|
|
// Find cache entry
|
|
|
- U32 cacheEntryIdx = MAX_U32;
|
|
|
- Bool cacheEntryFoundInCache;
|
|
|
- const Bool allocFailed = findBestCacheEntry(probe.m_uuid, cacheEntryIdx, cacheEntryFoundInCache);
|
|
|
- if(ANKI_UNLIKELY(allocFailed))
|
|
|
+ const U32 cacheEntryIdx = findBestCacheEntry(
|
|
|
+ probe.m_uuid, m_r->getGlobalTimestamp(), m_cacheEntries, m_probeUuidToCacheEntryIdx, getAllocator());
|
|
|
+ if(ANKI_UNLIKELY(cacheEntryIdx == MAX_U32))
|
|
|
{
|
|
|
+ // Failed
|
|
|
+ ANKI_R_LOGW("There is not enough space in the indirect lighting atlas for more probes. "
|
|
|
+ "Increase the r.indirect.maxSimultaneousProbeCount or decrease the scene's probes");
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
+ const Bool probeFoundInCache = m_cacheEntries[cacheEntryIdx].m_uuid == probe.m_uuid;
|
|
|
+
|
|
|
// Check if we _should_ and _can_ update the probe
|
|
|
- const Bool probeNeedsUpdate = m_cacheEntries[cacheEntryIdx].m_probeUuid != probe.m_uuid;
|
|
|
- if(ANKI_UNLIKELY(probeNeedsUpdate))
|
|
|
+ const Bool needsUpdate = !probeFoundInCache;
|
|
|
+ if(ANKI_UNLIKELY(needsUpdate))
|
|
|
{
|
|
|
- const Bool updateFailed = probeToUpdate != nullptr || probe.m_renderQueues[0] == nullptr;
|
|
|
+ const Bool canUpdateThisFrame = probeToUpdateThisFrame == nullptr && probe.m_renderQueues[0] != nullptr;
|
|
|
+ const Bool canUpdateNextFrame = !foundProbeToUpdateNextFrame;
|
|
|
|
|
|
- if(updateFailed && !foundProbeToRenderNextFrame)
|
|
|
+ if(!canUpdateThisFrame && canUpdateNextFrame)
|
|
|
{
|
|
|
// Probe will be updated next frame
|
|
|
- foundProbeToRenderNextFrame = true;
|
|
|
+ foundProbeToUpdateNextFrame = true;
|
|
|
probe.m_feedbackCallback(true, probe.m_userData);
|
|
|
+ continue;
|
|
|
}
|
|
|
-
|
|
|
- if(updateFailed)
|
|
|
+ else if(!canUpdateThisFrame)
|
|
|
{
|
|
|
+ // Can't be updated this frame so remove it from the list
|
|
|
continue;
|
|
|
}
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // Can be updated this frame so continue with it
|
|
|
+ probeToUpdateThisFrameCacheEntryIdx = cacheEntryIdx;
|
|
|
+ probeToUpdateThisFrame = &newListOfProbes[newListOfProbeCount];
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
// All good, can use this probe in this frame
|
|
|
|
|
|
// Update the cache entry
|
|
|
- m_cacheEntries[cacheEntryIdx].m_probeUuid = probe.m_uuid;
|
|
|
+ m_cacheEntries[cacheEntryIdx].m_uuid = probe.m_uuid;
|
|
|
m_cacheEntries[cacheEntryIdx].m_lastUsedTimestamp = m_r->getGlobalTimestamp();
|
|
|
|
|
|
// Update the probe
|
|
|
@@ -323,7 +310,7 @@ void Indirect::prepareProbes(
|
|
|
newListOfProbes[newListOfProbeCount++] = probe;
|
|
|
|
|
|
// Update cache map
|
|
|
- if(!cacheEntryFoundInCache)
|
|
|
+ if(!probeFoundInCache)
|
|
|
{
|
|
|
m_probeUuidToCacheEntryIdx.emplace(getAllocator(), probe.m_uuid, cacheEntryIdx);
|
|
|
}
|
|
|
@@ -333,15 +320,6 @@ void Indirect::prepareProbes(
|
|
|
{
|
|
|
probe.m_feedbackCallback(false, probe.m_userData);
|
|
|
}
|
|
|
-
|
|
|
- // Inform about the probe to update this frame
|
|
|
- if(probeNeedsUpdate)
|
|
|
- {
|
|
|
- ANKI_ASSERT(probe.m_renderQueues[0] != nullptr && probeToUpdate == nullptr);
|
|
|
-
|
|
|
- probeToUpdateCacheEntryIdx = cacheEntryIdx;
|
|
|
- probeToUpdate = &newListOfProbes[newListOfProbeCount - 1];
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
// Replace the probe list in the queue
|
|
|
@@ -359,44 +337,41 @@ void Indirect::prepareProbes(
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-void Indirect::runGBuffer(CommandBufferPtr& cmdb)
|
|
|
+void ProbeReflections::runGBuffer(U32 faceIdx, CommandBufferPtr& cmdb)
|
|
|
{
|
|
|
ANKI_ASSERT(m_ctx.m_probe);
|
|
|
- ANKI_TRACE_SCOPED_EVENT(R_IR);
|
|
|
+ ANKI_TRACE_SCOPED_EVENT(R_CUBE_REFL);
|
|
|
const ReflectionProbeQueueElement& probe = *m_ctx.m_probe;
|
|
|
|
|
|
- // For each face
|
|
|
- for(U faceIdx = 0; faceIdx < 6; ++faceIdx)
|
|
|
- {
|
|
|
- const U32 viewportX = faceIdx * m_gbuffer.m_tileSize;
|
|
|
- cmdb->setViewport(viewportX, 0, m_gbuffer.m_tileSize, m_gbuffer.m_tileSize);
|
|
|
- cmdb->setScissor(viewportX, 0, m_gbuffer.m_tileSize, m_gbuffer.m_tileSize);
|
|
|
+ const U32 viewportX = faceIdx * m_gbuffer.m_tileSize;
|
|
|
+ cmdb->setViewport(viewportX, 0, m_gbuffer.m_tileSize, m_gbuffer.m_tileSize);
|
|
|
+ cmdb->setScissor(viewportX, 0, m_gbuffer.m_tileSize, m_gbuffer.m_tileSize);
|
|
|
|
|
|
- /// Draw
|
|
|
- ANKI_ASSERT(probe.m_renderQueues[faceIdx]);
|
|
|
- const RenderQueue& rqueue = *probe.m_renderQueues[faceIdx];
|
|
|
+ // Draw
|
|
|
+ ANKI_ASSERT(probe.m_renderQueues[faceIdx]);
|
|
|
+ const RenderQueue& rqueue = *probe.m_renderQueues[faceIdx];
|
|
|
|
|
|
- if(!rqueue.m_renderables.isEmpty())
|
|
|
- {
|
|
|
- m_r->getSceneDrawer().drawRange(Pass::GB,
|
|
|
- rqueue.m_viewMatrix,
|
|
|
- rqueue.m_viewProjectionMatrix,
|
|
|
- Mat4::getIdentity(), // Don't care about prev mats
|
|
|
- cmdb,
|
|
|
- m_r->getSamplers().m_trilinearRepeatAniso,
|
|
|
- rqueue.m_renderables.getBegin(),
|
|
|
- rqueue.m_renderables.getEnd());
|
|
|
- }
|
|
|
+ if(!rqueue.m_renderables.isEmpty())
|
|
|
+ {
|
|
|
+ m_r->getSceneDrawer().drawRange(Pass::GB,
|
|
|
+ rqueue.m_viewMatrix,
|
|
|
+ rqueue.m_viewProjectionMatrix,
|
|
|
+ Mat4::getIdentity(), // Don't care about prev mats
|
|
|
+ cmdb,
|
|
|
+ m_r->getSamplers().m_trilinearRepeatAniso,
|
|
|
+ rqueue.m_renderables.getBegin(),
|
|
|
+ rqueue.m_renderables.getEnd(),
|
|
|
+ MAX_LOD_COUNT - 1);
|
|
|
}
|
|
|
|
|
|
// Restore state
|
|
|
cmdb->setScissor(0, 0, MAX_U32, MAX_U32);
|
|
|
}
|
|
|
|
|
|
-void Indirect::runLightShading(U32 faceIdx, RenderPassWorkContext& rgraphCtx)
|
|
|
+void ProbeReflections::runLightShading(U32 faceIdx, RenderPassWorkContext& rgraphCtx)
|
|
|
{
|
|
|
ANKI_ASSERT(faceIdx <= 6);
|
|
|
- ANKI_TRACE_SCOPED_EVENT(R_IR);
|
|
|
+ ANKI_TRACE_SCOPED_EVENT(R_CUBE_REFL);
|
|
|
|
|
|
CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
|
|
|
|
|
|
@@ -425,26 +400,32 @@ void Indirect::runLightShading(U32 faceIdx, RenderPassWorkContext& rgraphCtx)
|
|
|
rgraphCtx.bindTexture(0, 8, m_ctx.m_shadowMapRt, TextureSubresourceInfo(DepthStencilAspectBit::DEPTH));
|
|
|
}
|
|
|
|
|
|
- m_lightShading.m_deferred.drawLights(rqueue.m_viewProjectionMatrix,
|
|
|
- rqueue.m_viewProjectionMatrix.getInverse(),
|
|
|
- rqueue.m_cameraTransform.getTranslationPart(),
|
|
|
- UVec4(0, 0, m_lightShading.m_tileSize, m_lightShading.m_tileSize),
|
|
|
- Vec2(faceIdx * (1.0f / 6.0f), 0.0f),
|
|
|
- Vec2((faceIdx + 1) * (1.0f / 6.0f), 1.0f),
|
|
|
- probe.m_renderQueues[faceIdx]->m_cameraNear,
|
|
|
- probe.m_renderQueues[faceIdx]->m_cameraFar,
|
|
|
- (hasDirLight) ? &probe.m_renderQueues[faceIdx]->m_directionalLight : nullptr,
|
|
|
- rqueue.m_pointLights,
|
|
|
- rqueue.m_spotLights,
|
|
|
- cmdb);
|
|
|
+ TraditionalDeferredLightShadingDrawInfo dsInfo;
|
|
|
+ dsInfo.m_viewProjectionMatrix = rqueue.m_viewProjectionMatrix;
|
|
|
+ dsInfo.m_invViewProjectionMatrix = rqueue.m_viewProjectionMatrix.getInverse();
|
|
|
+ dsInfo.m_cameraPosWSpace = rqueue.m_cameraTransform.getTranslationPart();
|
|
|
+ dsInfo.m_viewport = UVec4(0, 0, m_lightShading.m_tileSize, m_lightShading.m_tileSize);
|
|
|
+ dsInfo.m_gbufferTexCoordsScale =
|
|
|
+ Vec2(1.0f / F32(m_lightShading.m_tileSize * 6), 1.0f / F32(m_lightShading.m_tileSize));
|
|
|
+ dsInfo.m_gbufferTexCoordsBias = Vec2(F32(faceIdx) * (1.0f / 6.0f), 0.0f);
|
|
|
+ dsInfo.m_lightbufferTexCoordsScale =
|
|
|
+ Vec2(1.0f / F32(m_lightShading.m_tileSize), 1.0f / F32(m_lightShading.m_tileSize));
|
|
|
+ dsInfo.m_lightbufferTexCoordsBias = Vec2(0.0f, 0.0f);
|
|
|
+ dsInfo.m_cameraNear = probe.m_renderQueues[faceIdx]->m_cameraNear;
|
|
|
+ dsInfo.m_cameraFar = probe.m_renderQueues[faceIdx]->m_cameraFar;
|
|
|
+ dsInfo.m_directionalLight = (hasDirLight) ? &probe.m_renderQueues[faceIdx]->m_directionalLight : nullptr;
|
|
|
+ dsInfo.m_pointLights = rqueue.m_pointLights;
|
|
|
+ dsInfo.m_spotLights = rqueue.m_spotLights;
|
|
|
+ dsInfo.m_commandBuffer = cmdb;
|
|
|
+ m_lightShading.m_deferred.drawLights(dsInfo);
|
|
|
}
|
|
|
|
|
|
-void Indirect::runMipmappingOfLightShading(U32 faceIdx, RenderPassWorkContext& rgraphCtx)
|
|
|
+void ProbeReflections::runMipmappingOfLightShading(U32 faceIdx, RenderPassWorkContext& rgraphCtx)
|
|
|
{
|
|
|
ANKI_ASSERT(faceIdx < 6);
|
|
|
ANKI_ASSERT(m_ctx.m_cacheEntryIdx < m_cacheEntries.getSize());
|
|
|
|
|
|
- ANKI_TRACE_SCOPED_EVENT(R_IR);
|
|
|
+ ANKI_TRACE_SCOPED_EVENT(R_CUBE_REFL);
|
|
|
|
|
|
TextureSubresourceInfo subresource(TextureSurfaceInfo(0, 0, faceIdx, m_ctx.m_cacheEntryIdx));
|
|
|
subresource.m_mipmapCount = m_lightShading.m_mipCount;
|
|
|
@@ -457,76 +438,64 @@ void Indirect::runMipmappingOfLightShading(U32 faceIdx, RenderPassWorkContext& r
|
|
|
rgraphCtx.m_commandBuffer->generateMipmaps2d(getGrManager().newTextureView(viewInit));
|
|
|
}
|
|
|
|
|
|
-void Indirect::runIrradiance(U32 faceIdx, RenderPassWorkContext& rgraphCtx)
|
|
|
+void ProbeReflections::runIrradiance(RenderPassWorkContext& rgraphCtx)
|
|
|
{
|
|
|
- ANKI_ASSERT(faceIdx < 6);
|
|
|
- ANKI_TRACE_SCOPED_EVENT(R_IR);
|
|
|
+ ANKI_TRACE_SCOPED_EVENT(R_CUBE_REFL);
|
|
|
const U32 cacheEntryIdx = m_ctx.m_cacheEntryIdx;
|
|
|
ANKI_ASSERT(cacheEntryIdx < m_cacheEntries.getSize());
|
|
|
|
|
|
CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
|
|
|
|
|
|
- // Set state
|
|
|
- cmdb->setViewport(0, 0, m_irradiance.m_tileSize, m_irradiance.m_tileSize);
|
|
|
cmdb->bindShaderProgram(m_irradiance.m_grProg);
|
|
|
|
|
|
- cmdb->bindSampler(0, 0, m_r->getSamplers().m_trilinearClamp);
|
|
|
+ // Bind stuff
|
|
|
+ cmdb->bindSampler(0, 0, m_r->getSamplers().m_nearestNearestClamp);
|
|
|
|
|
|
TextureSubresourceInfo subresource;
|
|
|
subresource.m_faceCount = 6;
|
|
|
subresource.m_firstLayer = cacheEntryIdx;
|
|
|
rgraphCtx.bindTexture(0, 1, m_ctx.m_lightShadingRt, subresource);
|
|
|
|
|
|
- // Set uniforms
|
|
|
- UVec4 pushConsts(faceIdx);
|
|
|
- cmdb->setPushConstants(&pushConsts, sizeof(pushConsts));
|
|
|
+ allocateAndBindStorage<void*>(
|
|
|
+ sizeof(Vec4) * 6 * m_irradiance.m_workgroupSize * m_irradiance.m_workgroupSize, cmdb, 0, 3);
|
|
|
+
|
|
|
+ cmdb->bindStorageBuffer(0, 4, m_irradiance.m_diceValuesBuff, 0, m_irradiance.m_diceValuesBuff->getSize());
|
|
|
|
|
|
// Draw
|
|
|
- drawQuad(cmdb);
|
|
|
+ cmdb->dispatchCompute(1, 1, 1);
|
|
|
}
|
|
|
|
|
|
-void Indirect::runIrradianceToRefl(U32 faceIdx, RenderPassWorkContext& rgraphCtx)
|
|
|
+void ProbeReflections::runIrradianceToRefl(RenderPassWorkContext& rgraphCtx)
|
|
|
{
|
|
|
- ANKI_ASSERT(faceIdx < 6);
|
|
|
- ANKI_TRACE_SCOPED_EVENT(R_IR);
|
|
|
+ ANKI_TRACE_SCOPED_EVENT(R_CUBE_REFL);
|
|
|
|
|
|
const U32 cacheEntryIdx = m_ctx.m_cacheEntryIdx;
|
|
|
ANKI_ASSERT(cacheEntryIdx < m_cacheEntries.getSize());
|
|
|
|
|
|
CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
|
|
|
|
|
|
- // Set state
|
|
|
- cmdb->setViewport(0, 0, m_lightShading.m_tileSize, m_lightShading.m_tileSize);
|
|
|
- cmdb->setBlendFactors(0, BlendFactor::ONE, BlendFactor::ONE);
|
|
|
-
|
|
|
cmdb->bindShaderProgram(m_irradianceToRefl.m_grProg);
|
|
|
|
|
|
// Bind resources
|
|
|
cmdb->bindSampler(0, 0, m_r->getSamplers().m_nearestNearestClamp);
|
|
|
- cmdb->bindSampler(0, 1, m_r->getSamplers().m_trilinearClamp);
|
|
|
|
|
|
- rgraphCtx.bindColorTexture(0, 2, m_ctx.m_gbufferColorRts[0]);
|
|
|
- rgraphCtx.bindColorTexture(0, 3, m_ctx.m_gbufferColorRts[1]);
|
|
|
- rgraphCtx.bindColorTexture(0, 4, m_ctx.m_gbufferColorRts[2]);
|
|
|
+ rgraphCtx.bindColorTexture(0, 1, m_ctx.m_gbufferColorRts[0], 0);
|
|
|
+ rgraphCtx.bindColorTexture(0, 1, m_ctx.m_gbufferColorRts[1], 1);
|
|
|
+ rgraphCtx.bindColorTexture(0, 1, m_ctx.m_gbufferColorRts[2], 2);
|
|
|
+
|
|
|
+ cmdb->bindStorageBuffer(0, 2, m_irradiance.m_diceValuesBuff, 0, m_irradiance.m_diceValuesBuff->getSize());
|
|
|
|
|
|
TextureSubresourceInfo subresource;
|
|
|
subresource.m_faceCount = 6;
|
|
|
subresource.m_firstLayer = cacheEntryIdx;
|
|
|
- rgraphCtx.bindTexture(0, 5, m_ctx.m_irradianceRt, subresource);
|
|
|
-
|
|
|
- Vec4 pushConsts(faceIdx);
|
|
|
- cmdb->setPushConstants(&pushConsts, sizeof(pushConsts));
|
|
|
-
|
|
|
- // Draw
|
|
|
- drawQuad(cmdb);
|
|
|
+ rgraphCtx.bindImage(0, 3, m_ctx.m_lightShadingRt, subresource);
|
|
|
|
|
|
- // Restore state
|
|
|
- cmdb->setBlendFactors(0, BlendFactor::ONE, BlendFactor::ZERO);
|
|
|
+ dispatchPPCompute(cmdb, 8, 8, m_lightShading.m_tileSize, m_lightShading.m_tileSize);
|
|
|
}
|
|
|
|
|
|
-void Indirect::populateRenderGraph(RenderingContext& rctx)
|
|
|
+void ProbeReflections::populateRenderGraph(RenderingContext& rctx)
|
|
|
{
|
|
|
- ANKI_TRACE_SCOPED_EVENT(R_IR);
|
|
|
+ ANKI_TRACE_SCOPED_EVENT(R_CUBE_REFL);
|
|
|
|
|
|
#if ANKI_EXTRA_CHECKS
|
|
|
m_ctx = {};
|
|
|
@@ -544,8 +513,6 @@ void Indirect::populateRenderGraph(RenderingContext& rctx)
|
|
|
// Just import and exit
|
|
|
|
|
|
m_ctx.m_lightShadingRt = rgraph.importRenderTarget(m_lightShading.m_cubeArr, TextureUsageBit::SAMPLED_FRAGMENT);
|
|
|
- m_ctx.m_irradianceRt = rgraph.importRenderTarget(m_irradiance.m_cubeArr, TextureUsageBit::SAMPLED_FRAGMENT);
|
|
|
-
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
@@ -569,14 +536,15 @@ void Indirect::populateRenderGraph(RenderingContext& rctx)
|
|
|
m_ctx.m_gbufferDepthRt = rgraph.newRenderTarget(m_gbuffer.m_depthRtDescr);
|
|
|
|
|
|
// Pass
|
|
|
- GraphicsRenderPassDescription& pass = rgraph.newGraphicsRenderPass("GI gbuff");
|
|
|
+ GraphicsRenderPassDescription& pass = rgraph.newGraphicsRenderPass("CubeRefl gbuff");
|
|
|
pass.setFramebufferInfo(m_gbuffer.m_fbDescr, rts, m_ctx.m_gbufferDepthRt);
|
|
|
pass.setWork(
|
|
|
[](RenderPassWorkContext& rgraphCtx) {
|
|
|
- static_cast<Indirect*>(rgraphCtx.m_userData)->runGBuffer(rgraphCtx.m_commandBuffer);
|
|
|
+ static_cast<ProbeReflections*>(rgraphCtx.m_userData)
|
|
|
+ ->runGBuffer(rgraphCtx.m_currentSecondLevelCommandBufferIndex, rgraphCtx.m_commandBuffer);
|
|
|
},
|
|
|
this,
|
|
|
- 0);
|
|
|
+ 6);
|
|
|
|
|
|
for(U i = 0; i < GBUFFER_COLOR_ATTACHMENT_COUNT; ++i)
|
|
|
{
|
|
|
@@ -626,14 +594,15 @@ void Indirect::populateRenderGraph(RenderingContext& rctx)
|
|
|
m_ctx.m_shadowMapRt = rgraph.newRenderTarget(m_shadowMapping.m_rtDescr);
|
|
|
|
|
|
// Pass
|
|
|
- GraphicsRenderPassDescription& pass = rgraph.newGraphicsRenderPass("GI SM");
|
|
|
+ GraphicsRenderPassDescription& pass = rgraph.newGraphicsRenderPass("CubeRefl SM");
|
|
|
pass.setFramebufferInfo(m_shadowMapping.m_fbDescr, {}, m_ctx.m_shadowMapRt);
|
|
|
pass.setWork(
|
|
|
[](RenderPassWorkContext& rgraphCtx) {
|
|
|
- static_cast<Indirect*>(rgraphCtx.m_userData)->runShadowMapping(rgraphCtx.m_commandBuffer);
|
|
|
+ static_cast<ProbeReflections*>(rgraphCtx.m_userData)
|
|
|
+ ->runShadowMapping(rgraphCtx.m_currentSecondLevelCommandBufferIndex, rgraphCtx.m_commandBuffer);
|
|
|
},
|
|
|
this,
|
|
|
- 0);
|
|
|
+ 6);
|
|
|
|
|
|
TextureSubresourceInfo subresource(DepthStencilAspectBit::DEPTH);
|
|
|
pass.newDependency({m_ctx.m_shadowMapRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE, subresource});
|
|
|
@@ -656,12 +625,12 @@ void Indirect::populateRenderGraph(RenderingContext& rctx)
|
|
|
m_ctx.m_lightShadingRt = rgraph.importRenderTarget(m_lightShading.m_cubeArr, TextureUsageBit::SAMPLED_FRAGMENT);
|
|
|
|
|
|
// Passes
|
|
|
- static const Array<CString, 6> passNames = {{"GI LightShad #0",
|
|
|
- "GI LightShad #1",
|
|
|
- "GI LightShad #2",
|
|
|
- "GI LightShad #3",
|
|
|
- "GI LightShad #4",
|
|
|
- "GI LightShad #5"}};
|
|
|
+ static const Array<CString, 6> passNames = {{"CubeRefl LightShad #0",
|
|
|
+ "CubeRefl LightShad #1",
|
|
|
+ "CubeRefl LightShad #2",
|
|
|
+ "CubeRefl LightShad #3",
|
|
|
+ "CubeRefl LightShad #4",
|
|
|
+ "CubeRefl LightShad #5"}};
|
|
|
for(U faceIdx = 0; faceIdx < 6; ++faceIdx)
|
|
|
{
|
|
|
GraphicsRenderPassDescription& pass = rgraph.newGraphicsRenderPass(passNames[faceIdx]);
|
|
|
@@ -690,109 +659,49 @@ void Indirect::populateRenderGraph(RenderingContext& rctx)
|
|
|
|
|
|
// Irradiance passes
|
|
|
{
|
|
|
- static const Array<RenderPassWorkCallback, 6> callbacks = {{runIrradianceCallback<0>,
|
|
|
- runIrradianceCallback<1>,
|
|
|
- runIrradianceCallback<2>,
|
|
|
- runIrradianceCallback<3>,
|
|
|
- runIrradianceCallback<4>,
|
|
|
- runIrradianceCallback<5>}};
|
|
|
-
|
|
|
- // Rt
|
|
|
- m_ctx.m_irradianceRt = rgraph.importRenderTarget(m_irradiance.m_cubeArr, TextureUsageBit::SAMPLED_FRAGMENT);
|
|
|
-
|
|
|
- static const Array<CString, 6> passNames = {
|
|
|
- {"GI Irr/ce #0", "GI Irr/ce #1", "GI Irr/ce #2", "GI Irr/ce #3", "GI Irr/ce #4", "GI Irr/ce #5"}};
|
|
|
- for(U faceIdx = 0; faceIdx < 6; ++faceIdx)
|
|
|
- {
|
|
|
- GraphicsRenderPassDescription& pass = rgraph.newGraphicsRenderPass(passNames[faceIdx]);
|
|
|
+ m_ctx.m_irradianceDiceValuesBuffHandle =
|
|
|
+ rgraph.importBuffer(m_irradiance.m_diceValuesBuff, BufferUsageBit::NONE);
|
|
|
|
|
|
- pass.setFramebufferInfo(
|
|
|
- m_cacheEntries[probeToUpdateCacheEntryIdx].m_irradianceFbDescrs[faceIdx], {{m_ctx.m_irradianceRt}}, {});
|
|
|
+ ComputeRenderPassDescription& pass = rgraph.newComputeRenderPass("CubeRefl Irradiance");
|
|
|
|
|
|
- pass.setWork(callbacks[faceIdx], this, 0);
|
|
|
+ pass.setWork(
|
|
|
+ [](RenderPassWorkContext& rgraphCtx) {
|
|
|
+ static_cast<ProbeReflections*>(rgraphCtx.m_userData)->runIrradiance(rgraphCtx);
|
|
|
+ },
|
|
|
+ this,
|
|
|
+ 0);
|
|
|
|
|
|
- // Read a cube but only one layer and level
|
|
|
- TextureSubresourceInfo readSubresource;
|
|
|
- readSubresource.m_faceCount = 6;
|
|
|
- readSubresource.m_firstLayer = probeToUpdateCacheEntryIdx;
|
|
|
- pass.newDependency({m_ctx.m_lightShadingRt, TextureUsageBit::SAMPLED_FRAGMENT, readSubresource});
|
|
|
+ // Read a cube but only one layer and level
|
|
|
+ TextureSubresourceInfo readSubresource;
|
|
|
+ readSubresource.m_faceCount = 6;
|
|
|
+ readSubresource.m_firstLayer = probeToUpdateCacheEntryIdx;
|
|
|
+ pass.newDependency({m_ctx.m_lightShadingRt, TextureUsageBit::SAMPLED_COMPUTE, readSubresource});
|
|
|
|
|
|
- TextureSubresourceInfo writeSubresource(TextureSurfaceInfo(0, 0, faceIdx, probeToUpdateCacheEntryIdx));
|
|
|
- pass.newDependency({m_ctx.m_irradianceRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE, writeSubresource});
|
|
|
- }
|
|
|
+ pass.newDependency({m_ctx.m_irradianceDiceValuesBuffHandle, BufferUsageBit::STORAGE_COMPUTE_WRITE});
|
|
|
}
|
|
|
|
|
|
// Write irradiance back to refl
|
|
|
{
|
|
|
- static const Array<RenderPassWorkCallback, 6> callbacks = {{runIrradianceToReflCallback<0>,
|
|
|
- runIrradianceToReflCallback<1>,
|
|
|
- runIrradianceToReflCallback<2>,
|
|
|
- runIrradianceToReflCallback<3>,
|
|
|
- runIrradianceToReflCallback<4>,
|
|
|
- runIrradianceToReflCallback<5>}};
|
|
|
-
|
|
|
- // Rt
|
|
|
- static const Array<CString, 6> passNames = {{"GI Irr2Refl #0",
|
|
|
- "GI Irr2Refl #1",
|
|
|
- "GI Irr2Refl #2",
|
|
|
- "GI Irr2Refl #3",
|
|
|
- "GI Irr2Refl #4",
|
|
|
- "GI Irr2Refl #5"}};
|
|
|
- for(U faceIdx = 0; faceIdx < 6; ++faceIdx)
|
|
|
- {
|
|
|
- GraphicsRenderPassDescription& pass = rgraph.newGraphicsRenderPass(passNames[faceIdx]);
|
|
|
-
|
|
|
- pass.setFramebufferInfo(m_cacheEntries[probeToUpdateCacheEntryIdx].m_irradianceToReflFbDescrs[faceIdx],
|
|
|
- {{m_ctx.m_lightShadingRt}},
|
|
|
- {});
|
|
|
-
|
|
|
- pass.setWork(callbacks[faceIdx], this, 0);
|
|
|
-
|
|
|
- for(U i = 0; i < GBUFFER_COLOR_ATTACHMENT_COUNT; ++i)
|
|
|
- {
|
|
|
- pass.newDependency({m_ctx.m_gbufferColorRts[i], TextureUsageBit::SAMPLED_FRAGMENT});
|
|
|
- }
|
|
|
-
|
|
|
- TextureSubresourceInfo readSubresource;
|
|
|
- readSubresource.m_faceCount = 6;
|
|
|
- readSubresource.m_firstLayer = probeToUpdateCacheEntryIdx;
|
|
|
- pass.newDependency({m_ctx.m_irradianceRt, TextureUsageBit::SAMPLED_FRAGMENT, readSubresource});
|
|
|
+ ComputeRenderPassDescription& pass = rgraph.newComputeRenderPass("CubeRefl apply indirect");
|
|
|
|
|
|
- TextureSubresourceInfo writeSubresource(TextureSurfaceInfo(0, 0, faceIdx, probeToUpdateCacheEntryIdx));
|
|
|
- pass.newDependency(
|
|
|
- {m_ctx.m_lightShadingRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE, writeSubresource});
|
|
|
- }
|
|
|
- }
|
|
|
+ pass.setWork(
|
|
|
+ [](RenderPassWorkContext& rgraphCtx) {
|
|
|
+ static_cast<ProbeReflections*>(rgraphCtx.m_userData)->runIrradianceToRefl(rgraphCtx);
|
|
|
+ },
|
|
|
+ this,
|
|
|
+ 0);
|
|
|
|
|
|
- // Irradiance passes 2nd bounce
|
|
|
- {
|
|
|
- static const Array<RenderPassWorkCallback, 6> callbacks = {{runIrradianceCallback<0>,
|
|
|
- runIrradianceCallback<1>,
|
|
|
- runIrradianceCallback<2>,
|
|
|
- runIrradianceCallback<3>,
|
|
|
- runIrradianceCallback<4>,
|
|
|
- runIrradianceCallback<5>}};
|
|
|
-
|
|
|
- static const Array<CString, 6> passNames = {
|
|
|
- {"GI Irr 2nd #0", "GI Irr 2nd #1", "GI Irr 2nd #2", "GI Irr 2nd #3", "GI Irr 2nd #4", "GI Irr 2nd #5"}};
|
|
|
- for(U faceIdx = 0; faceIdx < 6; ++faceIdx)
|
|
|
+ for(U i = 0; i < GBUFFER_COLOR_ATTACHMENT_COUNT - 1; ++i)
|
|
|
{
|
|
|
- GraphicsRenderPassDescription& pass = rgraph.newGraphicsRenderPass(passNames[faceIdx]);
|
|
|
-
|
|
|
- pass.setFramebufferInfo(
|
|
|
- m_cacheEntries[probeToUpdateCacheEntryIdx].m_irradianceFbDescrs[faceIdx], {{m_ctx.m_irradianceRt}}, {});
|
|
|
-
|
|
|
- pass.setWork(callbacks[faceIdx], this, 0);
|
|
|
+ pass.newDependency({m_ctx.m_gbufferColorRts[i], TextureUsageBit::SAMPLED_COMPUTE});
|
|
|
+ }
|
|
|
|
|
|
- // Read a cube but only one layer and level
|
|
|
- TextureSubresourceInfo readSubresource;
|
|
|
- readSubresource.m_faceCount = 6;
|
|
|
- readSubresource.m_firstLayer = probeToUpdateCacheEntryIdx;
|
|
|
- pass.newDependency({m_ctx.m_lightShadingRt, TextureUsageBit::SAMPLED_FRAGMENT, readSubresource});
|
|
|
+ TextureSubresourceInfo subresource;
|
|
|
+ subresource.m_faceCount = 6;
|
|
|
+ subresource.m_firstLayer = probeToUpdateCacheEntryIdx;
|
|
|
+ pass.newDependency({m_ctx.m_lightShadingRt, TextureUsageBit::IMAGE_COMPUTE_READ_WRITE, subresource});
|
|
|
|
|
|
- TextureSubresourceInfo writeSubresource(TextureSurfaceInfo(0, 0, faceIdx, probeToUpdateCacheEntryIdx));
|
|
|
- pass.newDependency({m_ctx.m_irradianceRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE, writeSubresource});
|
|
|
- }
|
|
|
+ pass.newDependency({m_ctx.m_irradianceDiceValuesBuffHandle, BufferUsageBit::STORAGE_COMPUTE_READ});
|
|
|
}
|
|
|
|
|
|
// Mipmapping "passes"
|
|
|
@@ -804,8 +713,12 @@ void Indirect::populateRenderGraph(RenderingContext& rctx)
|
|
|
runMipmappingOfLightShadingCallback<4>,
|
|
|
runMipmappingOfLightShadingCallback<5>}};
|
|
|
|
|
|
- static const Array<CString, 6> passNames = {
|
|
|
- {"GI Mip #0", "GI Mip #1", "GI Mip #2", "GI Mip #3", "GI Mip #4", "GI Mip #5"}};
|
|
|
+ static const Array<CString, 6> passNames = {{"CubeRefl Mip #0",
|
|
|
+ "CubeRefl Mip #1",
|
|
|
+ "CubeRefl Mip #2",
|
|
|
+ "CubeRefl Mip #3",
|
|
|
+ "CubeRefl Mip #4",
|
|
|
+ "CubeRefl Mip #5"}};
|
|
|
for(U faceIdx = 0; faceIdx < 6; ++faceIdx)
|
|
|
{
|
|
|
GraphicsRenderPassDescription& pass = rgraph.newGraphicsRenderPass(passNames[faceIdx]);
|
|
|
@@ -819,104 +732,37 @@ void Indirect::populateRenderGraph(RenderingContext& rctx)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-Bool Indirect::findBestCacheEntry(U64 probeUuid, U32& cacheEntryIdxAllocated, Bool& cacheEntryFound)
|
|
|
+void ProbeReflections::runShadowMapping(U32 faceIdx, CommandBufferPtr& cmdb)
|
|
|
{
|
|
|
- ANKI_ASSERT(probeUuid > 0);
|
|
|
+ cmdb->setPolygonOffset(1.0f, 1.0f);
|
|
|
|
|
|
- // First, try to see if the probe is in the cache
|
|
|
- auto it = m_probeUuidToCacheEntryIdx.find(probeUuid);
|
|
|
- if(it != m_probeUuidToCacheEntryIdx.getEnd())
|
|
|
- {
|
|
|
- const U32 cacheEntryIdx = *it;
|
|
|
- if(m_cacheEntries[cacheEntryIdx].m_probeUuid == probeUuid)
|
|
|
- {
|
|
|
- // Found it
|
|
|
- cacheEntryIdxAllocated = cacheEntryIdx;
|
|
|
- cacheEntryFound = true;
|
|
|
- return false;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- // Cache entry is wrong, remove it
|
|
|
- m_probeUuidToCacheEntryIdx.erase(getAllocator(), it);
|
|
|
- }
|
|
|
- }
|
|
|
- cacheEntryFound = false;
|
|
|
+ ANKI_ASSERT(m_ctx.m_probe);
|
|
|
+ ANKI_ASSERT(m_ctx.m_probe->m_renderQueues[faceIdx]);
|
|
|
+ const RenderQueue& faceRenderQueue = *m_ctx.m_probe->m_renderQueues[faceIdx];
|
|
|
+ ANKI_ASSERT(faceRenderQueue.m_directionalLight.m_uuid != 0);
|
|
|
+ ANKI_ASSERT(faceRenderQueue.m_directionalLight.m_shadowCascadeCount == 1);
|
|
|
|
|
|
- // 2nd and 3rd choice, find an empty entry or some entry to re-use
|
|
|
- U32 emptyCacheEntryIdx = MAX_U32;
|
|
|
- U32 cacheEntryIdxToKick = MAX_U32;
|
|
|
- Timestamp cacheEntryIdxToKickMinTimestamp = MAX_TIMESTAMP;
|
|
|
- for(U32 cacheEntryIdx = 0; cacheEntryIdx < m_cacheEntries.getSize(); ++cacheEntryIdx)
|
|
|
- {
|
|
|
- if(m_cacheEntries[cacheEntryIdx].m_probeUuid == 0)
|
|
|
- {
|
|
|
- // Found an empty
|
|
|
- emptyCacheEntryIdx = cacheEntryIdx;
|
|
|
- break;
|
|
|
- }
|
|
|
- else if(m_cacheEntries[cacheEntryIdx].m_lastUsedTimestamp != m_r->getGlobalTimestamp()
|
|
|
- && m_cacheEntries[cacheEntryIdx].m_lastUsedTimestamp < cacheEntryIdxToKickMinTimestamp)
|
|
|
- {
|
|
|
- // Found some with low timestamp
|
|
|
- cacheEntryIdxToKick = cacheEntryIdx;
|
|
|
- cacheEntryIdxToKickMinTimestamp = m_cacheEntries[cacheEntryIdx].m_lastUsedTimestamp;
|
|
|
- }
|
|
|
- }
|
|
|
+ ANKI_ASSERT(faceRenderQueue.m_directionalLight.m_shadowRenderQueues[0]);
|
|
|
+ const RenderQueue& cascadeRenderQueue = *faceRenderQueue.m_directionalLight.m_shadowRenderQueues[0];
|
|
|
|
|
|
- Bool failed = false;
|
|
|
- if(emptyCacheEntryIdx != MAX_U32)
|
|
|
- {
|
|
|
- cacheEntryIdxAllocated = emptyCacheEntryIdx;
|
|
|
- }
|
|
|
- else if(cacheEntryIdxToKick != MAX_U32)
|
|
|
- {
|
|
|
- cacheEntryIdxAllocated = cacheEntryIdxToKick;
|
|
|
- }
|
|
|
- else
|
|
|
+ if(cascadeRenderQueue.m_renderables.getSize() == 0)
|
|
|
{
|
|
|
- // We have a problem
|
|
|
- failed = true;
|
|
|
- ANKI_R_LOGW("There is not enough space in the indirect lighting atlas for more probes. "
|
|
|
- "Increase the r.indirect.maxSimultaneousProbeCount or decrease the scene's probes");
|
|
|
+ return;
|
|
|
}
|
|
|
|
|
|
- return failed;
|
|
|
-}
|
|
|
-
|
|
|
-void Indirect::runShadowMapping(CommandBufferPtr& cmdb)
|
|
|
-{
|
|
|
- cmdb->setPolygonOffset(1.0f, 1.0f);
|
|
|
-
|
|
|
- for(U faceIdx = 0; faceIdx < 6; ++faceIdx)
|
|
|
- {
|
|
|
- ANKI_ASSERT(m_ctx.m_probe);
|
|
|
- ANKI_ASSERT(m_ctx.m_probe->m_renderQueues[faceIdx]);
|
|
|
- const RenderQueue& faceRenderQueue = *m_ctx.m_probe->m_renderQueues[faceIdx];
|
|
|
- ANKI_ASSERT(faceRenderQueue.m_directionalLight.m_uuid != 0);
|
|
|
- ANKI_ASSERT(faceRenderQueue.m_directionalLight.m_shadowCascadeCount == 1);
|
|
|
-
|
|
|
- ANKI_ASSERT(faceRenderQueue.m_directionalLight.m_shadowRenderQueues[0]);
|
|
|
- const RenderQueue& cascadeRenderQueue = *faceRenderQueue.m_directionalLight.m_shadowRenderQueues[0];
|
|
|
-
|
|
|
- if(cascadeRenderQueue.m_renderables.getSize() == 0)
|
|
|
- {
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- const U rez = m_shadowMapping.m_rtDescr.m_height;
|
|
|
- cmdb->setViewport(rez * faceIdx, 0, rez, rez);
|
|
|
- cmdb->setScissor(rez * faceIdx, 0, rez, rez);
|
|
|
-
|
|
|
- m_r->getSceneDrawer().drawRange(Pass::SM,
|
|
|
- cascadeRenderQueue.m_viewMatrix,
|
|
|
- cascadeRenderQueue.m_viewProjectionMatrix,
|
|
|
- Mat4::getIdentity(), // Don't care about prev matrices here
|
|
|
- cmdb,
|
|
|
- m_r->getSamplers().m_trilinearRepeatAniso,
|
|
|
- cascadeRenderQueue.m_renderables.getBegin(),
|
|
|
- cascadeRenderQueue.m_renderables.getEnd());
|
|
|
- }
|
|
|
+ const U rez = m_shadowMapping.m_rtDescr.m_height;
|
|
|
+ cmdb->setViewport(rez * faceIdx, 0, rez, rez);
|
|
|
+ cmdb->setScissor(rez * faceIdx, 0, rez, rez);
|
|
|
+
|
|
|
+ m_r->getSceneDrawer().drawRange(Pass::SM,
|
|
|
+ cascadeRenderQueue.m_viewMatrix,
|
|
|
+ cascadeRenderQueue.m_viewProjectionMatrix,
|
|
|
+ Mat4::getIdentity(), // Don't care about prev matrices here
|
|
|
+ cmdb,
|
|
|
+ m_r->getSamplers().m_trilinearRepeatAniso,
|
|
|
+ cascadeRenderQueue.m_renderables.getBegin(),
|
|
|
+ cascadeRenderQueue.m_renderables.getEnd(),
|
|
|
+ MAX_LOD_COUNT - 1);
|
|
|
|
|
|
cmdb->setPolygonOffset(0.0f, 0.0f);
|
|
|
}
|