diff --git a/Common/GPU/OpenGL/GLQueueRunner.cpp b/Common/GPU/OpenGL/GLQueueRunner.cpp index 80a3193e40db..06e0e9428dd8 100644 --- a/Common/GPU/OpenGL/GLQueueRunner.cpp +++ b/Common/GPU/OpenGL/GLQueueRunner.cpp @@ -1148,12 +1148,12 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step, bool first, bool last CHECK_GL_ERROR_IF_DEBUG(); break; } - case GLRRenderCommand::BIND_VERTEX_BUFFER: + case GLRRenderCommand::DRAW: { // TODO: Add fast path for glBindVertexBuffer - GLRInputLayout *layout = c.bindVertexBuffer.inputLayout; - GLuint buf = c.bindVertexBuffer.buffer ? c.bindVertexBuffer.buffer->buffer_ : 0; - _dbg_assert_(!c.bindVertexBuffer.buffer || !c.bindVertexBuffer.buffer->Mapped()); + GLRInputLayout *layout = c.draw.inputLayout; + GLuint buf = c.draw.buffer ? c.draw.buffer->buffer_ : 0; + _dbg_assert_(!c.draw.buffer || !c.draw.buffer->Mapped()); if (buf != curArrayBuffer) { glBindBuffer(GL_ARRAY_BUFFER, buf); curArrayBuffer = buf; @@ -1161,7 +1161,6 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step, bool first, bool last if (attrMask != layout->semanticsMask_) { int enable = layout->semanticsMask_ & ~attrMask; int disable = (~layout->semanticsMask_) & attrMask; - for (int i = 0; i < 7; i++) { // SEM_MAX if (enable & (1 << i)) { glEnableVertexAttribArray(i); @@ -1174,26 +1173,22 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step, bool first, bool last } for (size_t i = 0; i < layout->entries.size(); i++) { auto &entry = layout->entries[i]; - glVertexAttribPointer(entry.location, entry.count, entry.type, entry.normalized, entry.stride, (const void *)(c.bindVertexBuffer.offset + entry.offset)); + glVertexAttribPointer(entry.location, entry.count, entry.type, entry.normalized, entry.stride, (const void *)(c.draw.offset + entry.offset)); } - CHECK_GL_ERROR_IF_DEBUG(); - break; - } - case GLRRenderCommand::BIND_BUFFER: - { - if (c.bind_buffer.target == GL_ARRAY_BUFFER) { - Crash(); - } else if (c.bind_buffer.target == GL_ELEMENT_ARRAY_BUFFER) { - GLuint buf = c.bind_buffer.buffer ? c.bind_buffer.buffer->buffer_ : 0; - _dbg_assert_(!(c.bind_buffer.buffer && c.bind_buffer.buffer->Mapped())); + if (c.draw.indexBuffer) { + GLuint buf = c.draw.indexBuffer->buffer_; + _dbg_assert_(!(c.draw.indexBuffer && c.draw.indexBuffer->Mapped())); if (buf != curElemArrayBuffer) { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf); curElemArrayBuffer = buf; } + if (c.draw.instances == 1) { + glDrawElements(c.draw.mode, c.draw.count, c.draw.indexType, c.draw.indices); + } else { + glDrawElementsInstanced(c.draw.mode, c.draw.count, c.draw.indexType, c.draw.indices, c.draw.instances); + } } else { - GLuint buf = c.bind_buffer.buffer ? c.bind_buffer.buffer->buffer_ : 0; - _dbg_assert_(!(c.bind_buffer.buffer && c.bind_buffer.buffer->Mapped())); - glBindBuffer(c.bind_buffer.target, buf); + glDrawArrays(c.draw.mode, c.draw.first, c.draw.count); } CHECK_GL_ERROR_IF_DEBUG(); break; @@ -1202,16 +1197,6 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step, bool first, bool last // TODO: Should we include the texture handle in the command? // Also, should this not be an init command? glGenerateMipmap(GL_TEXTURE_2D); - break; - case GLRRenderCommand::DRAW: - glDrawArrays(c.draw.mode, c.draw.first, c.draw.count); - break; - case GLRRenderCommand::DRAW_INDEXED: - if (c.drawIndexed.instances == 1) { - glDrawElements(c.drawIndexed.mode, c.drawIndexed.count, c.drawIndexed.indexType, c.drawIndexed.indices); - } else { - glDrawElementsInstanced(c.drawIndexed.mode, c.drawIndexed.count, c.drawIndexed.indexType, c.drawIndexed.indices, c.drawIndexed.instances); - } CHECK_GL_ERROR_IF_DEBUG(); break; case GLRRenderCommand::TEXTURESAMPLER: diff --git a/Common/GPU/OpenGL/GLQueueRunner.h b/Common/GPU/OpenGL/GLQueueRunner.h index e662b43dd190..c7b6134f1741 100644 --- a/Common/GPU/OpenGL/GLQueueRunner.h +++ b/Common/GPU/OpenGL/GLQueueRunner.h @@ -61,10 +61,8 @@ enum class GLRRenderCommand : uint8_t { BINDTEXTURE, BIND_FB_TEXTURE, BIND_VERTEX_BUFFER, - BIND_BUFFER, GENMIPS, DRAW, - DRAW_INDEXED, TEXTURE_SUBIMAGE, }; @@ -109,18 +107,17 @@ struct GLRRenderData { uint8_t writeMask; } stencilOp; // also write mask struct { + GLRInputLayout *inputLayout; + GLRBuffer *buffer; + size_t offset; + GLRBuffer *indexBuffer; GLenum mode; // primitive - GLint buffer; GLint first; GLint count; - } draw; - struct { - GLenum mode; // primitive - GLint count; - GLint instances; GLint indexType; void *indices; - } drawIndexed; + GLint instances; + } draw; struct { const char *name; // if null, use loc const GLint *loc; // NOTE: This is a pointer so we can immediately use things that are "queried" during program creation. @@ -171,11 +168,6 @@ struct GLRRenderData { struct { GLRProgram *program; } program; - struct { - GLRInputLayout *inputLayout; - GLRBuffer *buffer; - size_t offset; - } bindVertexBuffer; struct { int slot; GLenum wrapS; diff --git a/Common/GPU/OpenGL/GLRenderManager.h b/Common/GPU/OpenGL/GLRenderManager.h index f06724a6cbef..64edeca3d68c 100644 --- a/Common/GPU/OpenGL/GLRenderManager.h +++ b/Common/GPU/OpenGL/GLRenderManager.h @@ -641,24 +641,6 @@ class GLRenderManager { #endif } - void BindIndexBuffer(GLRBuffer *buffer) { // Want to support an offset but can't in ES 2.0. We supply an offset when binding the buffers instead. - _dbg_assert_(curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); - GLRRenderData data{ GLRRenderCommand::BIND_BUFFER}; - data.bind_buffer.buffer = buffer; - data.bind_buffer.target = GL_ELEMENT_ARRAY_BUFFER; - curRenderStep_->commands.push_back(data); - } - - void BindVertexBuffer(GLRInputLayout *inputLayout, GLRBuffer *buffer, size_t offset) { - _dbg_assert_(curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); - _dbg_assert_(inputLayout); - GLRRenderData data{ GLRRenderCommand::BIND_VERTEX_BUFFER }; - data.bindVertexBuffer.inputLayout = inputLayout; - data.bindVertexBuffer.offset = offset; - data.bindVertexBuffer.buffer = buffer; - curRenderStep_->commands.push_back(data); - } - void SetDepth(bool enabled, bool write, GLenum func) { _dbg_assert_(curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); GLRRenderData data{ GLRRenderCommand::DEPTH }; @@ -924,25 +906,33 @@ class GLRenderManager { curRenderStep_->commands.push_back(data); } - void Draw(GLenum mode, int first, int count) { + void Draw(GLRInputLayout *inputLayout, GLRBuffer *buffer, size_t offset, GLenum mode, int first, int count) { _dbg_assert_(curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); GLRRenderData data{ GLRRenderCommand::DRAW }; + data.draw.inputLayout = inputLayout; + data.draw.offset = offset; + data.draw.buffer = buffer; + data.draw.indexBuffer = nullptr; data.draw.mode = mode; data.draw.first = first; data.draw.count = count; - data.draw.buffer = 0; + data.draw.indexType = 0; curRenderStep_->commands.push_back(data); curRenderStep_->render.numDraws++; } - void DrawIndexed(GLenum mode, int count, GLenum indexType, void *indices, int instances = 1) { + void DrawIndexed(GLRInputLayout *inputLayout, GLRBuffer *buffer, size_t offset, GLRBuffer *indexBuffer, GLenum mode, int count, GLenum indexType, void *indices, int instances = 1) { _dbg_assert_(curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); - GLRRenderData data{ GLRRenderCommand::DRAW_INDEXED }; - data.drawIndexed.mode = mode; - data.drawIndexed.count = count; - data.drawIndexed.indexType = indexType; - data.drawIndexed.instances = instances; - data.drawIndexed.indices = indices; + GLRRenderData data{ GLRRenderCommand::DRAW }; + data.draw.inputLayout = inputLayout; + data.draw.offset = offset; + data.draw.buffer = buffer; + data.draw.indexBuffer = indexBuffer; + data.draw.mode = mode; + data.draw.count = count; + data.draw.indexType = indexType; + data.draw.indices = indices; + data.draw.instances = instances; curRenderStep_->commands.push_back(data); curRenderStep_->render.numDraws++; } diff --git a/Common/GPU/OpenGL/thin3d_gl.cpp b/Common/GPU/OpenGL/thin3d_gl.cpp index a50346f2b29f..aae890ee182f 100644 --- a/Common/GPU/OpenGL/thin3d_gl.cpp +++ b/Common/GPU/OpenGL/thin3d_gl.cpp @@ -1332,21 +1332,18 @@ void OpenGLContext::UpdateDynamicUniformBuffer(const void *ub, size_t size) { void OpenGLContext::Draw(int vertexCount, int offset) { _dbg_assert_msg_(curVBuffers_[0] != nullptr, "Can't call Draw without a vertex buffer"); ApplySamplers(); - if (curPipeline_->inputLayout) { - renderManager_.BindVertexBuffer(curPipeline_->inputLayout->inputLayout_, curVBuffers_[0]->buffer_, curVBufferOffsets_[0]); - } - renderManager_.Draw(curPipeline_->prim, offset, vertexCount); + _assert_(curPipeline_->inputLayout); + renderManager_.Draw(curPipeline_->inputLayout->inputLayout_, curVBuffers_[0]->buffer_, curVBufferOffsets_[0], curPipeline_->prim, offset, vertexCount); } void OpenGLContext::DrawIndexed(int vertexCount, int offset) { _dbg_assert_msg_(curVBuffers_[0] != nullptr, "Can't call DrawIndexed without a vertex buffer"); _dbg_assert_msg_(curIBuffer_ != nullptr, "Can't call DrawIndexed without an index buffer"); ApplySamplers(); - if (curPipeline_->inputLayout) { - renderManager_.BindVertexBuffer(curPipeline_->inputLayout->inputLayout_, curVBuffers_[0]->buffer_, curVBufferOffsets_[0]); - } - renderManager_.BindIndexBuffer(curIBuffer_->buffer_); - renderManager_.DrawIndexed(curPipeline_->prim, vertexCount, GL_UNSIGNED_SHORT, (void *)((intptr_t)curIBufferOffset_ + offset * sizeof(uint32_t))); + _assert_(curPipeline_->inputLayout); + renderManager_.DrawIndexed( + curPipeline_->inputLayout->inputLayout_, curVBuffers_[0]->buffer_, curVBufferOffsets_[0], curIBuffer_->buffer_, + curPipeline_->prim, vertexCount, GL_UNSIGNED_SHORT, (void *)((intptr_t)curIBufferOffset_ + offset * sizeof(uint32_t))); } void OpenGLContext::DrawUP(const void *vdata, int vertexCount) { @@ -1360,10 +1357,8 @@ void OpenGLContext::DrawUP(const void *vdata, int vertexCount) { size_t offset = frameData.push->Push(vdata, dataSize, &buf); ApplySamplers(); - if (curPipeline_->inputLayout) { - renderManager_.BindVertexBuffer(curPipeline_->inputLayout->inputLayout_, buf, offset); - } - renderManager_.Draw(curPipeline_->prim, 0, vertexCount); + _assert_(curPipeline_->inputLayout); + renderManager_.Draw(curPipeline_->inputLayout->inputLayout_, buf, offset, curPipeline_->prim, 0, vertexCount); } void OpenGLContext::Clear(int mask, uint32_t colorval, float depthVal, int stencilVal) { diff --git a/Common/VR/PPSSPPVR.cpp b/Common/VR/PPSSPPVR.cpp index 7daf981e2607..e580a6af8030 100644 --- a/Common/VR/PPSSPPVR.cpp +++ b/Common/VR/PPSSPPVR.cpp @@ -574,8 +574,8 @@ void PreprocessSkyplane(GLRStep* step) { for (auto& command : step->commands) { if (command.cmd == GLRRenderCommand::DEPTH) { depthEnabled = command.depth.enabled; - } else if ((command.cmd == GLRRenderCommand::DRAW_INDEXED) && !depthEnabled) { - command.drawIndexed.count = 0; + } else if ((command.cmd == GLRRenderCommand::DRAW && command.draw.indices != nullptr) && !depthEnabled) { + command.draw.count = 0; } } } diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index fb9c51105b24..0ea95fbffe91 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -326,17 +326,19 @@ void DrawEngineGLES::DoFlush() { LinkedShader *program = shaderManager_->ApplyFragmentShader(vsid, vshader, pipelineState_, framebufferManager_->UseBufferedRendering()); GLRInputLayout *inputLayout = SetupDecFmtForDraw(program, dec_->GetDecVtxFmt()); - render_->BindVertexBuffer(inputLayout, vertexBuffer, vertexBufferOffset); if (useElements) { if (!indexBuffer) { size_t esz = sizeof(uint16_t) * indexGen.VertexCount(); void *dest = frameData.pushIndex->Push(esz, &indexBufferOffset, &indexBuffer); memcpy(dest, decIndex, esz); } - render_->BindIndexBuffer(indexBuffer); - render_->DrawIndexed(glprim[prim], vertexCount, GL_UNSIGNED_SHORT, (GLvoid*)(intptr_t)indexBufferOffset); + render_->DrawIndexed( + inputLayout, vertexBuffer, vertexBufferOffset, indexBuffer, + glprim[prim], vertexCount, GL_UNSIGNED_SHORT, (GLvoid*)(intptr_t)indexBufferOffset); } else { - render_->Draw(glprim[prim], 0, vertexCount); + render_->Draw( + inputLayout, vertexBuffer, vertexBufferOffset, + glprim[prim], 0, vertexCount); } } else { PROFILE_THIS_SCOPE("soft"); @@ -434,13 +436,13 @@ void DrawEngineGLES::DoFlush() { if (result.drawIndexed) { vertexBufferOffset = (uint32_t)frameData.pushVertex->Push(result.drawBuffer, maxIndex * sizeof(TransformedVertex), &vertexBuffer); indexBufferOffset = (uint32_t)frameData.pushIndex->Push(inds, sizeof(uint16_t) * result.drawNumTrans, &indexBuffer); - render_->BindVertexBuffer(softwareInputLayout_, vertexBuffer, vertexBufferOffset); - render_->BindIndexBuffer(indexBuffer); - render_->DrawIndexed(glprim[prim], result.drawNumTrans, GL_UNSIGNED_SHORT, (void *)(intptr_t)indexBufferOffset); + render_->DrawIndexed( + softwareInputLayout_, vertexBuffer, vertexBufferOffset, indexBuffer, + glprim[prim], result.drawNumTrans, GL_UNSIGNED_SHORT, (void *)(intptr_t)indexBufferOffset); } else { vertexBufferOffset = (uint32_t)frameData.pushVertex->Push(result.drawBuffer, result.drawNumTrans * sizeof(TransformedVertex), &vertexBuffer); - render_->BindVertexBuffer(softwareInputLayout_, vertexBuffer, vertexBufferOffset); - render_->Draw(glprim[prim], 0, result.drawNumTrans); + render_->Draw( + softwareInputLayout_, vertexBuffer, vertexBufferOffset, glprim[prim], 0, result.drawNumTrans); } } else if (result.action == SW_CLEAR) { u32 clearColor = result.color;