mirror of
https://github.com/lubosz/overte.git
synced 2025-08-07 16:41:02 +02:00
Merge pull request #5539 from jherico/homer
Breaking up transfers and draw calls
This commit is contained in:
commit
0a8a43f8bd
4 changed files with 159 additions and 53 deletions
|
@ -11,6 +11,8 @@
|
||||||
#include "GLBackendShared.h"
|
#include "GLBackendShared.h"
|
||||||
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <queue>
|
||||||
|
#include <list>
|
||||||
#include <glm/gtc/type_ptr.hpp>
|
#include <glm/gtc/type_ptr.hpp>
|
||||||
|
|
||||||
using namespace gpu;
|
using namespace gpu;
|
||||||
|
@ -105,10 +107,10 @@ Backend* GLBackend::createBackend() {
|
||||||
|
|
||||||
GLBackend::GLBackend() :
|
GLBackend::GLBackend() :
|
||||||
_input(),
|
_input(),
|
||||||
_transform(),
|
|
||||||
_pipeline(),
|
_pipeline(),
|
||||||
_output()
|
_output()
|
||||||
{
|
{
|
||||||
|
glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &_uboAlignment);
|
||||||
initInput();
|
initInput();
|
||||||
initTransform();
|
initTransform();
|
||||||
}
|
}
|
||||||
|
@ -120,18 +122,99 @@ GLBackend::~GLBackend() {
|
||||||
killTransform();
|
killTransform();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLBackend::render(Batch& batch) {
|
void GLBackend::renderPassTransfer(Batch& batch) {
|
||||||
|
const size_t numCommands = batch.getCommands().size();
|
||||||
uint32 numCommands = batch.getCommands().size();
|
|
||||||
const Batch::Commands::value_type* command = batch.getCommands().data();
|
const Batch::Commands::value_type* command = batch.getCommands().data();
|
||||||
const Batch::CommandOffsets::value_type* offset = batch.getCommandOffsets().data();
|
const Batch::CommandOffsets::value_type* offset = batch.getCommandOffsets().data();
|
||||||
|
|
||||||
for (unsigned int i = 0; i < numCommands; i++) {
|
_transform._cameraTransforms.resize(0);
|
||||||
CommandCall call = _commandCalls[(*command)];
|
_transform._cameraTransforms.push_back(TransformCamera());
|
||||||
(this->*(call))(batch, *offset);
|
_transform._cameraOffsets.clear();
|
||||||
|
_transform._cameraOffsets.push_back(TransformStageState::Pair(0, 0));
|
||||||
|
|
||||||
|
_transform._objectTransforms.push_back(TransformObject());
|
||||||
|
_transform._objectOffsets.push_back(TransformStageState::Pair(0, 0));
|
||||||
|
_transform._objectOffsets.clear();
|
||||||
|
_transform._objectTransforms.resize(0);
|
||||||
|
|
||||||
|
_commandIndex = 0;
|
||||||
|
preUpdateTransform();
|
||||||
|
|
||||||
|
int drawCount = 0;
|
||||||
|
for (_commandIndex = 0; _commandIndex < numCommands; ++_commandIndex) {
|
||||||
|
switch (*command) {
|
||||||
|
case Batch::COMMAND_draw:
|
||||||
|
case Batch::COMMAND_drawIndexed:
|
||||||
|
case Batch::COMMAND_drawInstanced:
|
||||||
|
case Batch::COMMAND_drawIndexedInstanced:
|
||||||
|
preUpdateTransform();
|
||||||
|
++drawCount;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Batch::COMMAND_setModelTransform:
|
||||||
|
case Batch::COMMAND_setViewportTransform:
|
||||||
|
case Batch::COMMAND_setViewTransform:
|
||||||
|
case Batch::COMMAND_setProjectionTransform:
|
||||||
|
{
|
||||||
|
CommandCall call = _commandCalls[(*command)];
|
||||||
|
(this->*(call))(batch, *offset);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
command++;
|
command++;
|
||||||
offset++;
|
offset++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static QByteArray bufferData;
|
||||||
|
glBindBuffer(GL_UNIFORM_BUFFER, _transform._transformCameraBuffer);
|
||||||
|
bufferData.resize(_transform._cameraUboSize * _transform._cameraTransforms.size());
|
||||||
|
for (size_t i = 0; i < _transform._cameraTransforms.size(); ++i) {
|
||||||
|
memcpy(bufferData.data() + (_transform._cameraUboSize * i), &_transform._cameraTransforms[i], sizeof(TransformCamera));
|
||||||
|
}
|
||||||
|
glBufferData(GL_UNIFORM_BUFFER, bufferData.size(), bufferData.data(), GL_DYNAMIC_DRAW);
|
||||||
|
glBindBuffer(GL_UNIFORM_BUFFER, _transform._transformObjectBuffer);
|
||||||
|
bufferData.resize(_transform._objectUboSize * _transform._objectTransforms.size());
|
||||||
|
for (size_t i = 0; i < _transform._objectTransforms.size(); ++i) {
|
||||||
|
memcpy(bufferData.data() + (_transform._objectUboSize * i), &_transform._objectTransforms[i], sizeof(TransformObject));
|
||||||
|
}
|
||||||
|
glBufferData(GL_UNIFORM_BUFFER, bufferData.size(), bufferData.data(), GL_DYNAMIC_DRAW);
|
||||||
|
glBindBuffer(GL_UNIFORM_BUFFER, 0);
|
||||||
|
CHECK_GL_ERROR();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLBackend::renderPassDraw(Batch& batch) {
|
||||||
|
const size_t numCommands = batch.getCommands().size();
|
||||||
|
const Batch::Commands::value_type* command = batch.getCommands().data();
|
||||||
|
const Batch::CommandOffsets::value_type* offset = batch.getCommandOffsets().data();
|
||||||
|
for (_commandIndex = 0; _commandIndex < numCommands; ++_commandIndex) {
|
||||||
|
switch (*command) {
|
||||||
|
// Ignore these commands on this pass, taken care of in the transfer pass
|
||||||
|
case Batch::COMMAND_setModelTransform:
|
||||||
|
case Batch::COMMAND_setViewportTransform:
|
||||||
|
case Batch::COMMAND_setViewTransform:
|
||||||
|
case Batch::COMMAND_setProjectionTransform:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
CommandCall call = _commandCalls[(*command)];
|
||||||
|
(this->*(call))(batch, *offset);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
command++;
|
||||||
|
offset++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLBackend::render(Batch& batch) {
|
||||||
|
renderPassTransfer(batch);
|
||||||
|
renderPassDraw(batch);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLBackend::checkGLError(const char* name) {
|
bool GLBackend::checkGLError(const char* name) {
|
||||||
|
|
|
@ -14,6 +14,9 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
|
#include <queue>
|
||||||
|
#include <utility>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
#include "GPUConfig.h"
|
#include "GPUConfig.h"
|
||||||
|
|
||||||
|
@ -239,6 +242,9 @@ public:
|
||||||
void getStats(Stats& stats) const { stats = _stats; }
|
void getStats(Stats& stats) const { stats = _stats; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
void renderPassTransfer(Batch& batch);
|
||||||
|
void renderPassDraw(Batch& batch);
|
||||||
|
|
||||||
Stats _stats;
|
Stats _stats;
|
||||||
|
|
||||||
// Draw Stage
|
// Draw Stage
|
||||||
|
@ -305,34 +311,36 @@ protected:
|
||||||
// Synchronize the state cache of this Backend with the actual real state of the GL Context
|
// Synchronize the state cache of this Backend with the actual real state of the GL Context
|
||||||
void syncTransformStateCache();
|
void syncTransformStateCache();
|
||||||
void updateTransform();
|
void updateTransform();
|
||||||
|
void preUpdateTransform();
|
||||||
void resetTransformStage();
|
void resetTransformStage();
|
||||||
struct TransformStageState {
|
struct TransformStageState {
|
||||||
TransformObject _transformObject;
|
TransformObject _transformObject;
|
||||||
TransformCamera _transformCamera;
|
TransformCamera _transformCamera;
|
||||||
GLuint _transformObjectBuffer;
|
|
||||||
GLuint _transformCameraBuffer;
|
std::vector<TransformObject> _objectTransforms;
|
||||||
|
std::vector<TransformCamera> _cameraTransforms;
|
||||||
|
size_t _cameraUboSize{ 0 };
|
||||||
|
size_t _objectUboSize{ 0 };
|
||||||
|
GLuint _transformObjectBuffer{ 0 };
|
||||||
|
GLuint _transformCameraBuffer{ 0 };
|
||||||
Transform _model;
|
Transform _model;
|
||||||
Transform _view;
|
Transform _view;
|
||||||
Mat4 _projection;
|
Mat4 _projection;
|
||||||
Vec4i _viewport;
|
Vec4i _viewport{ 0, 0, 1, 1 };
|
||||||
bool _invalidModel;
|
bool _invalidModel{true};
|
||||||
bool _invalidView;
|
bool _invalidView{false};
|
||||||
bool _invalidProj;
|
bool _invalidProj{false};
|
||||||
bool _invalidViewport;
|
bool _invalidViewport{ false };
|
||||||
|
|
||||||
TransformStageState() :
|
using Pair = std::pair<size_t, size_t>;
|
||||||
_transformObjectBuffer(0),
|
using List = std::list<Pair>;
|
||||||
_transformCameraBuffer(0),
|
List _cameraOffsets;
|
||||||
_model(),
|
List _objectOffsets;
|
||||||
_view(),
|
|
||||||
_projection(),
|
|
||||||
_viewport(0,0,1,1),
|
|
||||||
_invalidModel(true),
|
|
||||||
_invalidView(true),
|
|
||||||
_invalidProj(false),
|
|
||||||
_invalidViewport(false) {}
|
|
||||||
} _transform;
|
} _transform;
|
||||||
|
|
||||||
|
int32_t _uboAlignment{ 0 };
|
||||||
|
|
||||||
|
|
||||||
// Uniform Stage
|
// Uniform Stage
|
||||||
void do_setUniformBuffer(Batch& batch, uint32 paramOffset);
|
void do_setUniformBuffer(Batch& batch, uint32 paramOffset);
|
||||||
|
|
||||||
|
@ -359,6 +367,7 @@ protected:
|
||||||
{}
|
{}
|
||||||
|
|
||||||
} _resource;
|
} _resource;
|
||||||
|
size_t _commandIndex{ 0 };
|
||||||
|
|
||||||
// Pipeline Stage
|
// Pipeline Stage
|
||||||
void do_setPipeline(Batch& batch, uint32 paramOffset);
|
void do_setPipeline(Batch& batch, uint32 paramOffset);
|
||||||
|
|
|
@ -43,14 +43,14 @@ void GLBackend::do_setViewportTransform(Batch& batch, uint32 paramOffset) {
|
||||||
void GLBackend::initTransform() {
|
void GLBackend::initTransform() {
|
||||||
glGenBuffers(1, &_transform._transformObjectBuffer);
|
glGenBuffers(1, &_transform._transformObjectBuffer);
|
||||||
glGenBuffers(1, &_transform._transformCameraBuffer);
|
glGenBuffers(1, &_transform._transformCameraBuffer);
|
||||||
|
size_t cameraSize = sizeof(TransformCamera);
|
||||||
glBindBuffer(GL_UNIFORM_BUFFER, _transform._transformObjectBuffer);
|
while (_transform._cameraUboSize < cameraSize) {
|
||||||
glBufferData(GL_UNIFORM_BUFFER, sizeof(_transform._transformObject), (const void*) &_transform._transformObject, GL_DYNAMIC_DRAW);
|
_transform._cameraUboSize += _uboAlignment;
|
||||||
|
}
|
||||||
glBindBuffer(GL_UNIFORM_BUFFER, _transform._transformCameraBuffer);
|
size_t objectSize = sizeof(TransformObject);
|
||||||
glBufferData(GL_UNIFORM_BUFFER, sizeof(_transform._transformCamera), (const void*) &_transform._transformCamera, GL_DYNAMIC_DRAW);
|
while (_transform._objectUboSize < objectSize) {
|
||||||
|
_transform._objectUboSize += _uboAlignment;
|
||||||
glBindBuffer(GL_UNIFORM_BUFFER, 0);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLBackend::killTransform() {
|
void GLBackend::killTransform() {
|
||||||
|
@ -72,7 +72,7 @@ void GLBackend::syncTransformStateCache() {
|
||||||
_transform._model.setIdentity();
|
_transform._model.setIdentity();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLBackend::updateTransform() {
|
void GLBackend::preUpdateTransform() {
|
||||||
// Check all the dirty flags and update the state accordingly
|
// Check all the dirty flags and update the state accordingly
|
||||||
if (_transform._invalidViewport) {
|
if (_transform._invalidViewport) {
|
||||||
_transform._transformCamera._viewport = glm::vec4(_transform._viewport);
|
_transform._transformCamera._viewport = glm::vec4(_transform._viewport);
|
||||||
|
@ -98,33 +98,47 @@ void GLBackend::updateTransform() {
|
||||||
viewUntranslated[3] = Vec4(0.0f, 0.0f, 0.0f, 1.0f);
|
viewUntranslated[3] = Vec4(0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
_transform._transformCamera._projectionViewUntranslated = _transform._transformCamera._projection * viewUntranslated;
|
_transform._transformCamera._projectionViewUntranslated = _transform._transformCamera._projection * viewUntranslated;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: WE need a ring buffer to do effcient dynamic updates here
|
|
||||||
// FOr now let's just do that bind and update sequence
|
|
||||||
if (_transform._invalidView || _transform._invalidProj || _transform._invalidViewport) {
|
if (_transform._invalidView || _transform._invalidProj || _transform._invalidViewport) {
|
||||||
glBindBufferBase(GL_UNIFORM_BUFFER, TRANSFORM_CAMERA_SLOT, 0);
|
_transform._cameraOffsets.push_back(TransformStageState::Pair(_commandIndex, _transform._cameraUboSize * _transform._cameraTransforms.size()));
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, _transform._transformCameraBuffer);
|
_transform._cameraTransforms.push_back(_transform._transformCamera);
|
||||||
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(_transform._transformCamera), (const void*)&_transform._transformCamera);
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
||||||
CHECK_GL_ERROR();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_transform._invalidModel) {
|
if (_transform._invalidModel) {
|
||||||
glBindBufferBase(GL_UNIFORM_BUFFER, TRANSFORM_OBJECT_SLOT, 0);
|
_transform._objectOffsets.push_back(TransformStageState::Pair(_commandIndex, _transform._objectUboSize * _transform._objectTransforms.size()));
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, _transform._transformObjectBuffer);
|
_transform._objectTransforms.push_back(_transform._transformObject);
|
||||||
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(_transform._transformObject), (const void*) &_transform._transformObject);
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
||||||
CHECK_GL_ERROR();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
glBindBufferBase(GL_UNIFORM_BUFFER, TRANSFORM_OBJECT_SLOT, _transform._transformObjectBuffer);
|
|
||||||
glBindBufferBase(GL_UNIFORM_BUFFER, TRANSFORM_CAMERA_SLOT, _transform._transformCameraBuffer);
|
|
||||||
CHECK_GL_ERROR();
|
|
||||||
|
|
||||||
// Flags are clean
|
// Flags are clean
|
||||||
_transform._invalidView = _transform._invalidProj = _transform._invalidModel = _transform._invalidViewport = false;
|
_transform._invalidView = _transform._invalidProj = _transform._invalidModel = _transform._invalidViewport = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GLBackend::updateTransform() {
|
||||||
|
int offset = -1;
|
||||||
|
while (!_transform._objectOffsets.empty() && _commandIndex >= _transform._objectOffsets.front().first) {
|
||||||
|
offset = _transform._objectOffsets.front().second;
|
||||||
|
_transform._objectOffsets.pop_front();
|
||||||
|
}
|
||||||
|
if (offset >= 0) {
|
||||||
|
glBindBufferRange(GL_UNIFORM_BUFFER, TRANSFORM_OBJECT_SLOT,
|
||||||
|
_transform._transformObjectBuffer,
|
||||||
|
offset, sizeof(Backend::TransformObject));
|
||||||
|
}
|
||||||
|
|
||||||
|
offset = -1;
|
||||||
|
while (!_transform._cameraOffsets.empty() && _commandIndex >= _transform._cameraOffsets.front().first) {
|
||||||
|
offset = _transform._cameraOffsets.front().second;
|
||||||
|
_transform._cameraOffsets.pop_front();
|
||||||
|
}
|
||||||
|
if (offset >= 0) {
|
||||||
|
glBindBufferRange(GL_UNIFORM_BUFFER, TRANSFORM_CAMERA_SLOT,
|
||||||
|
_transform._transformCameraBuffer,
|
||||||
|
offset, sizeof(Backend::TransformObject));
|
||||||
|
}
|
||||||
|
|
||||||
|
(void)CHECK_GL_ERROR();
|
||||||
|
}
|
||||||
|
|
||||||
void GLBackend::resetTransformStage() {
|
void GLBackend::resetTransformStage() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,14 +25,14 @@ struct TransformCamera {
|
||||||
vec4 _viewport;
|
vec4 _viewport;
|
||||||
};
|
};
|
||||||
|
|
||||||
uniform transformObjectBuffer {
|
layout(std140) uniform transformObjectBuffer {
|
||||||
TransformObject _object;
|
TransformObject _object;
|
||||||
};
|
};
|
||||||
TransformObject getTransformObject() {
|
TransformObject getTransformObject() {
|
||||||
return _object;
|
return _object;
|
||||||
}
|
}
|
||||||
|
|
||||||
uniform transformCameraBuffer {
|
layout(std140) uniform transformCameraBuffer {
|
||||||
TransformCamera _camera;
|
TransformCamera _camera;
|
||||||
};
|
};
|
||||||
TransformCamera getTransformCamera() {
|
TransformCamera getTransformCamera() {
|
||||||
|
|
Loading…
Reference in a new issue