mirror of
https://github.com/overte-org/overte.git
synced 2025-04-18 00:26:33 +02:00
Working on breaking up transfers and draws
This commit is contained in:
parent
b726769f15
commit
e94cff594d
4 changed files with 158 additions and 53 deletions
|
@ -11,6 +11,8 @@
|
|||
#include "GLBackendShared.h"
|
||||
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
#include <list>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
using namespace gpu;
|
||||
|
@ -105,10 +107,10 @@ Backend* GLBackend::createBackend() {
|
|||
|
||||
GLBackend::GLBackend() :
|
||||
_input(),
|
||||
_transform(),
|
||||
_pipeline(),
|
||||
_output()
|
||||
{
|
||||
glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &_uboAlignment);
|
||||
initInput();
|
||||
initTransform();
|
||||
}
|
||||
|
@ -120,18 +122,99 @@ GLBackend::~GLBackend() {
|
|||
killTransform();
|
||||
}
|
||||
|
||||
void GLBackend::render(Batch& batch) {
|
||||
|
||||
uint32 numCommands = batch.getCommands().size();
|
||||
void GLBackend::renderPassTransfer(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 (unsigned int i = 0; i < numCommands; i++) {
|
||||
CommandCall call = _commandCalls[(*command)];
|
||||
(this->*(call))(batch, *offset);
|
||||
_transform._cameraTransforms.resize(0);
|
||||
_transform._cameraTransforms.push_back(TransformCamera());
|
||||
_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++;
|
||||
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) {
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
#include <assert.h>
|
||||
#include <functional>
|
||||
#include <bitset>
|
||||
#include <queue>
|
||||
#include <utility>
|
||||
|
||||
#include "GPUConfig.h"
|
||||
|
||||
|
@ -239,6 +241,9 @@ public:
|
|||
void getStats(Stats& stats) const { stats = _stats; }
|
||||
|
||||
protected:
|
||||
void renderPassTransfer(Batch& batch);
|
||||
void renderPassDraw(Batch& batch);
|
||||
|
||||
Stats _stats;
|
||||
|
||||
// Draw Stage
|
||||
|
@ -305,34 +310,36 @@ protected:
|
|||
// Synchronize the state cache of this Backend with the actual real state of the GL Context
|
||||
void syncTransformStateCache();
|
||||
void updateTransform();
|
||||
void preUpdateTransform();
|
||||
void resetTransformStage();
|
||||
struct TransformStageState {
|
||||
TransformObject _transformObject;
|
||||
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 _view;
|
||||
Mat4 _projection;
|
||||
Vec4i _viewport;
|
||||
bool _invalidModel;
|
||||
bool _invalidView;
|
||||
bool _invalidProj;
|
||||
bool _invalidViewport;
|
||||
Vec4i _viewport{ 0, 0, 1, 1 };
|
||||
bool _invalidModel{true};
|
||||
bool _invalidView{false};
|
||||
bool _invalidProj{false};
|
||||
bool _invalidViewport{ false };
|
||||
|
||||
TransformStageState() :
|
||||
_transformObjectBuffer(0),
|
||||
_transformCameraBuffer(0),
|
||||
_model(),
|
||||
_view(),
|
||||
_projection(),
|
||||
_viewport(0,0,1,1),
|
||||
_invalidModel(true),
|
||||
_invalidView(true),
|
||||
_invalidProj(false),
|
||||
_invalidViewport(false) {}
|
||||
using Pair = std::pair<size_t, size_t>;
|
||||
using List = std::list<Pair>;
|
||||
List _cameraOffsets;
|
||||
List _objectOffsets;
|
||||
} _transform;
|
||||
|
||||
int32_t _uboAlignment{ 0 };
|
||||
|
||||
|
||||
// Uniform Stage
|
||||
void do_setUniformBuffer(Batch& batch, uint32 paramOffset);
|
||||
|
||||
|
@ -359,6 +366,7 @@ protected:
|
|||
{}
|
||||
|
||||
} _resource;
|
||||
size_t _commandIndex{ 0 };
|
||||
|
||||
// Pipeline Stage
|
||||
void do_setPipeline(Batch& batch, uint32 paramOffset);
|
||||
|
|
|
@ -43,14 +43,14 @@ void GLBackend::do_setViewportTransform(Batch& batch, uint32 paramOffset) {
|
|||
void GLBackend::initTransform() {
|
||||
glGenBuffers(1, &_transform._transformObjectBuffer);
|
||||
glGenBuffers(1, &_transform._transformCameraBuffer);
|
||||
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, _transform._transformObjectBuffer);
|
||||
glBufferData(GL_UNIFORM_BUFFER, sizeof(_transform._transformObject), (const void*) &_transform._transformObject, GL_DYNAMIC_DRAW);
|
||||
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, _transform._transformCameraBuffer);
|
||||
glBufferData(GL_UNIFORM_BUFFER, sizeof(_transform._transformCamera), (const void*) &_transform._transformCamera, GL_DYNAMIC_DRAW);
|
||||
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, 0);
|
||||
size_t cameraSize = sizeof(TransformCamera);
|
||||
while (_transform._cameraUboSize < cameraSize) {
|
||||
_transform._cameraUboSize += _uboAlignment;
|
||||
}
|
||||
size_t objectSize = sizeof(TransformObject);
|
||||
while (_transform._objectUboSize < objectSize) {
|
||||
_transform._objectUboSize += _uboAlignment;
|
||||
}
|
||||
}
|
||||
|
||||
void GLBackend::killTransform() {
|
||||
|
@ -72,7 +72,7 @@ void GLBackend::syncTransformStateCache() {
|
|||
_transform._model.setIdentity();
|
||||
}
|
||||
|
||||
void GLBackend::updateTransform() {
|
||||
void GLBackend::preUpdateTransform() {
|
||||
// Check all the dirty flags and update the state accordingly
|
||||
if (_transform._invalidViewport) {
|
||||
_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);
|
||||
_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) {
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, TRANSFORM_CAMERA_SLOT, 0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, _transform._transformCameraBuffer);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(_transform._transformCamera), (const void*)&_transform._transformCamera);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
CHECK_GL_ERROR();
|
||||
_transform._cameraOffsets.push_back(TransformStageState::Pair(_commandIndex, _transform._cameraUboSize * _transform._cameraTransforms.size()));
|
||||
_transform._cameraTransforms.push_back(_transform._transformCamera);
|
||||
}
|
||||
|
||||
if (_transform._invalidModel) {
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, TRANSFORM_OBJECT_SLOT, 0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, _transform._transformObjectBuffer);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(_transform._transformObject), (const void*) &_transform._transformObject);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
CHECK_GL_ERROR();
|
||||
_transform._objectOffsets.push_back(TransformStageState::Pair(_commandIndex, _transform._objectUboSize * _transform._objectTransforms.size()));
|
||||
_transform._objectTransforms.push_back(_transform._transformObject);
|
||||
}
|
||||
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, TRANSFORM_OBJECT_SLOT, _transform._transformObjectBuffer);
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, TRANSFORM_CAMERA_SLOT, _transform._transformCameraBuffer);
|
||||
CHECK_GL_ERROR();
|
||||
|
||||
// Flags are clean
|
||||
_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() {
|
||||
|
||||
}
|
||||
|
|
|
@ -25,14 +25,14 @@ struct TransformCamera {
|
|||
vec4 _viewport;
|
||||
};
|
||||
|
||||
uniform transformObjectBuffer {
|
||||
layout(std140) uniform transformObjectBuffer {
|
||||
TransformObject _object;
|
||||
};
|
||||
TransformObject getTransformObject() {
|
||||
return _object;
|
||||
}
|
||||
|
||||
uniform transformCameraBuffer {
|
||||
layout(std140) uniform transformCameraBuffer {
|
||||
TransformCamera _camera;
|
||||
};
|
||||
TransformCamera getTransformCamera() {
|
||||
|
|
Loading…
Reference in a new issue