GL render manager: Merge BindInputLayout into BindVertexBuffer.

This commit is contained in:
Henrik Rydgård 2017-12-19 12:25:13 +01:00
parent 84ad7a2dba
commit 958078f603
7 changed files with 40 additions and 60 deletions

View File

@ -514,7 +514,6 @@ void DrawEngineGLES::DoFlush() {
size_t vsz = dec_->GetDecVtxFmt().stride * indexGen.MaxIndex();
vai->vbo = render_->CreateBuffer(GL_ARRAY_BUFFER, vsz, GL_STATIC_DRAW);
render_->BufferSubdata(vai->vbo, 0, vsz, decoded);
render_->BindVertexBuffer(vai->vbo);
// If there's only been one primitive type, and it's either TRIANGLES, LINES or POINTS,
// there is no need for the index buffer we built. We can then use glDrawArrays instead
// for a very minor speed boost.
@ -607,16 +606,14 @@ rotateVBO:
LinkedShader *program = shaderManager_->ApplyFragmentShader(vsid, vshader, lastVType_, prim);
GLRInputLayout *inputLayout = SetupDecFmtForDraw(program, dec_->GetDecVtxFmt());
render_->BindVertexBuffer(vertexBuffer);
render_->BindInputLayout(inputLayout, vertexBufferOffset);
render_->BindVertexBuffer(inputLayout, vertexBuffer, vertexBufferOffset);
if (useElements) {
if (!indexBuffer) {
indexBufferOffset = (uint32_t)frameData.pushIndex->Push(decIndex, sizeof(uint16_t) * indexGen.VertexCount(), &indexBuffer);
render_->BindIndexBuffer(indexBuffer);
}
if (gstate_c.bezier || gstate_c.spline)
// Instanced rendering for instanced tessellation
; // glDrawElementsInstanced(glprim[prim], vertexCount, GL_UNSIGNED_SHORT, (GLvoid*)(intptr_t)indexBufferOffset, numPatches);
render_->DrawIndexed(glprim[prim], vertexCount, GL_UNSIGNED_SHORT, (GLvoid*)(intptr_t)indexBufferOffset, numPatches);
else
render_->DrawIndexed(glprim[prim], vertexCount, GL_UNSIGNED_SHORT, (GLvoid*)(intptr_t)indexBufferOffset);
} else {
@ -681,14 +678,12 @@ rotateVBO:
if (drawIndexed) {
vertexBufferOffset = (uint32_t)frameData.pushVertex->Push(drawBuffer, maxIndex * sizeof(TransformedVertex), &vertexBuffer);
indexBufferOffset = (uint32_t)frameData.pushIndex->Push(inds, sizeof(uint16_t) * numTrans, &indexBuffer);
render_->BindVertexBuffer(vertexBuffer);
render_->BindInputLayout(softwareInputLayout_, vertexBufferOffset);
render_->BindVertexBuffer(softwareInputLayout_, vertexBuffer, vertexBufferOffset);
render_->BindIndexBuffer(indexBuffer);
render_->DrawIndexed(glprim[prim], numTrans, GL_UNSIGNED_SHORT, (void *)(intptr_t)indexBufferOffset);
} else {
vertexBufferOffset = (uint32_t)frameData.pushVertex->Push(drawBuffer, numTrans * sizeof(TransformedVertex), &vertexBuffer);
render_->BindVertexBuffer(vertexBuffer);
render_->BindInputLayout(softwareInputLayout_, vertexBufferOffset);
render_->BindVertexBuffer(softwareInputLayout_, vertexBuffer, vertexBufferOffset);
render_->Draw(glprim[prim], 0, numTrans);
}
} else if (result.action == SW_CLEAR) {

View File

@ -460,8 +460,7 @@ void FramebufferManagerGLES::DrawActiveTexture(float x, float y, float w, float
GLRBuffer *buffer;
void *dest = drawEngineGL_->GetPushVertexBuffer()->Push(sizeof(verts), &bindOffset, &buffer);
memcpy(dest, verts, sizeof(verts));
render_->BindVertexBuffer(buffer);
render_->BindInputLayout(simple2DInputLayout_, bindOffset);
render_->BindVertexBuffer(simple2DInputLayout_, buffer, bindOffset);
render_->Draw(GL_TRIANGLE_STRIP, 0, 4);
}

View File

@ -405,8 +405,7 @@ public:
memcpy(verts[i].pos, &pos_[order[i]], sizeof(Pos));
memcpy(verts[i].uv, &uv_[order[i]], sizeof(UV));
}
render->BindVertexBuffer(bindBuffer);
render->BindInputLayout(inputLayout, bindOffset);
render->BindVertexBuffer(inputLayout, bindBuffer, bindOffset);
}
void Shade(GLRenderManager *render) {

View File

@ -617,12 +617,17 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) {
}
break;
}
case GLRRenderCommand::BIND_INPUT_LAYOUT:
case GLRRenderCommand::BIND_VERTEX_BUFFER:
{
GLRInputLayout *layout = c.inputLayout.inputLayout;
int enable, disable;
enable = layout->semanticsMask_ & ~attrMask;
disable = (~layout->semanticsMask_) & attrMask;
// TODO: Add fast path for glBindVertexBuffer
GLRInputLayout *layout = c.bindVertexBuffer.inputLayout;
GLuint buf = c.bindVertexBuffer.buffer ? c.bindVertexBuffer.buffer->buffer : 0;
if (buf != curArrayBuffer) {
glBindBuffer(GL_ARRAY_BUFFER, buf);
curArrayBuffer = buf;
}
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);
@ -634,18 +639,14 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) {
attrMask = layout->semanticsMask_;
for (int 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.inputLayout.offset + entry.offset));
glVertexAttribPointer(entry.location, entry.count, entry.type, entry.normalized, entry.stride, (const void *)(c.bindVertexBuffer.offset + entry.offset));
}
break;
}
case GLRRenderCommand::BIND_BUFFER:
{
if (c.bind_buffer.target == GL_ARRAY_BUFFER) {
GLuint buf = c.bind_buffer.buffer ? c.bind_buffer.buffer->buffer : 0;
if (buf != curArrayBuffer) {
glBindBuffer(GL_ARRAY_BUFFER, buf);
curArrayBuffer = buf;
}
Crash();
} else if (c.bind_buffer.target == GL_ELEMENT_ARRAY_BUFFER) {
GLuint buf = c.bind_buffer.buffer ? c.bind_buffer.buffer->buffer : 0;
if (buf != curElemArrayBuffer) {
@ -660,6 +661,7 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) {
}
case GLRRenderCommand::GENMIPS:
// 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:
@ -668,6 +670,8 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) {
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);
}
break;
case GLRRenderCommand::TEXTURESAMPLER:

