Skip to content

Commit 73b0adc

Browse files
committed
Merge all compatible draw calls inside layers
1 parent 08c57d9 commit 73b0adc

2 files changed

Lines changed: 153 additions & 48 deletions

File tree

engine/render/r_main.cpp

Lines changed: 150 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "r_local.h"
88

99
#include <fmt/chrono.h>
10+
#include <map>
1011

1112
// =======
1213
// Classes
@@ -214,6 +215,8 @@ struct Vertex {
214215

215216
struct Batch {
216217
explicit Batch(GLuint prog);
218+
Batch(Batch&& rhs);
219+
Batch& operator = (Batch&& rhs);
217220
Batch(Batch const&) = delete;
218221
Batch& operator = (Batch const&) = delete;
219222
~Batch();
@@ -226,7 +229,7 @@ struct Batch {
226229
GLuint vbo;
227230
std::vector<Vertex> vertices;
228231

229-
void FlushBatch();
232+
void Execute();
230233
};
231234

232235
Batch::Batch(GLuint prog)
@@ -238,11 +241,36 @@ Batch::Batch(GLuint prog)
238241
glGenBuffers(1, &vbo);
239242
}
240243

244+
Batch::Batch(Batch&& rhs)
245+
: prog(rhs.prog)
246+
, xyAttr(rhs.xyAttr)
247+
, uvAttr(rhs.uvAttr)
248+
, tintAttr(rhs.tintAttr)
249+
, vbo(rhs.vbo)
250+
, vertices(std::move(rhs.vertices))
251+
{
252+
rhs.vbo = 0;
253+
}
254+
255+
Batch& Batch::operator = (Batch&& rhs) {
256+
prog = rhs.prog;
257+
xyAttr = rhs.xyAttr;
258+
uvAttr = rhs.uvAttr;
259+
tintAttr = rhs.tintAttr;
260+
vbo = rhs.vbo;
261+
vertices = std::move(rhs.vertices);
262+
rhs.vbo = 0;
263+
264+
return *this;
265+
}
266+
241267
Batch::~Batch() {
242-
glDeleteBuffers(1, &vbo);
268+
if (vbo) {
269+
glDeleteBuffers(1, &vbo);
270+
}
243271
}
244272

245-
void Batch::FlushBatch()
273+
void Batch::Execute()
246274
{
247275
if (vertices.empty()) {
248276
return;
@@ -266,61 +294,74 @@ void Batch::FlushBatch()
266294

267295
void r_layer_c::Render()
268296
{
269-
r_viewport_s curViewPort = { -1, -1, -1, -1 };
270-
int curBlendMode = -1;
271-
r_tex_c* curTex = NULL;
297+
struct BatchKey {
298+
r_viewport_s viewport = { -1, -1, -1, -1 };
299+
int blendMode = -1;
300+
r_tex_c* tex = NULL;
301+
302+
bool operator < (BatchKey const& rhs) const {
303+
if (viewport.x != rhs.viewport.x) {
304+
return viewport.x < rhs.viewport.x;
305+
}
306+
if (viewport.y != rhs.viewport.y) {
307+
return viewport.y < rhs.viewport.y;
308+
}
309+
if (viewport.width != rhs.viewport.width) {
310+
return viewport.width < rhs.viewport.width;
311+
}
312+
if (viewport.height != rhs.viewport.height) {
313+
return viewport.height < rhs.viewport.height;
314+
}
315+
if (blendMode != rhs.blendMode) {
316+
return blendMode < rhs.blendMode;
317+
}
318+
return std::less<r_tex_c const*>{}(tex, rhs.tex);
319+
}
320+
};
321+
322+
if (renderer->glPushGroupMarkerEXT)
323+
{
324+
std::ostringstream oss;
325+
oss << "Layer " << layer << ", sub-layer " << subLayer;
326+
renderer->glPushGroupMarkerEXT(0, oss.str().c_str());
327+
}
328+
BatchKey currentKey{};
272329
GLuint prog = renderer->tintedTextureProgram;
273330
float tint[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
274331
glUseProgram(prog);
275332
{
276333
GLint texLoc = glGetUniformLocation(prog, "t_tex");
277334
glUniform1i(texLoc, 0);
278335
}
279-
Batch batch{ prog };
336+
337+
std::vector<Batch> batches;
338+
std::vector<BatchKey> batchKeys;
339+
std::map<BatchKey, size_t> batchIndices;
280340

281341
for (int i = 0; i < numCmd; i++) {
282342
r_layerCmd_s* cmd = cmdList[i];
283343
switch (cmd->cmd) {
284344
case r_layerCmd_s::VIEWPORT:
285-
if (cmd->viewport.x != curViewPort.x || cmd->viewport.y != curViewPort.y || cmd->viewport.width != curViewPort.width || cmd->viewport.height != curViewPort.height) {
286-
batch.FlushBatch();
287-
auto& vid = renderer->sys->video->vid;
288-
float fbScaleX = vid.fbSize[0] / (float)vid.size[0];
289-
float fbScaleY = vid.fbSize[1] / (float)vid.size[1];
290-
float x = cmd->viewport.x * fbScaleX;
291-
float y = (vid.size[1] - cmd->viewport.y - cmd->viewport.height) * fbScaleY;
292-
float width = cmd->viewport.width * fbScaleX;
293-
float height = cmd->viewport.height * fbScaleY;
294-
glViewport((int)x, (int)y, (int)width, (int)height);
295-
Mat4 mvpMatrix = OrthoMatrix(0, cmd->viewport.width, cmd->viewport.height, 0, -9999, 9999);
296-
GLint mvpMatrixLoc = glGetUniformLocation(prog, "mvp_matrix");
297-
glUniformMatrix4fv(mvpMatrixLoc, 1, GL_FALSE, mvpMatrix.data());
298-
}
345+
currentKey.viewport = cmd->viewport;
299346
break;
300347
case r_layerCmd_s::BLEND:
301-
if (cmd->blendMode != curBlendMode) {
302-
batch.FlushBatch();
303-
switch (cmd->blendMode) {
304-
case RB_ALPHA:
305-
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
306-
break;
307-
case RB_PRE_ALPHA:
308-
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
309-
break;
310-
case RB_ADDITIVE:
311-
glBlendFunc(GL_ONE, GL_ONE);
312-
break;
313-
}
314-
}
348+
currentKey.blendMode = cmd->blendMode;
315349
break;
316350
case r_layerCmd_s::BIND:
317-
if (cmd->tex != curTex) {
318-
batch.FlushBatch();
319-
cmd->tex->Bind();
320-
curTex = cmd->tex;
321-
}
351+
currentKey.tex = cmd->tex;
322352
break;
323353
case r_layerCmd_s::QUAD: {
354+
Batch* batch{};
355+
auto I = batchIndices.find(currentKey);
356+
if (I != batchIndices.end()) {
357+
batch = &batches[I->second];
358+
}
359+
else {
360+
batchIndices.insert(I, { currentKey, batches.size() });
361+
batchKeys.push_back(currentKey);
362+
batches.emplace_back(prog);
363+
batch = &batches.back();
364+
}
324365
Vertex quad[4];
325366
for (int v = 0; v < 4; v++) {
326367
quad[v].u = (float)cmd->quad.s[v];
@@ -332,27 +373,75 @@ void r_layer_c::Render()
332373
quad[v].b = tint[2];
333374
quad[v].a = tint[3];
334375
}
335-
// 3 2
336-
// 0 1
376+
// 3-2
377+
// |/|
378+
// 0-1
337379
size_t indices[] = { 0, 1, 2, 0, 2, 3 };
338380
for (auto idx : indices) {
339-
batch.vertices.push_back(quad[idx]);
381+
batch->vertices.push_back(quad[idx]);
340382
}
341383
} break;
342-
case r_layerCmd_s::COLOR: {
384+
case r_layerCmd_s::COLOR:
343385
std::copy_n(cmd->col, 4, tint);
344-
} break;
386+
break;
387+
}
388+
}
389+
390+
std::optional<BatchKey> lastKey{};
391+
int const numBatches = batches.size();
392+
for (int i = 0; i < numBatches; ++i) {
393+
auto& batch = batches[i];
394+
auto& key = batchKeys[i];
395+
if (!lastKey || lastKey->viewport.x != key.viewport.x || lastKey->viewport.y != key.viewport.y ||
396+
lastKey->viewport.width != key.viewport.width || lastKey->viewport.height != key.viewport.height)
397+
{
398+
auto& vid = renderer->sys->video->vid;
399+
float fbScaleX = vid.fbSize[0] / (float)vid.size[0];
400+
float fbScaleY = vid.fbSize[1] / (float)vid.size[1];
401+
float x = key.viewport.x * fbScaleX;
402+
float y = (vid.size[1] - key.viewport.y - key.viewport.height) * fbScaleY;
403+
float width = key.viewport.width * fbScaleX;
404+
float height = key.viewport.height * fbScaleY;
405+
glViewport((int)x, (int)y, (int)width, (int)height);
406+
Mat4 mvpMatrix = OrthoMatrix(0, key.viewport.width, key.viewport.height, 0, -9999, 9999);
407+
GLint mvpMatrixLoc = glGetUniformLocation(prog, "mvp_matrix");
408+
glUniformMatrix4fv(mvpMatrixLoc, 1, GL_FALSE, mvpMatrix.data());
345409
}
410+
if (!lastKey || lastKey->blendMode != key.blendMode) {
411+
switch (key.blendMode) {
412+
case RB_ALPHA:
413+
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
414+
break;
415+
case RB_PRE_ALPHA:
416+
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
417+
break;
418+
case RB_ADDITIVE:
419+
glBlendFunc(GL_ONE, GL_ONE);
420+
break;
421+
}
422+
}
423+
if (!lastKey || lastKey->tex != key.tex) {
424+
key.tex->Bind();
425+
}
426+
427+
batch.Execute();
428+
429+
lastKey = key;
430+
}
431+
glUseProgram(0);
432+
433+
for (int i = 0; i < numCmd; i++) {
434+
r_layerCmd_s* cmd = cmdList[i];
346435
if (renderer->layerCmdBinCount == renderer->layerCmdBinSize) {
347436
renderer->layerCmdBinSize <<= 1;
348437
trealloc(renderer->layerCmdBin, renderer->layerCmdBinSize);
349438
}
350439
renderer->layerCmdBin[renderer->layerCmdBinCount++] = cmd;
351440
}
352-
// Draw the last batch
353-
batch.FlushBatch();
354-
glUseProgram(0);
355441
numCmd = 0;
442+
if (renderer->glPopGroupMarkerEXT) {
443+
renderer->glPopGroupMarkerEXT();
444+
}
356445
}
357446

358447
// =====================
@@ -495,6 +584,19 @@ void r_renderer_c::Init()
495584
glCompressedTexImage2D = NULL;
496585
}
497586

587+
if (strstr(st_ext, "GL_EXT_debug_marker")) {
588+
sys->con->Printf("using GL_EXT_debug_marker\n");
589+
glInsertEventMarkerEXT = (PFNGLINSERTEVENTMARKEREXTPROC)openGL->GetProc("glInsertEventMarkerEXT");
590+
glPushGroupMarkerEXT = (PFNGLPUSHGROUPMARKEREXTPROC)openGL->GetProc("glPushGroupMarkerEXT");
591+
glPopGroupMarkerEXT = (PFNGLPOPGROUPMARKEREXTPROC)openGL->GetProc("glPopGroupMarkerEXT");
592+
}
593+
else {
594+
sys->con->Printf("GL_EXT_debug_marker not supported\n");
595+
glInsertEventMarkerEXT = NULL;
596+
glPushGroupMarkerEXT = NULL;
597+
glPopGroupMarkerEXT = NULL;
598+
}
599+
498600
texNonPOT = true;
499601

500602
// Initialise texture manager

engine/render/r_main.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,9 @@ class r_renderer_c: public r_IRenderer, public conCmdHandler_c {
9898
dword texMaxDim = 0; // Maximum texture dimension
9999

100100
PFNGLCOMPRESSEDTEXIMAGE2DPROC glCompressedTexImage2D = nullptr;
101+
PFNGLINSERTEVENTMARKEREXTPROC glInsertEventMarkerEXT = nullptr;
102+
PFNGLPUSHGROUPMARKEREXTPROC glPushGroupMarkerEXT = nullptr;
103+
PFNGLPOPGROUPMARKEREXTPROC glPopGroupMarkerEXT = nullptr;
101104

102105
conVar_c* r_compress = nullptr;
103106
conVar_c* r_screenshotFormat = nullptr;

0 commit comments

Comments
 (0)