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
215216struct 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
232235Batch::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+
241267Batch::~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
267295void 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
0 commit comments