Skip to content

Commit c67c100

Browse files
committed
Cull geometry outside of viewport extents
Some views in the application can have a lot of geometry outside of the viewports, particularly the passive skill tree. We can save a lot of GPU work and emit fewer batch boundaries if we conservatively cull out quads that are entirely outside of their viewports by testing axis-aligned bounding boxes. This greatly speeds up the skill tree when partially zoomed, which tends to be a common case. This has benefits in reducing the amount of batch boundary cuts by not having to consider the render states of unseen geometry, especially texture changes.
1 parent 9e8f947 commit c67c100

2 files changed

Lines changed: 57 additions & 0 deletions

File tree

engine/render/r_main.cpp

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
//
66

77
#define GLAD_GLES2_IMPLEMENTATION
8+
#define IMGUI_DEFINE_MATH_OPERATORS
89
#include "r_local.h"
910

1011
#include <array>
@@ -218,6 +219,49 @@ void r_layer_c::Quad(double s0, double t0, double x0, double y0, double s1, doub
218219
cmd->quad.y[0] = y0; cmd->quad.y[1] = y1; cmd->quad.y[2] = y2; cmd->quad.y[3] = y3;
219220
}
220221

222+
// =================
223+
// Geometric queries
224+
// =================
225+
226+
struct r_aabb_s {
227+
float lo[2];
228+
float hi[2];
229+
};
230+
231+
r_aabb_s AabbFromCmdQuad(decltype(r_layerCmd_s::quad)& q, r_viewport_s& vp)
232+
{
233+
r_aabb_s r{
234+
{+FLT_MAX, +FLT_MAX},
235+
{-FLT_MAX, -FLT_MAX},
236+
};
237+
for (size_t i = 0; i < 4; ++i) {
238+
r.lo[0] = (std::min)(r.lo[0], (float)q.x[i]);
239+
r.lo[1] = (std::min)(r.lo[1], (float)q.y[i]);
240+
r.hi[0] = (std::max)(r.hi[0], (float)q.x[i]);
241+
r.hi[1] = (std::max)(r.hi[1], (float)q.y[i]);
242+
}
243+
r.lo[0] += vp.x;
244+
r.lo[1] += vp.y;
245+
r.hi[0] += vp.x;
246+
r.hi[1] += vp.y;
247+
return r;
248+
}
249+
250+
r_aabb_s AabbFromViewport(r_viewport_s& vp)
251+
{
252+
r_aabb_s r{
253+
{(float)vp.x, (float)vp.y },
254+
{(float)(vp.x + vp.width), (float)(vp.y + vp.height) },
255+
};
256+
return r;
257+
}
258+
259+
bool AabbAabbIntersects(r_aabb_s& a, r_aabb_s& b)
260+
{
261+
// A.lo <= B.hi && A.hi >= B.lo
262+
return a.lo[0] <= b.hi[0] && a.lo[1] <= b.hi[1] && a.hi[0] >= b.lo[0] && a.hi[1] >= b.lo[1];
263+
}
264+
221265
struct Vertex {
222266
float x, y;
223267
float u, v;
@@ -392,6 +436,16 @@ struct AdjacentMergeStrategy : RenderStrategy {
392436
// ImGui::Text("QUAD");
393437
}
394438

439+
// Cull the quad first before it influences any boundary cuts.
440+
if (!!renderer_->r_drawCull->intVal) {
441+
auto a = AabbFromCmdQuad(cmd->quad, nextViewport_);
442+
auto b = AabbFromViewport(nextViewport_);
443+
bool intersects = AabbAabbIntersects(a, b);
444+
if (!intersects) {
445+
break;
446+
}
447+
}
448+
395449
// If the current batch is incompatible key-wise, dispatch it to get a fresh
396450
// batch to grow in.
397451
if (!batch_.batch.vertices.empty() && batch_.key != latchKey_) {
@@ -643,6 +697,7 @@ r_renderer_c::r_renderer_c(sys_IMain* sysHnd)
643697
r_layerOptimize = sys->con->Cvar_Add("r_layerOptimize", CV_ARCHIVE | CV_CLAMP, "1", 0, 1);
644698
r_layerShuffle = sys->con->Cvar_Add("r_layerShuffle", CV_ARCHIVE | CV_CLAMP, "0", 0, 1);
645699
r_elideFrames = sys->con->Cvar_Add("r_elideFrames", CV_ARCHIVE | CV_CLAMP, "1", 0, 1);
700+
r_drawCull = sys->con->Cvar_Add("r_drawCull", CV_ARCHIVE | CV_CLAMP, "1", 0, 1);
646701

647702
Cmd_Add("screenshot", 0, "[<format>]", this, &r_renderer_c::C_Screenshot);
648703
}
@@ -1142,6 +1197,7 @@ void r_renderer_c::EndFrame()
11421197
ImGui::Text("%d out of %d frames drawn, %d saved.", drawnFrames, totalFrames, savedFrames);
11431198
CVarSliderInt("Optimization", r_layerOptimize);
11441199
CVarCheckbox("Elide identical frames", r_elideFrames);
1200+
CVarCheckbox("Draw command culling", r_drawCull);
11451201

11461202
int totalCmd{};
11471203
if (ImGui::BeginTable("Layer stats", 5, ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit)) {

engine/render/r_main.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ class r_renderer_c: public r_IRenderer, public conCmdHandler_c {
120120
conVar_c* r_layerOptimize = nullptr;
121121
conVar_c* r_layerShuffle = nullptr;
122122
conVar_c* r_elideFrames = nullptr;
123+
conVar_c* r_drawCull = nullptr;
123124

124125
r_shaderHnd_c* whiteImage = nullptr; // White image
125126

0 commit comments

Comments
 (0)