Skip to content

Commit a92ad79

Browse files
committed
optimize cascades rendering
1 parent 104dc1e commit a92ad79

File tree

5 files changed

+83
-17
lines changed

5 files changed

+83
-17
lines changed

sources/include/cage-engine/provisionalGraphics.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,22 @@ namespace cage
4242
Holder<ProvisionalTexture> texture(const String &name, std::function<void(Texture *)> &&init = {});
4343
Holder<ProvisionalTexture> texture(const String &name, uint32 target, std::function<void(Texture *)> &&init = {});
4444

45+
template<class T>
46+
requires(std::is_default_constructible_v<T> && std::is_trivially_destructible_v<T> && std::is_same_v<std::remove_cvref_t<T>, T>)
47+
Holder<T> cpuBuffer(const String &name)
48+
{
49+
auto h = cpuBuffer_(name, sizeof(T), [](void *ptr) -> void { new (ptr, privat::OperatorNewTrait()) T(); });
50+
T *ptr = (T *)+h;
51+
return Holder<T>(ptr, std::move(h));
52+
}
53+
4554
// section: thread-safe, requires opengl context
4655

47-
void reset(); // erase data not used (resolved) since last reset
56+
void update(); // erase data not used (resolved) since last update
4857
void purge(); // erase all data unconditionally
58+
59+
private:
60+
Holder<void> cpuBuffer_(const String &name, uintPtr size, Delegate<void(void *)> &&init);
4961
};
5062

5163
CAGE_ENGINE_API Holder<ProvisionalGraphics> newProvisionalGraphics();

sources/include/cage-engine/renderPipeline.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ namespace cage
1818
String name;
1919
ScreenSpaceEffectsComponent effects;
2020
Mat4 projection;
21+
CameraCommonProperties camera;
2122
Transform transform;
2223
TextureHandle target;
23-
CameraCommonProperties camera;
2424
LodSelection lodSelection;
2525
uint64 currentTime = 0;
2626
uint64 elapsedTime = 1'000'000 / 60; // microseconds since last frame

sources/libengine/graphics/provisionalGraphics.cpp

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include <set>
22

33
#include <cage-core/concurrent.h>
4+
#include <cage-core/memoryBuffer.h>
45
#include <cage-core/string.h>
56
#include <cage-engine/frameBuffer.h>
67
#include <cage-engine/opengl.h>
@@ -54,6 +55,17 @@ namespace cage
5455
ProvisionalTextureHandleImpl(const String &name) : name(name) {}
5556
};
5657

58+
class ProvisionalCpuBufferImpl
59+
{
60+
public:
61+
const String name;
62+
MemoryBuffer result;
63+
ProvisionalGraphicsImpl *impl = nullptr;
64+
uint32 usage = UsageDuration;
65+
66+
ProvisionalCpuBufferImpl(const String &name) : name(name) {}
67+
};
68+
5769
class ProvisionalGraphicsImpl : public ProvisionalGraphics
5870
{
5971
public:
@@ -73,7 +85,7 @@ namespace cage
7385
return it->share();
7486
}
7587

76-
void reset()
88+
void update()
7789
{
7890
ScopeLock lock(mutex);
7991
std::erase_if(data,
@@ -119,6 +131,7 @@ namespace cage
119131
Container<ProvisionalUniformBufferImpl> uniformBuffers;
120132
Container<ProvisionalFrameBufferHandleImpl> frameBuffers;
121133
Container<ProvisionalTextureHandleImpl> textures;
134+
Container<ProvisionalCpuBufferImpl> cpuBuffers;
122135

123136
Holder<ProvisionalUniformBuffer> uniformBuffer(const String &name, std::function<void(UniformBuffer *)> &&init)
124137
{
@@ -151,18 +164,35 @@ namespace cage
151164
return std::move(t).cast<ProvisionalTexture>();
152165
}
153166

154-
void reset()
167+
Holder<void> cpuBuffer(const String &name, uintPtr size, Delegate<void(void *)> &&init)
155168
{
156-
uniformBuffers.reset();
157-
textures.reset();
158-
frameBuffers.reset();
169+
CAGE_ASSERT(size > 0);
170+
auto t = cpuBuffers.acquire(name);
171+
if (t->result.size() == 0)
172+
{
173+
t->result.allocate(size);
174+
init(t->result.data());
175+
}
176+
CAGE_ASSERT(t->result.size() == size);
177+
t->usage = UsageDuration;
178+
void *ptr = t->result.data();
179+
return Holder<void>(ptr, std::move(t));
180+
}
181+
182+
void update()
183+
{
184+
uniformBuffers.update();
185+
textures.update();
186+
frameBuffers.update();
187+
cpuBuffers.update();
159188
}
160189

161190
void purge()
162191
{
163192
uniformBuffers.purge();
164193
textures.purge();
165194
frameBuffers.purge();
195+
cpuBuffers.purge();
166196
}
167197
};
168198
}
@@ -244,10 +274,10 @@ namespace cage
244274
return impl->texture(name, std::move(init), target);
245275
}
246276

247-
void ProvisionalGraphics::reset()
277+
void ProvisionalGraphics::update()
248278
{
249279
ProvisionalGraphicsImpl *impl = (ProvisionalGraphicsImpl *)this;
250-
impl->reset();
280+
impl->update();
251281
}
252282

253283
void ProvisionalGraphics::purge()
@@ -256,6 +286,12 @@ namespace cage
256286
impl->purge();
257287
}
258288

