From e94cff594d723b7a881531668606dd90cb5ba337 Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Fri, 7 Aug 2015 14:49:51 -0700 Subject: [PATCH 1/3] Working on breaking up transfers and draws --- libraries/gpu/src/gpu/GLBackend.cpp | 97 ++++++++++++++++++-- libraries/gpu/src/gpu/GLBackend.h | 44 +++++---- libraries/gpu/src/gpu/GLBackendTransform.cpp | 66 +++++++------ libraries/gpu/src/gpu/Transform.slh | 4 +- 4 files changed, 158 insertions(+), 53 deletions(-) diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index f0029d15a3..4afd2ba940 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -11,6 +11,8 @@ #include "GLBackendShared.h" #include +#include +#include #include 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) { diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index f3e3b1cc7c..cfa2cd706d 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -14,6 +14,8 @@ #include #include #include +#include +#include #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 _objectTransforms; + std::vector _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; + using List = std::list; + 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); diff --git a/libraries/gpu/src/gpu/GLBackendTransform.cpp b/libraries/gpu/src/gpu/GLBackendTransform.cpp index 5099e3ed2a..a9f30fd0fa 100755 --- a/libraries/gpu/src/gpu/GLBackendTransform.cpp +++ b/libraries/gpu/src/gpu/GLBackendTransform.cpp @@ -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() { } diff --git a/libraries/gpu/src/gpu/Transform.slh b/libraries/gpu/src/gpu/Transform.slh index 49c2455c8a..b492b4ef24 100644 --- a/libraries/gpu/src/gpu/Transform.slh +++ b/libraries/gpu/src/gpu/Transform.slh @@ -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() { From f539e95e5345986024c07d7c310ff43a6e6f9b7a Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 10 Aug 2015 23:27:02 -0700 Subject: [PATCH 2/3] Fixing includes --- libraries/gpu/src/gpu/GLBackend.h | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index cfa2cd706d..455240deb8 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -16,6 +16,7 @@ #include #include #include +#include #include "GPUConfig.h" From 3595f6a8a023ade5d2bf7485a24a0b7678ad86e0 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 11 Aug 2015 14:06:35 -0700 Subject: [PATCH 3/3] Fixing bad success macro for the Oculus SDK on windows --- .../src/display-plugins/oculus/OculusBaseDisplayPlugin.h | 4 ---- .../src/display-plugins/oculus/OculusHelpers.h | 4 ++++ 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/display-plugins/src/display-plugins/oculus/OculusBaseDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/oculus/OculusBaseDisplayPlugin.h index b338e2709b..e376ae12ba 100644 --- a/libraries/display-plugins/src/display-plugins/oculus/OculusBaseDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/oculus/OculusBaseDisplayPlugin.h @@ -24,7 +24,3 @@ public: virtual glm::mat4 getHeadPose() const override; }; - -#if (OVR_MAJOR_VERSION < 6) -#define OVR_SUCCESS(x) x -#endif diff --git a/libraries/display-plugins/src/display-plugins/oculus/OculusHelpers.h b/libraries/display-plugins/src/display-plugins/oculus/OculusHelpers.h index d4e1bec312..31b7c246af 100644 --- a/libraries/display-plugins/src/display-plugins/oculus/OculusHelpers.h +++ b/libraries/display-plugins/src/display-plugins/oculus/OculusHelpers.h @@ -12,6 +12,10 @@ #include #include +#if (OVR_MAJOR_VERSION < 6) +#define OVR_SUCCESS(x) x +#endif + // Convenience method for looping over each eye with a lambda template inline void ovr_for_each_eye(Function function) {