Working on breaking up transfers and draws

This commit is contained in:
Bradley Austin Davis 2015-08-07 14:49:51 -07:00 committed by Brad Davis
parent b726769f15
commit e94cff594d
4 changed files with 158 additions and 53 deletions

View file

@ -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) {

View file

@ -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);

View file

@ -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() {
}

View file

@ -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() {