289+
Holder<void> ProvisionalGraphics::cpuBuffer_(const String &name, uintPtr size, Delegate<void(void *)> &&init)
290+
{
291+
ProvisionalGraphicsImpl *impl = (ProvisionalGraphicsImpl *)this;
292+
return impl->cpuBuffer(name, size, std::move(init));
293+
}
294+
259295
Holder<ProvisionalGraphics> newProvisionalGraphics()
260296
{
261297
return systemMemory().createImpl<ProvisionalGraphics, ProvisionalGraphicsImpl>();

sources/libengine/graphics/renderPipeline.cpp

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@ namespace cage
198198
LightComponent lightComponent;
199199
ShadowmapComponent shadowmapComponent;
200200
uint32 cascade = 0;
201+
bool doesRendering = true;
201202
};
202203

203204
struct RenderPipelineImpl : public RenderPipelineConfig
@@ -1364,7 +1365,8 @@ namespace cage
13641365

13651366
// ensure that shadowmaps are rendered before the camera
13661367
for (auto &shm : data->shadowmaps)
1367-
queue->enqueue(std::move(shm->renderQueue));
1368+
if (shm->renderQueue)
1369+
queue->enqueue(std::move(shm->renderQueue));
13681370

13691371
queue->enqueue(std::move(renderQueue));
13701372
return queue;
@@ -1552,6 +1554,20 @@ namespace cage
15521554
static constexpr Mat4 bias = Mat4(0.5, 0, 0, 0, 0, 0.5, 0, 0, 0, 0, 0.5, 0, 0.5, 0.5, 0.5, 1);
15531555
shadowmap->shadowUni.shadowMat[shadowmap->cascade] = bias * viewProj;
15541556
shadowmap->shadowUni.cascadesDepths[shadowmap->cascade] = splitFar;
1557+
1558+
// progressive rendering
1559+
Holder<UniShadowedLight> cache = provisionalGraphics->cpuBuffer<UniShadowedLight>(Stringizer() + name + "_cache_" + shadowmap->cascade);
1560+
if ((frameIndex % sc.cascadesCount) == shadowmap->cascade)
1561+
{
1562+
// render the cascade
1563+
*cache = shadowmap->shadowUni;
1564+
}
1565+
else
1566+
{
1567+
// reuse from earlier
1568+
shadowmap->shadowUni = *cache;
1569+
shadowmap->doesRendering = false;
1570+
}
15551571
}
15561572

15571573
void initializeShadowmapSingle()
@@ -1586,19 +1602,20 @@ namespace cage
15861602
{
15871603
case LightTypeEnum::Directional:
15881604
{
1605+
CAGE_ASSERT(sc.cascadesCount > 0 && sc.cascadesCount <= CAGE_SHADER_MAX_SHADOWMAPSCASCADES);
15891606
Holder<ProvisionalTexture> tex;
15901607
{
1591-
const String name = Stringizer() + this->name + "_shadowmap_" + e->id() + "_cascades_" + sc.resolution;
1608+
const String name = Stringizer() + this->name + "_shadowmap_" + e->id() + "_cascades_" + sc.resolution + "_" + sc.cascadesCount;
15921609
tex = provisionalGraphics->texture(name, GL_TEXTURE_2D_ARRAY,
1593-
[resolution = sc.resolution](Texture *t)
1610+
[resolution = sc.resolution, cascadesCount = sc.cascadesCount](Texture *t)
15941611
{
1595-
t->initialize(Vec3i(resolution, resolution, CAGE_SHADER_MAX_SHADOWMAPSCASCADES), 1, GL_DEPTH_COMPONENT24);
1612+
t->initialize(Vec3i(resolution, resolution, cascadesCount), 1, GL_DEPTH_COMPONENT24);
15961613
t->filters(GL_LINEAR, GL_LINEAR, 16);
15971614
t->wraps(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
15981615
});
15991616
}
16001617
ShadowmapData *first = nullptr;
1601-
for (uint32 cascade = 0; cascade < CAGE_SHADER_MAX_SHADOWMAPSCASCADES; cascade++)
1618+
for (uint32 cascade = 0; cascade < sc.cascadesCount; cascade++)
16021619
{
16031620
auto data = createShadowmapPipeline(e, lc, sc);
16041621
data->shadowmap->cascade = cascade;
@@ -1611,7 +1628,8 @@ namespace cage
16111628
first->shadowUni.cascadesDepths[cascade] = data->shadowmap->shadowUni.cascadesDepths[cascade];
16121629
first->shadowUni.shadowMat[cascade] = data->shadowmap->shadowUni.shadowMat[cascade];
16131630
}
1614-
outputTasks.push_back(tasksRunAsync<RenderPipelineImpl>("render shadowmap cascade", [](RenderPipelineImpl &impl, uint32) { impl.taskShadowmap(); }, std::move(data)));
1631+
if (data->shadowmap->doesRendering)
1632+
outputTasks.push_back(tasksRunAsync<RenderPipelineImpl>("render shadowmap cascade", [](RenderPipelineImpl &impl, uint32) { impl.taskShadowmap(); }, std::move(data)));
16151633
}
16161634
break;
16171635
}

sources/libsimple/graphics.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -466,8 +466,8 @@ namespace cage
466466
renderQueue->dispatch();
467467

468468
{
469-
const auto _ = ProfilingScope("reset provisionals");
470-
engineProvisionalGraphics()->reset();
469+
const auto _ = ProfilingScope("update provisionals");
470+
engineProvisionalGraphics()->update();
471471
}
472472

473473
// check gl errors (even in release, but do not halt the game)

0 commit comments

Comments
 (0)