From a5ad40bee97e14a860335f0fb3a1f74d5fc981fd Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 27 Jul 2015 14:07:28 -0700 Subject: [PATCH] INtroduce the resetStage command to clear up all cache and state in the gpu::Conference and make sure no more resource are linked --- interface/src/Application.cpp | 6 ++ libraries/gpu/src/gpu/Batch.cpp | 4 ++ libraries/gpu/src/gpu/Batch.h | 5 ++ libraries/gpu/src/gpu/Context.cpp | 1 + libraries/gpu/src/gpu/GLBackend.cpp | 20 +++++++ libraries/gpu/src/gpu/GLBackend.h | 45 ++++++++++---- libraries/gpu/src/gpu/GLBackendInput.cpp | 59 ++++++++++++++++--- libraries/gpu/src/gpu/GLBackendOutput.cpp | 5 ++ libraries/gpu/src/gpu/GLBackendPipeline.cpp | 22 +++++++ libraries/gpu/src/gpu/GLBackendQuery.cpp | 4 ++ libraries/gpu/src/gpu/GLBackendState.cpp | 2 +- libraries/gpu/src/gpu/GLBackendTransform.cpp | 4 +- .../render-utils/src/RenderDeferredTask.cpp | 1 - libraries/render/src/render/DrawTask.cpp | 40 ------------- libraries/render/src/render/DrawTask.h | 8 --- 15 files changed, 156 insertions(+), 70 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c2be31cfb3..7bfad60eaf 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -996,6 +996,12 @@ void Application::paintGL() { _compositor.displayOverlayTexture(&renderArgs); } + // Reset the gpu::Context Stages + gpu::Batch batch; + batch.resetStages(); + renderArgs._context->render(batch); + + if (!OculusManager::isConnected() || OculusManager::allowSwap()) { PROFILE_RANGE(__FUNCTION__ "/bufferSwap"); _glWidget->swapBuffers(); diff --git a/libraries/gpu/src/gpu/Batch.cpp b/libraries/gpu/src/gpu/Batch.cpp index 4ac33d8f14..8815c1bae1 100644 --- a/libraries/gpu/src/gpu/Batch.cpp +++ b/libraries/gpu/src/gpu/Batch.cpp @@ -288,6 +288,10 @@ void Batch::getQuery(const QueryPointer& query) { _params.push_back(_queries.cache(query)); } +void Batch::resetStages() { + ADD_COMMAND(resetStages); +} + void push_back(Batch::Params& params, const vec3& v) { params.push_back(v.x); params.push_back(v.y); diff --git a/libraries/gpu/src/gpu/Batch.h b/libraries/gpu/src/gpu/Batch.h index 58fe03c9cf..5f2c2dd089 100644 --- a/libraries/gpu/src/gpu/Batch.h +++ b/libraries/gpu/src/gpu/Batch.h @@ -113,6 +113,9 @@ public: void endQuery(const QueryPointer& query); void getQuery(const QueryPointer& query); + // Reset the stage caches and states + void resetStages(); + // TODO: As long as we have gl calls explicitely issued from interface // code, we need to be able to record and batch these calls. THe long // term strategy is to get rid of any GL calls in favor of the HIFI GPU API @@ -186,6 +189,8 @@ public: COMMAND_endQuery, COMMAND_getQuery, + COMMAND_resetStages, + // TODO: As long as we have gl calls explicitely issued from interface // code, we need to be able to record and batch these calls. THe long // term strategy is to get rid of any GL calls in favor of the HIFI GPU API diff --git a/libraries/gpu/src/gpu/Context.cpp b/libraries/gpu/src/gpu/Context.cpp index 604f39f46f..6730be33bb 100644 --- a/libraries/gpu/src/gpu/Context.cpp +++ b/libraries/gpu/src/gpu/Context.cpp @@ -45,3 +45,4 @@ void Context::syncCache() { void Context::downloadFramebuffer(const FramebufferPointer& srcFramebuffer, const Vec4i& region, QImage& destImage) { _backend->downloadFramebuffer(srcFramebuffer, region, destImage); } + diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index 6b1d552be9..51637462f1 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -46,6 +46,8 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = (&::gpu::GLBackend::do_endQuery), (&::gpu::GLBackend::do_getQuery), + (&::gpu::GLBackend::do_resetStages), + (&::gpu::GLBackend::do_glEnable), (&::gpu::GLBackend::do_glDisable), @@ -128,6 +130,8 @@ GLBackend::GLBackend() : } GLBackend::~GLBackend() { + resetStages(); + killInput(); killTransform(); } @@ -246,6 +250,22 @@ void GLBackend::do_drawIndexedInstanced(Batch& batch, uint32 paramOffset) { (void) CHECK_GL_ERROR(); } +void GLBackend::do_resetStages(Batch& batch, uint32 paramOffset) { + resetStages(); +} + +void GLBackend::resetStages() { + resetInputStage(); + resetPipelineStage(); + resetTransformStage(); + resetUniformStage(); + resetResourceStage(); + resetOutputStage(); + resetQueryStage(); + + (void) CHECK_GL_ERROR(); +} + // TODO: As long as we have gl calls explicitely issued from interface // code, we need to be able to record and batch these calls. THe long // term strategy is to get rid of any GL calls in favor of the HIFI GPU API diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index 9d8c9ef805..59a6c1ee7e 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -195,7 +195,7 @@ public: static const int MAX_NUM_ATTRIBUTES = Stream::NUM_INPUT_SLOTS; static const int MAX_NUM_INPUT_BUFFERS = 16; - uint32 getNumInputBuffers() const { return _input._buffersState.size(); } + uint32 getNumInputBuffers() const { return _input._invalidBuffers.size(); } // The State setters called by the GLState::Commands when a new state is assigned @@ -250,12 +250,16 @@ protected: void killInput(); void syncInputStateCache(); void updateInput(); + void resetInputStage(); struct InputStageState { bool _invalidFormat = true; Stream::FormatPointer _format; + typedef std::bitset ActivationCache; + ActivationCache _attributeActivation; + typedef std::bitset BuffersState; - BuffersState _buffersState; + BuffersState _invalidBuffers; Buffers _buffers; Offsets _bufferOffsets; @@ -266,23 +270,20 @@ protected: Offset _indexBufferOffset; Type _indexBufferType; - typedef std::bitset ActivationCache; - ActivationCache _attributeActivation; - GLuint _defaultVAO; InputStageState() : _invalidFormat(true), _format(0), - _buffersState(0), - _buffers(_buffersState.size(), BufferPointer(0)), - _bufferOffsets(_buffersState.size(), 0), - _bufferStrides(_buffersState.size(), 0), - _bufferVBOs(_buffersState.size(), 0), + _attributeActivation(0), + _invalidBuffers(0), + _buffers(_invalidBuffers.size(), BufferPointer(0)), + _bufferOffsets(_invalidBuffers.size(), 0), + _bufferStrides(_invalidBuffers.size(), 0), + _bufferVBOs(_invalidBuffers.size(), 0), _indexBuffer(0), _indexBufferOffset(0), _indexBufferType(UINT32), - _attributeActivation(0), _defaultVAO(0) {} } _input; @@ -298,6 +299,7 @@ protected: // Synchronize the state cache of this Backend with the actual real state of the GL Context void syncTransformStateCache(); void updateTransform(); + void resetTransformStage(); struct TransformStageState { TransformObject _transformObject; TransformCamera _transformCamera; @@ -330,12 +332,20 @@ protected: // Uniform Stage void do_setUniformBuffer(Batch& batch, uint32 paramOffset); - void do_setResourceTexture(Batch& batch, uint32 paramOffset); + void resetUniformStage(); struct UniformStageState { }; + // Resource Stage + void do_setResourceTexture(Batch& batch, uint32 paramOffset); + + void resetResourceStage(); + struct ResourceStageState { + + }; + // Pipeline Stage void do_setPipeline(Batch& batch, uint32 paramOffset); void do_setStateBlendFactor(Batch& batch, uint32 paramOffset); @@ -349,6 +359,7 @@ protected: void syncPipelineStateCache(); // Grab the actual gl state into it's gpu::State equivalent. THis is used by the above call syncPipleineStateCache() void getCurrentGLState(State::Data& state); + void resetPipelineStage(); struct PipelineStageState { @@ -388,6 +399,7 @@ protected: // Synchronize the state cache of this Backend with the actual real state of the GL Context void syncOutputStateCache(); + void resetOutputStage(); struct OutputStageState { @@ -402,6 +414,15 @@ protected: void do_endQuery(Batch& batch, uint32 paramOffset); void do_getQuery(Batch& batch, uint32 paramOffset); + void resetQueryStage(); + struct QueryStageState { + + }; + + // Reset stages + void do_resetStages(Batch& batch, uint32 paramOffset); + void resetStages(); + // TODO: As long as we have gl calls explicitely issued from interface // code, we need to be able to record and batch these calls. THe long // term strategy is to get rid of any GL calls in favor of the HIFI GPU API diff --git a/libraries/gpu/src/gpu/GLBackendInput.cpp b/libraries/gpu/src/gpu/GLBackendInput.cpp index 229b29cd43..9014024914 100755 --- a/libraries/gpu/src/gpu/GLBackendInput.cpp +++ b/libraries/gpu/src/gpu/GLBackendInput.cpp @@ -52,7 +52,7 @@ void GLBackend::do_setInputBuffer(Batch& batch, uint32 paramOffset) { } if (isModified) { - _input._buffersState.set(channel); + _input._invalidBuffers.set(channel); } } } @@ -154,7 +154,7 @@ void GLBackend::updateInput() { _stats._ISNumFormatChanges++; } - if (_input._buffersState.any()) { + if (_input._invalidBuffers.any()) { int numBuffers = _input._buffers.size(); auto buffer = _input._buffers.data(); auto vbo = _input._bufferVBOs.data(); @@ -162,7 +162,7 @@ void GLBackend::updateInput() { auto stride = _input._bufferStrides.data(); for (int bufferNum = 0; bufferNum < numBuffers; bufferNum++) { - if (_input._buffersState.test(bufferNum)) { + if (_input._invalidBuffers.test(bufferNum)) { glBindVertexBuffer(bufferNum, (*vbo), (*offset), (*stride)); } buffer++; @@ -170,11 +170,11 @@ void GLBackend::updateInput() { offset++; stride++; } - _input._buffersState.reset(); + _input._invalidBuffers.reset(); (void) CHECK_GL_ERROR(); } #else - if (_input._invalidFormat || _input._buffersState.any()) { + if (_input._invalidFormat || _input._invalidBuffers.any()) { if (_input._invalidFormat) { InputStageState::ActivationCache newActivation; @@ -232,7 +232,7 @@ void GLBackend::updateInput() { if ((channelIt).first < buffers.size()) { int bufferNum = (channelIt).first; - if (_input._buffersState.test(bufferNum) || _input._invalidFormat) { + if (_input._invalidBuffers.test(bufferNum) || _input._invalidFormat) { // GLuint vbo = gpu::GLBackend::getBufferID((*buffers[bufferNum])); GLuint vbo = _input._bufferVBOs[bufferNum]; if (boundVBO != vbo) { @@ -240,7 +240,7 @@ void GLBackend::updateInput() { (void) CHECK_GL_ERROR(); boundVBO = vbo; } - _input._buffersState[bufferNum] = false; + _input._invalidBuffers[bufferNum] = false; for (unsigned int i = 0; i < channel._slots.size(); i++) { const Stream::Attribute& attrib = attributes.at(channel._slots[i]); @@ -285,6 +285,51 @@ void GLBackend::updateInput() { #endif } +void GLBackend::resetInputStage() { + // Reset index buffer + _input._indexBufferType = UINT32; + _input._indexBufferOffset = 0; + _input._indexBuffer.reset(); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + (void) CHECK_GL_ERROR(); + + +#if defined(SUPPORT_VAO) + // TODO +#else + glBindBuffer(GL_ARRAY_BUFFER, 0); + + size_t i = 0; +#if defined(SUPPORT_LEGACY_OPENGL) + for (; i < NUM_CLASSIC_ATTRIBS; i++) { + glDisableClientState(attributeSlotToClassicAttribName[i]); + } + glVertexPointer(4, GL_FLOAT, 0, 0); + glNormalPointer(GL_FLOAT, 0, 0); + glColorPointer(4, GL_FLOAT, 0, 0); + glTexCoordPointer(4, GL_FLOAT, 0, 0); +#endif + + for (; i < _input._attributeActivation.size(); i++) { + glDisableVertexAttribArray(i); + glVertexAttribPointer(i, 4, GL_FLOAT, GL_FALSE, 0, 0); + } +#endif + + // Reset vertex buffer and format + _input._format.reset(); + _input._invalidFormat = false; + _input._attributeActivation.reset(); + + for (int i = 0; i < _input._buffers.size(); i++) { + _input._buffers[i].reset(); + _input._bufferOffsets[i] = 0; + _input._bufferStrides[i] = 0; + _input._bufferVBOs[i] = 0; + } + _input._invalidBuffers.reset(); + +} void GLBackend::do_setIndexBuffer(Batch& batch, uint32 paramOffset) { _input._indexBufferType = (Type) batch._params[paramOffset + 2]._uint; diff --git a/libraries/gpu/src/gpu/GLBackendOutput.cpp b/libraries/gpu/src/gpu/GLBackendOutput.cpp index b37def48e7..6b0bfae635 100755 --- a/libraries/gpu/src/gpu/GLBackendOutput.cpp +++ b/libraries/gpu/src/gpu/GLBackendOutput.cpp @@ -177,6 +177,11 @@ void GLBackend::syncOutputStateCache() { _output._framebuffer.reset(); } +void GLBackend::resetOutputStage() { + _output._framebuffer.reset(); + _output._drawFBO = 0; + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); +} void GLBackend::do_setFramebuffer(Batch& batch, uint32 paramOffset) { auto framebuffer = batch._framebuffers.get(batch._params[paramOffset]._uint); diff --git a/libraries/gpu/src/gpu/GLBackendPipeline.cpp b/libraries/gpu/src/gpu/GLBackendPipeline.cpp index 51a3a24e9b..4a54753af8 100755 --- a/libraries/gpu/src/gpu/GLBackendPipeline.cpp +++ b/libraries/gpu/src/gpu/GLBackendPipeline.cpp @@ -164,6 +164,24 @@ void GLBackend::updatePipeline() { #endif } +void GLBackend::resetPipelineStage() { + // First reset State to default + State::Signature resetSignature(0); + resetPipelineState(resetSignature); + _pipeline._state = nullptr; + _pipeline._invalidState = false; + + // Second the shader side + _pipeline._invalidProgram = false; + _pipeline._program = 0; + _pipeline._pipeline.reset(); + glUseProgram(0); +} + +void GLBackend::resetUniformStage() { + +} + void GLBackend::do_setUniformBuffer(Batch& batch, uint32 paramOffset) { GLuint slot = batch._params[paramOffset + 3]._uint; BufferPointer uniformBuffer = batch._buffers.get(batch._params[paramOffset + 2]._uint); @@ -188,6 +206,10 @@ void GLBackend::do_setUniformBuffer(Batch& batch, uint32 paramOffset) { (void) CHECK_GL_ERROR(); } +void GLBackend::resetResourceStage() { + +} + void GLBackend::do_setResourceTexture(Batch& batch, uint32 paramOffset) { GLuint slot = batch._params[paramOffset + 1]._uint; TexturePointer uniformTexture = batch._textures.get(batch._params[paramOffset + 0]._uint); diff --git a/libraries/gpu/src/gpu/GLBackendQuery.cpp b/libraries/gpu/src/gpu/GLBackendQuery.cpp index 39db19dafd..2bdf7c86ad 100644 --- a/libraries/gpu/src/gpu/GLBackendQuery.cpp +++ b/libraries/gpu/src/gpu/GLBackendQuery.cpp @@ -104,3 +104,7 @@ void GLBackend::do_getQuery(Batch& batch, uint32 paramOffset) { (void)CHECK_GL_ERROR(); } } + +void GLBackend::resetQueryStage() { +} + diff --git a/libraries/gpu/src/gpu/GLBackendState.cpp b/libraries/gpu/src/gpu/GLBackendState.cpp index 18fc9ddd3c..618a13e2c4 100644 --- a/libraries/gpu/src/gpu/GLBackendState.cpp +++ b/libraries/gpu/src/gpu/GLBackendState.cpp @@ -484,7 +484,7 @@ void GLBackend::syncPipelineStateCache() { glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); getCurrentGLState(state); State::Signature signature = State::evalSignature(state); - + _pipeline._stateCache = state; _pipeline._stateSignatureCache = signature; } diff --git a/libraries/gpu/src/gpu/GLBackendTransform.cpp b/libraries/gpu/src/gpu/GLBackendTransform.cpp index 65d9c6ed75..e05e0fc1c0 100755 --- a/libraries/gpu/src/gpu/GLBackendTransform.cpp +++ b/libraries/gpu/src/gpu/GLBackendTransform.cpp @@ -184,4 +184,6 @@ void GLBackend::updateTransform() { _transform._invalidView = _transform._invalidProj = _transform._invalidModel = _transform._invalidViewport = false; } - +void GLBackend::resetTransformStage() { + +} diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 0c8d19250b..30c8dffc0e 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -97,7 +97,6 @@ RenderDeferredTask::RenderDeferredTask() : Task() { _drawStatusJobIndex = _jobs.size() - 1; _jobs.push_back(Job(new DrawOverlay3D::JobModel("DrawOverlay3D"))); - _jobs.push_back(Job(new ResetGLState::JobModel())); // Give ourselves 3 frmaes of timer queries _timerQueries.push_back(std::make_shared()); diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index 0e3eba0b53..0aef913d50 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -216,46 +216,6 @@ void render::renderItems(const SceneContextPointer& sceneContext, const RenderCo } } -void addClearStateCommands(gpu::Batch& batch) { - batch._glDepthMask(true); - batch._glDepthFunc(GL_LESS); - batch._glDisable(GL_CULL_FACE); - - batch._glActiveTexture(GL_TEXTURE0 + 1); - batch._glBindTexture(GL_TEXTURE_2D, 0); - batch._glActiveTexture(GL_TEXTURE0 + 2); - batch._glBindTexture(GL_TEXTURE_2D, 0); - batch._glActiveTexture(GL_TEXTURE0 + 3); - batch._glBindTexture(GL_TEXTURE_2D, 0); - batch._glActiveTexture(GL_TEXTURE0); - batch._glBindTexture(GL_TEXTURE_2D, 0); - - - // deactivate vertex arrays after drawing - batch._glDisableClientState(GL_NORMAL_ARRAY); - batch._glDisableClientState(GL_VERTEX_ARRAY); - batch._glDisableClientState(GL_TEXTURE_COORD_ARRAY); - batch._glDisableClientState(GL_COLOR_ARRAY); - batch._glDisableVertexAttribArray(gpu::Stream::TANGENT); - batch._glDisableVertexAttribArray(gpu::Stream::SKIN_CLUSTER_INDEX); - batch._glDisableVertexAttribArray(gpu::Stream::SKIN_CLUSTER_WEIGHT); - - // bind with 0 to switch back to normal operation - batch._glBindBuffer(GL_ARRAY_BUFFER, 0); - batch._glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - batch._glBindTexture(GL_TEXTURE_2D, 0); - - // Back to no program - batch._glUseProgram(0); -} -void ResetGLState::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - - gpu::Batch theBatch; - addClearStateCommands(theBatch); - assert(renderContext->args); - renderContext->args->_context->render(theBatch); -} - void DrawLight::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { assert(renderContext->args); assert(renderContext->args->_viewFrustum); diff --git a/libraries/render/src/render/DrawTask.h b/libraries/render/src/render/DrawTask.h index 62810d47f0..ec6656c0dc 100755 --- a/libraries/render/src/render/DrawTask.h +++ b/libraries/render/src/render/DrawTask.h @@ -260,14 +260,6 @@ public: typedef Job::Model JobModel; }; -class ResetGLState { -public: - void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext); - - typedef Job::Model JobModel; -}; - - class DrawSceneTask : public Task { public: