From 440464f884ee6042dcb7fa30d4b02691441ddf84 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 14 Jul 2015 18:35:11 -0700 Subject: [PATCH] Trying to improve the GLBackendINtpu cahce a bit and thinking about moving to core profile --- interface/src/ui/ApplicationOverlay.cpp | 2 +- libraries/gpu/src/gpu/Batch.h | 5 +- libraries/gpu/src/gpu/GLBackend.cpp | 2 + libraries/gpu/src/gpu/GLBackend.h | 28 ++- libraries/gpu/src/gpu/GLBackendInput.cpp | 232 ++++++++++++------- libraries/gpu/src/gpu/GLBackendShader.cpp | 19 +- libraries/gpu/src/gpu/GLBackendTransform.cpp | 9 +- 7 files changed, 202 insertions(+), 95 deletions(-) diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 44904a8655..c28aa272ea 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -109,7 +109,7 @@ void ApplicationOverlay::renderQmlUi(RenderArgs* renderArgs) { batch._glBindTexture(GL_TEXTURE_2D, _uiTexture); geometryCache->renderUnitQuad(batch, glm::vec4(1)); renderArgs->_context->syncCache(); - renderArgs->_context->render(batch); + // renderArgs->_context->render(batch); } } diff --git a/libraries/gpu/src/gpu/Batch.h b/libraries/gpu/src/gpu/Batch.h index abd9982cd0..bf6883e3a9 100644 --- a/libraries/gpu/src/gpu/Batch.h +++ b/libraries/gpu/src/gpu/Batch.h @@ -40,11 +40,8 @@ namespace gpu { enum ReservedSlot { -/* TRANSFORM_OBJECT_SLOT = 6, + TRANSFORM_OBJECT_SLOT = 6, TRANSFORM_CAMERA_SLOT = 7, - */ - TRANSFORM_OBJECT_SLOT = 1, - TRANSFORM_CAMERA_SLOT = 2, }; class Batch { diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index b79f506544..adbef7cb31 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -87,10 +87,12 @@ GLBackend::GLBackend() : _pipeline(), _output() { + initInput(); initTransform(); } GLBackend::~GLBackend() { + killInput(); killTransform(); } diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index 8df55a7f67..491897b281 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -228,7 +228,21 @@ public: void do_setStateColorWriteMask(uint32 mask); + // Repporting stats of the context + class Stats { + public: + int _ISNumFormatChanges = 0; + int _ISNumInputBufferChanges = 0; + int _ISNumIndexBufferChanges = 0; + + Stats() {} + Stats(const Stats& stats) = default; + }; + + void getStats(Stats& stats) const { stats = _stats; } + protected: + Stats _stats; // Draw Stage void do_draw(Batch& batch, uint32 paramOffset); @@ -242,12 +256,13 @@ protected: void do_setInputFormat(Batch& batch, uint32 paramOffset); void do_setInputBuffer(Batch& batch, uint32 paramOffset); void do_setIndexBuffer(Batch& batch, uint32 paramOffset); - - // Synchronize the state cache of this Backend with the actual real state of the GL Context + + void initInput(); + void killInput(); void syncInputStateCache(); void updateInput(); struct InputStageState { - bool _invalidFormat; + bool _invalidFormat = true; Stream::FormatPointer _format; typedef std::bitset BuffersState; @@ -256,6 +271,7 @@ protected: Buffers _buffers; Offsets _bufferOffsets; Offsets _bufferStrides; + std::vector _bufferVBOs; BufferPointer _indexBuffer; Offset _indexBufferOffset; @@ -264,6 +280,8 @@ protected: typedef std::bitset ActivationCache; ActivationCache _attributeActivation; + GLuint _defaultVAO; + InputStageState() : _invalidFormat(true), _format(0), @@ -271,10 +289,12 @@ protected: _buffers(_buffersState.size(), BufferPointer(0)), _bufferOffsets(_buffersState.size(), 0), _bufferStrides(_buffersState.size(), 0), + _bufferVBOs(_buffersState.size(), 0), _indexBuffer(0), _indexBufferOffset(0), _indexBufferType(UINT32), - _attributeActivation(0) + _attributeActivation(0), + _defaultVAO(0) {} } _input; diff --git a/libraries/gpu/src/gpu/GLBackendInput.cpp b/libraries/gpu/src/gpu/GLBackendInput.cpp index aac7b56bc2..34b1b1761f 100755 --- a/libraries/gpu/src/gpu/GLBackendInput.cpp +++ b/libraries/gpu/src/gpu/GLBackendInput.cpp @@ -28,13 +28,39 @@ void GLBackend::do_setInputBuffer(Batch& batch, uint32 paramOffset) { uint32 channel = batch._params[paramOffset + 3]._uint; if (channel < getNumInputBuffers()) { - _input._buffers[channel] = buffer; - _input._bufferOffsets[channel] = offset; - _input._bufferStrides[channel] = stride; - _input._buffersState.set(channel); + bool isModified = false; + if (_input._buffers[channel] != buffer) { + _input._buffers[channel] = buffer; + + GLuint vbo = 0; + if (buffer) { + vbo = getBufferID((*buffer)); + } + _input._bufferVBOs[channel] = vbo; + + isModified = true; + } + + if (_input._bufferOffsets[channel] != offset) { + _input._bufferOffsets[channel] = offset; + isModified = true; + } + + if (_input._bufferStrides[channel] != stride) { + _input._bufferStrides[channel] = stride; + isModified = true; + } + + if (isModified) { + _input._buffersState.set(channel); + } } } +#define NOT_SUPPORT_VAO +#if defined(SUPPORT_VAO) +#else + #define SUPPORT_LEGACY_OPENGL #if defined(SUPPORT_LEGACY_OPENGL) static const int NUM_CLASSIC_ATTRIBS = Stream::TANGENT; @@ -45,24 +71,120 @@ static const GLenum attributeSlotToClassicAttribName[NUM_CLASSIC_ATTRIBS] = { GL_TEXTURE_COORD_ARRAY }; #endif +#endif + +void GLBackend::initInput() { +#if defined(SUPPORT_VAO) + if(!_input._defaultVAO) { + glGenVertexArrays(1, &_input._defaultVAO); + } + glBindVertexArray(_input._defaultVAO); + (void) CHECK_GL_ERROR(); +#endif +} + +void GLBackend::killInput() { +#if defined(SUPPORT_VAO) + glBindVertexArray(0); + if(_input._defaultVAO) { + glDeleteVertexArrays(1, &_input._defaultVAO); + } + (void) CHECK_GL_ERROR(); +#endif +} void GLBackend::syncInputStateCache() { +#if defined(SUPPORT_VAO) for (int i = 0; i < NUM_CLASSIC_ATTRIBS; i++) { _input._attributeActivation[i] = glIsEnabled(attributeSlotToClassicAttribName[i]); } + //_input._defaultVAO + glBindVertexArray(_input._defaultVAO); +#else + int i = 0; +#if defined(SUPPORT_LEGACY_OPENGL) + for (; i < NUM_CLASSIC_ATTRIBS; i++) { + _input._attributeActivation[i] = glIsEnabled(attributeSlotToClassicAttribName[i]); + } +#endif + for (; i < _input._attributeActivation.size(); i++) { + GLint active = 0; + glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &active); + _input._attributeActivation[i] = active; + } +#endif } void GLBackend::updateInput() { +#if defined(SUPPORT_VAO) + if (_input._invalidFormat) { + + InputStageState::ActivationCache newActivation; + + // Assign the vertex format required + if (_input._format) { + for (auto& it : _input._format->getAttributes()) { + const Stream::Attribute& attrib = (it).second; + newActivation.set(attrib._slot); + glVertexAttribFormat( + attrib._slot, + attrib._element.getDimensionCount(), + _elementTypeToGLType[attrib._element.getType()], + attrib._element.isNormalized(), + attrib._offset); + } + (void) CHECK_GL_ERROR(); + } + + // Manage Activation what was and what is expected now + for (int i = 0; i < newActivation.size(); i++) { + bool newState = newActivation[i]; + if (newState != _input._attributeActivation[i]) { + if (newState) { + glEnableVertexAttribArray(i); + } else { + glDisableVertexAttribArray(i); + } + _input._attributeActivation.flip(i); + } + } + (void) CHECK_GL_ERROR(); + + _input._invalidFormat = false; + _stats._ISNumFormatChanges++; + } + + if (_input._buffersState.any()) { + int numBuffers = _input._buffers.size(); + auto buffer = _input._buffers.data(); + auto vbo = _input._bufferVBOs.data(); + auto offset = _input._bufferOffsets.data(); + auto stride = _input._bufferStrides.data(); + + for (int bufferNum = 0; bufferNum < numBuffers; bufferNum++) { + if (_input._buffersState.test(bufferNum)) { + glBindVertexBuffer(bufferNum, (*vbo), (*offset), (*stride)); + } + buffer++; + vbo++; + offset++; + stride++; + } + _input._buffersState.reset(); + (void) CHECK_GL_ERROR(); + } +#else if (_input._invalidFormat || _input._buffersState.any()) { if (_input._invalidFormat) { InputStageState::ActivationCache newActivation; + _stats._ISNumFormatChanges++; + // Check expected activation if (_input._format) { - const Stream::Format::AttributeMap& attributes = _input._format->getAttributes(); - for (Stream::Format::AttributeMap::const_iterator it = attributes.begin(); it != attributes.end(); it++) { - const Stream::Attribute& attrib = (*it).second; + for (auto& it : _input._format->getAttributes()) { + const Stream::Attribute& attrib = (it).second; newActivation.set(attrib._slot); } } @@ -72,17 +194,15 @@ void GLBackend::updateInput() { bool newState = newActivation[i]; if (newState != _input._attributeActivation[i]) { #if defined(SUPPORT_LEGACY_OPENGL) - const bool useClientState = i < NUM_CLASSIC_ATTRIBS; -#else - const bool useClientState = false; -#endif - if (useClientState) { + if (i < NUM_CLASSIC_ATTRIBS) { if (newState) { glEnableClientState(attributeSlotToClassicAttribName[i]); } else { glDisableClientState(attributeSlotToClassicAttribName[i]); } - } else { + } else +#endif + { if (newState) { glEnableVertexAttribArray(i); } else { @@ -103,18 +223,23 @@ void GLBackend::updateInput() { const Offsets& strides = _input._bufferStrides; const Stream::Format::AttributeMap& attributes = _input._format->getAttributes(); + auto& inputChannels = _input._format->getChannels(); + _stats._ISNumInputBufferChanges++; - for (Stream::Format::ChannelMap::const_iterator channelIt = _input._format->getChannels().begin(); - channelIt != _input._format->getChannels().end(); - channelIt++) { - const Stream::Format::ChannelMap::value_type::second_type& channel = (*channelIt).second; - if ((*channelIt).first < buffers.size()) { - int bufferNum = (*channelIt).first; + GLuint boundVBO = 0; + for (auto& channelIt : inputChannels) { + const Stream::Format::ChannelMap::value_type::second_type& channel = (channelIt).second; + if ((channelIt).first < buffers.size()) { + int bufferNum = (channelIt).first; if (_input._buffersState.test(bufferNum) || _input._invalidFormat) { - GLuint vbo = gpu::GLBackend::getBufferID((*buffers[bufferNum])); - glBindBuffer(GL_ARRAY_BUFFER, vbo); - (void) CHECK_GL_ERROR(); + // GLuint vbo = gpu::GLBackend::getBufferID((*buffers[bufferNum])); + GLuint vbo = _input._bufferVBOs[bufferNum]; + if (boundVBO != vbo) { + glBindBuffer(GL_ARRAY_BUFFER, vbo); + (void) CHECK_GL_ERROR(); + boundVBO = vbo; + } _input._buffersState[bufferNum] = false; for (unsigned int i = 0; i < channel._slots.size(); i++) { @@ -126,9 +251,6 @@ void GLBackend::updateInput() { GLuint pointer = attrib._offset + offsets[bufferNum]; #if defined(SUPPORT_LEGACY_OPENGL) const bool useClientState = slot < NUM_CLASSIC_ATTRIBS; -#else - const bool useClientState = false; -#endif if (useClientState) { switch (slot) { case Stream::POSITION: @@ -144,7 +266,9 @@ void GLBackend::updateInput() { glTexCoordPointer(count, type, stride, reinterpret_cast(pointer)); break; }; - } else { + } else +#endif + { GLboolean isNormalized = attrib._element.isNormalized(); glVertexAttribPointer(slot, count, type, isNormalized, stride, reinterpret_cast(pointer)); @@ -158,61 +282,7 @@ void GLBackend::updateInput() { // everything format related should be in sync now _input._invalidFormat = false; } - -/* TODO: Fancy version GL4.4 - if (_needInputFormatUpdate) { - - InputActivationCache newActivation; - - // Assign the vertex format required - if (_inputFormat) { - const StreamFormat::AttributeMap& attributes = _inputFormat->getAttributes(); - for (StreamFormat::AttributeMap::const_iterator it = attributes.begin(); it != attributes.end(); it++) { - const StreamFormat::Attribute& attrib = (*it).second; - newActivation.set(attrib._slot); - glVertexAttribFormat( - attrib._slot, - attrib._element.getDimensionCount(), - _elementTypeToGLType[attrib._element.getType()], - attrib._element.isNormalized(), - attrib._stride); - } - CHECK_GL_ERROR(); - } - - // Manage Activation what was and what is expected now - for (int i = 0; i < newActivation.size(); i++) { - bool newState = newActivation[i]; - if (newState != _inputAttributeActivation[i]) { - if (newState) { - glEnableVertexAttribArray(i); - } else { - glDisableVertexAttribArray(i); - } - _inputAttributeActivation.flip(i); - } - } - CHECK_GL_ERROR(); - - _needInputFormatUpdate = false; - } - - if (_needInputStreamUpdate) { - if (_inputStream) { - const Stream::Buffers& buffers = _inputStream->getBuffers(); - const Stream::Offsets& offsets = _inputStream->getOffsets(); - const Stream::Strides& strides = _inputStream->getStrides(); - - for (int i = 0; i < buffers.size(); i++) { - GLuint vbo = gpu::GLBackend::getBufferID((*buffers[i])); - glBindVertexBuffer(i, vbo, offsets[i], strides[i]); - } - - CHECK_GL_ERROR(); - } - _needInputStreamUpdate = false; - } -*/ +#endif } diff --git a/libraries/gpu/src/gpu/GLBackendShader.cpp b/libraries/gpu/src/gpu/GLBackendShader.cpp index 7902275c27..fd5bed2e5e 100755 --- a/libraries/gpu/src/gpu/GLBackendShader.cpp +++ b/libraries/gpu/src/gpu/GLBackendShader.cpp @@ -41,21 +41,34 @@ void makeBindings(GLBackend::GLShader* shader) { glBindAttribLocation(glprogram, gpu::Stream::POSITION, "position"); } + loc = glGetAttribLocation(glprogram, "attribPosition"); + if (loc >= 0) { + glBindAttribLocation(glprogram, gpu::Stream::POSITION, "attribPosition"); + } + //Check for gpu specific attribute slotBindings loc = glGetAttribLocation(glprogram, "gl_Vertex"); if (loc >= 0) { - glBindAttribLocation(glprogram, gpu::Stream::POSITION, "position"); + glBindAttribLocation(glprogram, gpu::Stream::POSITION, "gl_Vertex"); } loc = glGetAttribLocation(glprogram, "normal"); if (loc >= 0) { glBindAttribLocation(glprogram, gpu::Stream::NORMAL, "normal"); } + loc = glGetAttribLocation(glprogram, "attribNormal"); + if (loc >= 0) { + glBindAttribLocation(glprogram, gpu::Stream::NORMAL, "attribNormal"); + } loc = glGetAttribLocation(glprogram, "color"); if (loc >= 0) { glBindAttribLocation(glprogram, gpu::Stream::COLOR, "color"); } + loc = glGetAttribLocation(glprogram, "attribColor"); + if (loc >= 0) { + glBindAttribLocation(glprogram, gpu::Stream::COLOR, "attribColor"); + } loc = glGetAttribLocation(glprogram, "texcoord"); if (loc >= 0) { @@ -75,6 +88,10 @@ void makeBindings(GLBackend::GLShader* shader) { if (loc >= 0) { glBindAttribLocation(glprogram, gpu::Stream::TEXCOORD1, "texcoord1"); } + loc = glGetAttribLocation(glprogram, "attribTexcoord1"); + if (loc >= 0) { + glBindAttribLocation(glprogram, gpu::Stream::TEXCOORD1, "texcoord1"); + } loc = glGetAttribLocation(glprogram, "clusterIndices"); if (loc >= 0) { diff --git a/libraries/gpu/src/gpu/GLBackendTransform.cpp b/libraries/gpu/src/gpu/GLBackendTransform.cpp index 48a42fe5f1..01229cb317 100755 --- a/libraries/gpu/src/gpu/GLBackendTransform.cpp +++ b/libraries/gpu/src/gpu/GLBackendTransform.cpp @@ -82,8 +82,6 @@ void GLBackend::syncTransformStateCache() { } void GLBackend::updateTransform() { - GLint originalMatrixMode; - glGetIntegerv(GL_MATRIX_MODE, &originalMatrixMode); // Check all the dirty flags and update the state accordingly if (_transform._invalidViewport) { _transform._transformCamera._viewport = glm::vec4(_transform._viewport); @@ -138,6 +136,9 @@ void GLBackend::updateTransform() { #if (GPU_TRANSFORM_PROFILE == GPU_LEGACY) // Do it again for fixed pipeline until we can get rid of it + GLint originalMatrixMode; + glGetIntegerv(GL_MATRIX_MODE, &originalMatrixMode); + if (_transform._invalidProj) { if (_transform._lastMode != GL_PROJECTION) { glMatrixMode(GL_PROJECTION); @@ -173,12 +174,12 @@ void GLBackend::updateTransform() { } (void) CHECK_GL_ERROR(); } + + glMatrixMode(originalMatrixMode); #endif // Flags are clean _transform._invalidView = _transform._invalidProj = _transform._invalidModel = _transform._invalidViewport = false; - - glMatrixMode(originalMatrixMode); }