diff --git a/Common/GPU/OpenGL/GLQueueRunner.cpp b/Common/GPU/OpenGL/GLQueueRunner.cpp index c302f3c9ec..4c27693f75 100644 --- a/Common/GPU/OpenGL/GLQueueRunner.cpp +++ b/Common/GPU/OpenGL/GLQueueRunner.cpp @@ -1266,7 +1266,9 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step, bool first, bool last glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf); curElemArrayBuffer = buf; } - if (c.draw.instances == 1) { + if (c.draw.instances == 1 && c.draw.maxIndex >= 0 && (!gl_extensions.IsGLES || gl_extensions.GLES3)) { + glDrawRangeElements(c.draw.mode, 0, c.draw.maxIndex, c.draw.count, c.draw.indexType, (void *)(intptr_t)c.draw.indexOffset); + } else if (c.draw.instances == 1) { glDrawElements(c.draw.mode, c.draw.count, c.draw.indexType, (void *)(intptr_t)c.draw.indexOffset); } else { glDrawElementsInstanced(c.draw.mode, c.draw.count, c.draw.indexType, (void *)(intptr_t)c.draw.indexOffset, c.draw.instances); diff --git a/Common/GPU/OpenGL/GLQueueRunner.h b/Common/GPU/OpenGL/GLQueueRunner.h index e7934ecfde..2bc4b890b2 100644 --- a/Common/GPU/OpenGL/GLQueueRunner.h +++ b/Common/GPU/OpenGL/GLQueueRunner.h @@ -116,6 +116,7 @@ struct GLRRenderData { GLint count; GLint indexType; GLint instances; + GLint maxIndex; // -1 if unknown. Otherwise, all indices are known to be <= maxIndex. } draw; struct { const char *name; // if null, use loc diff --git a/Common/GPU/OpenGL/GLRenderManager.h b/Common/GPU/OpenGL/GLRenderManager.h index 2e03897320..687307c67d 100644 --- a/Common/GPU/OpenGL/GLRenderManager.h +++ b/Common/GPU/OpenGL/GLRenderManager.h @@ -794,7 +794,9 @@ public: } // Would really love to have a basevertex parameter, but impossible in unextended GLES, without glDrawElementsBaseVertex, unfortunately. - void DrawIndexed(GLRInputLayout *inputLayout, GLRBuffer *vertexBuffer, uint32_t vertexOffset, GLRBuffer *indexBuffer, uint32_t indexOffset, GLenum mode, int count, GLenum indexType, int instances = 1) { + // If maxIndex is known (>= 0), it's passed on to the driver through glDrawRangeElements, which saves drivers that need the index + // range (like Panfrost) from scanning the index data on the CPU for every draw. + void DrawIndexed(GLRInputLayout *inputLayout, GLRBuffer *vertexBuffer, uint32_t vertexOffset, GLRBuffer *indexBuffer, uint32_t indexOffset, GLenum mode, int count, GLenum indexType, int instances = 1, int maxIndex = -1) { _dbg_assert_(vertexBuffer && indexBuffer && curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); GLRRenderData &data = curRenderStep_->commands.push_uninitialized(); data.cmd = GLRRenderCommand::DRAW; @@ -807,6 +809,7 @@ public: data.draw.count = count; data.draw.indexType = indexType; data.draw.instances = instances; + data.draw.maxIndex = maxIndex; } enum { MAX_INFLIGHT_FRAMES = 3 }; diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index f778b8d451..a86ff17852 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -332,7 +332,7 @@ void DrawEngineGLES::Flush() { render_->DrawIndexed(inputLayout, vertexBuffer, vertexBufferOffset, indexBuffer, indexBufferOffset, - glprim[prim], vertexCount, GL_UNSIGNED_SHORT); + glprim[prim], vertexCount, GL_UNSIGNED_SHORT, 1, maxIndex - 1); } else { render_->Draw( inputLayout, vertexBuffer, vertexBufferOffset, @@ -419,7 +419,7 @@ void DrawEngineGLES::Flush() { indexBufferOffset = (uint32_t)frameData.pushIndex->Push(inds, sizeof(uint16_t) * result.drawIndexCount, 2, &indexBuffer); render_->DrawIndexed( softwareInputLayout_, vertexBuffer, vertexBufferOffset, indexBuffer, indexBufferOffset, - glprim[prim], result.drawIndexCount, GL_UNSIGNED_SHORT); + glprim[prim], result.drawIndexCount, GL_UNSIGNED_SHORT, 1, result.drawVertexCount - 1); gpuStats.perFrame.numVertsDrawn += result.drawIndexCount; } else if (action == SW_CLEAR) { u32 clearColor = result.color;