View File

@ -45,7 +45,7 @@ enum class GLRRenderCommand : uint8_t {
BINDPROGRAM,
BINDTEXTURE,
BIND_FB_TEXTURE,
BIND_INPUT_LAYOUT,
BIND_VERTEX_BUFFER,
BIND_BUFFER,
GENMIPS,
DRAW,
@ -136,8 +136,9 @@ struct GLRRenderData {
} program;
struct {
GLRInputLayout *inputLayout;
GLRBuffer *buffer;
size_t offset;
} inputLayout;
} bindVertexBuffer;
struct {
GLenum wrapS;
GLenum wrapT;

View File

@ -346,14 +346,6 @@ public:
curRenderStep_->commands.push_back(data);
}
void BindVertexBuffer(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_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER);
GLRRenderData data{ GLRRenderCommand::BIND_BUFFER };
data.bind_buffer.buffer = buffer;
data.bind_buffer.target = GL_ARRAY_BUFFER;
curRenderStep_->commands.push_back(data);
}
void BindPixelPackBuffer(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_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER);
GLRRenderData data{ GLRRenderCommand::BIND_BUFFER };
@ -370,12 +362,13 @@ public:
curRenderStep_->commands.push_back(data);
}
void BindInputLayout(GLRInputLayout *inputLayout, size_t offset) {
void BindVertexBuffer(GLRInputLayout *inputLayout, GLRBuffer *buffer, size_t offset) {
_dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER);
assert(inputLayout);
GLRRenderData data{ GLRRenderCommand::BIND_INPUT_LAYOUT };
data.inputLayout.inputLayout = inputLayout;
data.inputLayout.offset = offset;
GLRRenderData data{ GLRRenderCommand::BIND_VERTEX_BUFFER };
data.bindVertexBuffer.inputLayout = inputLayout;
data.bindVertexBuffer.offset = offset;
data.bindVertexBuffer.buffer = buffer;
curRenderStep_->commands.push_back(data);
}
@ -579,13 +572,13 @@ public:
curRenderStep_->render.numDraws++;
}
void DrawIndexed(GLenum mode, int count, GLenum indexType, void *indices) {
void DrawIndexed(GLenum mode, int count, GLenum indexType, void *indices, int instances = 1) {
_dbg_assert_(G3D, 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 = 1;
data.drawIndexed.instances = instances;
data.drawIndexed.indices = indices;
curRenderStep_->commands.push_back(data);
curRenderStep_->render.numDraws++;

View File

@ -940,13 +940,6 @@ public:
render_->DeleteBuffer(buffer_);
}
void Bind(int offset) {
Crash();
// render_->BindBuffer(buffer_);
// TODO: Can't support offset using ES 2.0
// glBindBuffer(target_, buffer_);
}
GLRenderManager *render_;
GLRBuffer *buffer_;
GLuint target_;
@ -962,7 +955,6 @@ Buffer *OpenGLContext::CreateBuffer(size_t size, uint32_t usageFlags) {
void OpenGLContext::UpdateBuffer(Buffer *buffer, const uint8_t *data, size_t offset, size_t size, UpdateBufferFlags flags) {
OpenGLBuffer *buf = (OpenGLBuffer *)buffer;
buf->Bind(0);
if (size + offset > buf->totalSize_) {
Crash();
}
@ -970,6 +962,7 @@ void OpenGLContext::UpdateBuffer(Buffer *buffer, const uint8_t *data, size_t off
uint8_t *dataCopy = new uint8_t[size];
memcpy(dataCopy, data, size);
// if (flags & UPDATE_DISCARD) we could try to orphan the buffer using glBufferData.
// But we're much better off using separate buffers per FrameData...
renderManager_.BufferSubdata(buf->buffer_, offset, size, dataCopy);
}
@ -1097,21 +1090,19 @@ void OpenGLContext::UpdateDynamicUniformBuffer(const void *ub, size_t size) {
}
void OpenGLContext::Draw(int vertexCount, int offset) {
curVBuffers_[0]->Bind(curVBufferOffsets_[0]);
renderManager_.BindInputLayout(curPipeline_->inputLayout->inputLayout_, 0);
_dbg_assert_msg_(G3D, curVBuffers_[0], "Can't call Draw without a vertex buffer");
ApplySamplers();
renderManager_.BindVertexBuffer(curPipeline_->inputLayout->inputLayout_, curVBuffers_[0]->buffer_, curVBufferOffsets_[0]);
renderManager_.Draw(curPipeline_->prim, offset, vertexCount);
}
void OpenGLContext::DrawIndexed(int vertexCount, int offset) {
curVBuffers_[0]->Bind(curVBufferOffsets_[0]);
renderManager_.BindInputLayout(curPipeline_->inputLayout->inputLayout_, 0);
_dbg_assert_msg_(G3D, curVBuffers_[0], "Can't call DrawIndexed without a vertex buffer");
_dbg_assert_msg_(G3D, curIBuffer_, "Can't call DrawIndexed without an index buffer");
ApplySamplers();
// Note: ibuf binding is stored in the VAO, so call this after binding the fmt.
curIBuffer_->Bind(curIBufferOffset_);
renderManager_.DrawIndexed(curPipeline_->prim, vertexCount, GL_UNSIGNED_INT, (void *)(intptr_t)offset);
renderManager_.BindVertexBuffer(curPipeline_->inputLayout->inputLayout_, curVBuffers_[0]->buffer_, curVBufferOffsets_[0]);
renderManager_.BindIndexBuffer(curIBuffer_->buffer_);
renderManager_.DrawIndexed(curPipeline_->prim, vertexCount, GL_UNSIGNED_INT, (void *)(intptr_t)curIBufferOffset_);
}
void OpenGLContext::DrawUP(const void *vdata, int vertexCount) {
@ -1125,9 +1116,7 @@ void OpenGLContext::DrawUP(const void *vdata, int vertexCount) {
ApplySamplers();
renderManager_.BindVertexBuffer(buf);
renderManager_.BindInputLayout(curPipeline_->inputLayout->inputLayout_, offset);
renderManager_.BindVertexBuffer(curPipeline_->inputLayout->inputLayout_, buf, offset);
renderManager_.Draw(curPipeline_->prim, 0, vertexCount);
}