From 37cf37e3e16498c74cfd285c38a1c0a34bfdeb47 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 12 Sep 2018 11:47:32 -0700 Subject: [PATCH] PR feedback --- .../gpu-gl-common/src/gpu/gl/GLBackend.cpp | 1 - .../gpu-gl-common/src/gpu/gl/GLBackend.h | 150 +++++++++--------- .../src/gpu/gl/GLBackendInput.cpp | 3 +- .../src/gpu/gl/GLBackendOutput.cpp | 10 +- .../src/gpu/gl/GLBackendPipeline.cpp | 40 ++--- .../gpu-gl/src/gpu/gl41/GL41BackendBuffer.cpp | 10 +- .../gpu-gl/src/gpu/gl41/GL41BackendInput.cpp | 4 +- .../gpu-gl/src/gpu/gl45/GL45BackendBuffer.cpp | 9 +- 8 files changed, 108 insertions(+), 119 deletions(-) diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp index 30a3cf0aaf..4fea4f2dc5 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp @@ -150,7 +150,6 @@ void GLBackend::init() { }); } - GLBackend::GLBackend(bool syncCache) { _pipeline._cameraCorrectionBuffer._buffer->flush(); initShaderBinaryCache(); diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h index 7927734256..fecf1a5798 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h @@ -39,6 +39,7 @@ #define GPU_STEREO_TECHNIQUE_INSTANCED #endif + // Let these be configured by the one define picked above #ifdef GPU_STEREO_TECHNIQUE_DOUBLED_SIMPLE #define GPU_STEREO_DRAWCALL_DOUBLED @@ -208,9 +209,8 @@ class GLBackend : public Backend, public std::enable_shared_from_this protected: explicit GLBackend(bool syncCache); GLBackend(); - - public: + #if defined(USE_GLES) // https://www.khronos.org/registry/OpenGL-Refpages/es3/html/glGet.xhtml static const GLint MIN_REQUIRED_TEXTURE_IMAGE_UNITS = 16; @@ -251,8 +251,8 @@ public: // This is the ugly "download the pixels to sysmem for taking a snapshot" // Just avoid using it, it's ugly and will break performances virtual void downloadFramebuffer(const FramebufferPointer& srcFramebuffer, - const Vec4i& region, - QImage& destImage) final override; + const Vec4i& region, QImage& destImage) final override; + // this is the maximum numeber of available input buffers size_t getNumInputBuffers() const { return _input._invalidBuffers.size(); } @@ -273,6 +273,7 @@ public: static const int MAX_NUM_RESOURCE_TABLE_TEXTURES = 2; size_t getMaxNumResourceTextureTables() const { return MAX_NUM_RESOURCE_TABLE_TEXTURES; } + // Draw Stage virtual void do_draw(const Batch& batch, size_t paramOffset) = 0; virtual void do_drawIndexed(const Batch& batch, size_t paramOffset) = 0; @@ -324,6 +325,7 @@ public: // Reset stages virtual void do_resetStages(const Batch& batch, size_t paramOffset) final; + virtual void do_disableContextViewCorrection(const Batch& batch, size_t paramOffset) final; virtual void do_restoreContextViewCorrection(const Batch& batch, size_t paramOffset) final; @@ -343,7 +345,7 @@ public: virtual void do_popProfileRange(const Batch& batch, size_t paramOffset) final; // 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 + // 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 virtual void do_glUniform1i(const Batch& batch, size_t paramOffset) final; virtual void do_glUniform1f(const Batch& batch, size_t paramOffset) final; @@ -368,9 +370,7 @@ public: virtual void do_setStateAntialiasedLineEnable(bool enable) final; virtual void do_setStateDepthBias(Vec2 bias) final; virtual void do_setStateDepthTest(State::DepthTest test) final; - virtual void do_setStateStencil(State::StencilActivation activation, - State::StencilTest frontTest, - State::StencilTest backTest) final; + virtual void do_setStateStencil(State::StencilActivation activation, State::StencilTest frontTest, State::StencilTest backTest) final; virtual void do_setStateAlphaToCoverageEnable(bool enable) final; virtual void do_setStateSampleMask(uint32 mask) final; virtual void do_setStateBlend(State::BlendFunction blendFunction) final; @@ -399,9 +399,7 @@ public: virtual void releaseQuery(GLuint id) const; virtual void queueLambda(const std::function lambda) const; - bool isTextureManagementSparseEnabled() const override { - return (_textureManagement._sparseCapable && Texture::getEnableSparseTextures()); - } + bool isTextureManagementSparseEnabled() const override { return (_textureManagement._sparseCapable && Texture::getEnableSparseTextures()); } protected: virtual GLint getRealUniformLocation(GLint location) const; @@ -410,11 +408,11 @@ protected: // FIXME instead of a single flag, create a features struct similar to // https://www.khronos.org/registry/vulkan/specs/1.0/man/html/VkPhysicalDeviceFeatures.html - virtual bool supportsBindless() const { return false; } + virtual bool supportsBindless() const { return false; } static const size_t INVALID_OFFSET = (size_t)-1; - bool _inRenderTransferPass{ false }; - int _currentDraw{ -1 }; + bool _inRenderTransferPass { false }; + int _currentDraw { -1 }; std::list profileRanges; mutable Mutex _trashMutex; @@ -443,42 +441,36 @@ protected: virtual void updateInput() = 0; struct InputStageState { - bool _invalidFormat{ true }; - bool _lastUpdateStereoState{ false }; + bool _invalidFormat { true }; + bool _lastUpdateStereoState{ false }; bool _hadColorAttribute{ true }; FormatReference _format{ GPU_REFERENCE_INIT_VALUE }; std::string _formatKey; typedef std::bitset ActivationCache; - ActivationCache _attributeActivation{ 0 }; + ActivationCache _attributeActivation { 0 }; typedef std::bitset BuffersState; BuffersState _invalidBuffers{ 0 }; BuffersState _attribBindingBuffers{ 0 }; - std::vector _buffers{ MAX_NUM_INPUT_BUFFERS, GPU_REFERENCE_INIT_VALUE }; - Offsets _bufferOffsets; - Offsets _bufferStrides; - std::vector _bufferVBOs; + std::array _buffers{}; + std::array _bufferOffsets{}; + std::array _bufferStrides{}; + std::array _bufferVBOs{}; glm::vec4 _colorAttribute{ 0.0f }; - BufferReference _indexBuffer{ GPU_REFERENCE_INIT_VALUE }; - Offset _indexBufferOffset{ 0 }; - Type _indexBufferType{ UINT32 }; + BufferReference _indexBuffer{}; + Offset _indexBufferOffset { 0 }; + Type _indexBufferType { UINT32 }; - BufferReference _indirectBuffer{ GPU_REFERENCE_INIT_VALUE }; + BufferReference _indirectBuffer{}; Offset _indirectBufferOffset{ 0 }; Offset _indirectBufferStride{ 0 }; - GLuint _defaultVAO{ 0 }; - - InputStageState() { - _bufferOffsets.resize(MAX_NUM_INPUT_BUFFERS, 0); - _bufferStrides.resize(MAX_NUM_INPUT_BUFFERS, 0); - _bufferVBOs.resize(MAX_NUM_INPUT_BUFFERS, 0); - } + GLuint _defaultVAO { 0 }; } _input; virtual void initTransform() = 0; @@ -489,7 +481,7 @@ protected: virtual void resetTransformStage(); // Allows for correction of the camera pose to account for changes - // between the time when a was recorded and the time(s) when it is + // between the time when a was recorded and the time(s) when it is // executed // Prev is the previous correction used at previous frame struct CameraCorrection { @@ -504,12 +496,9 @@ protected: struct Cameras { TransformCamera _cams[2]; - Cameras(){}; + Cameras() {}; Cameras(const TransformCamera& cam) { memcpy(_cams, &cam, sizeof(TransformCamera)); }; - Cameras(const TransformCamera& camL, const TransformCamera& camR) { - memcpy(_cams, &camL, sizeof(TransformCamera)); - memcpy(_cams + 1, &camR, sizeof(TransformCamera)); - }; + Cameras(const TransformCamera& camL, const TransformCamera& camR) { memcpy(_cams, &camL, sizeof(TransformCamera)); memcpy(_cams + 1, &camR, sizeof(TransformCamera)); }; }; using CameraBufferElement = Cameras; @@ -523,24 +512,25 @@ protected: mutable std::map _drawCallInfoOffsets; - GLuint _objectBuffer{ 0 }; - GLuint _cameraBuffer{ 0 }; - GLuint _drawCallInfoBuffer{ 0 }; - GLuint _objectBufferTexture{ 0 }; - size_t _cameraUboSize{ 0 }; + GLuint _objectBuffer { 0 }; + GLuint _cameraBuffer { 0 }; + GLuint _drawCallInfoBuffer { 0 }; + GLuint _objectBufferTexture { 0 }; + size_t _cameraUboSize { 0 }; bool _viewIsCamera{ false }; - bool _skybox{ false }; + bool _skybox { false }; Transform _view; CameraCorrection _correction; bool _viewCorrectionEnabled{ true }; + Mat4 _projection; - Vec4i _viewport{ 0, 0, 1, 1 }; - Vec2 _depthRange{ 0.0f, 1.0f }; + Vec4i _viewport { 0, 0, 1, 1 }; + Vec2 _depthRange { 0.0f, 1.0f }; Vec2 _projectionJitter{ 0.0f, 0.0f }; - bool _invalidView{ false }; - bool _invalidProj{ false }; - bool _invalidViewport{ false }; + bool _invalidView { false }; + bool _invalidProj { false }; + bool _invalidViewport { false }; bool _enabledDrawcallInfoBuffer{ false }; @@ -559,10 +549,9 @@ protected: struct UniformStageState { struct BufferState { - BufferReference buffer{ GPU_REFERENCE_INIT_VALUE }; + BufferReference buffer{}; GLintptr offset{ 0 }; GLsizeiptr size{ 0 }; - //BufferState(const BufferPointer& buffer = nullptr, GLintptr offset = 0, GLsizeiptr size = 0); BufferState& operator=(const BufferState& other) = delete; void reset() { gpu::gl::reset(buffer); offset = 0; size = 0; } @@ -573,12 +562,12 @@ protected: }; // MAX_NUM_UNIFORM_BUFFERS-1 is the max uniform index BATCHES are allowed to set, but - // MIN_REQUIRED_UNIFORM_BUFFER_BINDINGS is used here because the backend sets some - // internal UBOs for things like camera correction + // MIN_REQUIRED_UNIFORM_BUFFER_BINDINGS is used here because the backend sets some + // internal UBOs for things like camera correction std::array _buffers; } _uniform; - // Helper function that provides common code + // Helper function that provides common code void bindUniformBuffer(uint32_t slot, const BufferPointer& buffer, GLintptr offset = 0, GLsizeiptr size = 0); void releaseUniformBuffer(uint32_t slot); void resetUniformStage(); @@ -588,19 +577,23 @@ protected: virtual bool bindResourceBuffer(uint32_t slot, const BufferPointer& buffer) = 0; virtual void releaseResourceBuffer(uint32_t slot) = 0; - // Helper function that provides common code used by do_setResourceTexture and + // Helper function that provides common code used by do_setResourceTexture and // do_setResourceTextureTable (in non-bindless mode) void bindResourceTexture(uint32_t slot, const TexturePointer& texture); + // update resource cache and do the gl unbind call with the current gpu::Texture cached at slot s void releaseResourceTexture(uint32_t slot); void resetResourceStage(); struct ResourceStageState { - std::vector _buffers{ MAX_NUM_RESOURCE_BUFFERS, BufferReference() }; - std::vector _textures{ MAX_NUM_RESOURCE_TEXTURES, GPU_REFERENCE_INIT_VALUE }; - //Textures _textures { { MAX_NUM_RESOURCE_TEXTURES } }; + struct TextureState { + TextureReference _texture{}; + GLenum _target; + }; + std::array _buffers{}; + std::array _textures{}; int findEmptyTextureSlot() const; } _resource; @@ -615,22 +608,21 @@ protected: void resetPipelineStage(); struct PipelineStageState { - PipelineReference _pipeline{ GPU_REFERENCE_INIT_VALUE }; + PipelineReference _pipeline{}; - GLuint _program{ 0 }; - bool _cameraCorrection{ false }; - GLShader* _programShader{ nullptr }; - bool _invalidProgram{ false }; + GLuint _program { 0 }; + bool _cameraCorrection { false }; + GLShader* _programShader { nullptr }; + bool _invalidProgram { false }; - BufferView _cameraCorrectionBuffer{ gpu::BufferView(std::make_shared(sizeof(CameraCorrection), nullptr)) }; - BufferView _cameraCorrectionBufferIdentity{ gpu::BufferView( - std::make_shared(sizeof(CameraCorrection), nullptr)) }; + BufferView _cameraCorrectionBuffer { gpu::BufferView(std::make_shared(sizeof(CameraCorrection), nullptr )) }; + BufferView _cameraCorrectionBufferIdentity { gpu::BufferView(std::make_shared(sizeof(CameraCorrection), nullptr )) }; State::Data _stateCache{ State::DEFAULT }; - State::Signature _stateSignatureCache{ 0 }; + State::Signature _stateSignatureCache { 0 }; - GLState* _state{ nullptr }; - bool _invalidState{ false }; + GLState* _state { nullptr }; + bool _invalidState { false }; PipelineStageState() { _cameraCorrectionBuffer.edit() = CameraCorrection(); @@ -644,9 +636,9 @@ protected: virtual GLShader* compileBackendProgram(const Shader& program, const Shader::CompilationHandler& handler); virtual GLShader* compileBackendShader(const Shader& shader, const Shader::CompilationHandler& handler); virtual std::string getBackendShaderHeader() const = 0; - // For a program, this will return a string containing all the source files (without any - // backend headers or defines). For a vertex, fragment or geometry shader, this will - // return the fully customized shader with all the version and backend specific + // For a program, this will return a string containing all the source files (without any + // backend headers or defines). For a vertex, fragment or geometry shader, this will + // return the fully customized shader with all the version and backend specific // preprocessor directives // The program string returned can be used as a key for a cache of shader binaries // The shader strings can be reliably sent to the low level `compileShader` functions @@ -662,22 +654,22 @@ protected: // Synchronize the state cache of this Backend with the actual real state of the GL Context void syncOutputStateCache(); void resetOutputStage(); - + struct OutputStageState { - FramebufferReference _framebuffer{ GPU_REFERENCE_INIT_VALUE }; - GLuint _drawFBO{ 0 }; + FramebufferReference _framebuffer{}; + GLuint _drawFBO { 0 }; } _output; void resetQueryStage(); struct QueryStageState { - uint32_t _rangeQueryDepth{ 0 }; + uint32_t _rangeQueryDepth { 0 }; } _queryStage; void resetStages(); // Stores cached binary versions of the shaders for quicker startup on subsequent runs - // Note that shaders in the cache can still fail to load due to hardware or driver - // changes that invalidate the cached binary, in which case we fall back on compiling + // Note that shaders in the cache can still fail to load due to hardware or driver + // changes that invalidate the cached binary, in which case we fall back on compiling // the source again struct ShaderBinaryCache { std::mutex _mutex; @@ -689,7 +681,7 @@ protected: virtual void killShaderBinaryCache(); struct TextureManagementStageState { - bool _sparseCapable{ false }; + bool _sparseCapable { false }; GLTextureTransferEnginePointer _transferEngine; } _textureManagement; virtual void initTextureManagementStage(); diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackendInput.cpp b/libraries/gpu-gl-common/src/gpu/gl/GLBackendInput.cpp index 219efae866..85e6ba5382 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackendInput.cpp +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackendInput.cpp @@ -19,8 +19,8 @@ using namespace gpu::gl; void GLBackend::do_setInputFormat(const Batch& batch, size_t paramOffset) { const auto& format = batch._streamFormats.get(batch._params[paramOffset]._uint); if (!compare(_input._format, format)) { - assign(_input._format, format); if (format) { + assign(_input._format, format); auto inputFormat = GLInputFormat::sync((*format)); assert(inputFormat); if (_input._formatKey != inputFormat->key) { @@ -28,6 +28,7 @@ void GLBackend::do_setInputFormat(const Batch& batch, size_t paramOffset) { _input._invalidFormat = true; } } else { + reset(_input._format); _input._formatKey.clear(); _input._invalidFormat = true; } diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackendOutput.cpp b/libraries/gpu-gl-common/src/gpu/gl/GLBackendOutput.cpp index 370e50592d..411e16b18e 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackendOutput.cpp +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackendOutput.cpp @@ -25,15 +25,19 @@ using namespace gpu::gl; void GLBackend::syncOutputStateCache() { GLint currentFBO; glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, ¤tFBO); + _output._drawFBO = currentFBO; reset(_output._framebuffer); } void GLBackend::resetOutputStage() { - _output._drawFBO = 0; - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + if (valid(_output._framebuffer)) { + reset(_output._framebuffer); + _output._drawFBO = 0; + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + } + glEnable(GL_FRAMEBUFFER_SRGB); - reset(_output._framebuffer); } void GLBackend::do_setFramebuffer(const Batch& batch, size_t paramOffset) { diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackendPipeline.cpp b/libraries/gpu-gl-common/src/gpu/gl/GLBackendPipeline.cpp index 9b28fa8114..7a06b3af86 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackendPipeline.cpp +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackendPipeline.cpp @@ -140,13 +140,9 @@ void GLBackend::resetPipelineStage() { void GLBackend::releaseUniformBuffer(uint32_t slot) { auto& bufferState = _uniform._buffers[slot]; - auto buffer = acquire(bufferState.buffer); - if (buffer) { - auto* object = Backend::getGPUObject(*buffer); - if (object) { - glBindBufferBase(GL_UNIFORM_BUFFER, slot, 0); // RELEASE - (void)CHECK_GL_ERROR(); - } + if (valid(bufferState.buffer)) { + glBindBufferBase(GL_UNIFORM_BUFFER, slot, 0); // RELEASE + (void)CHECK_GL_ERROR(); } bufferState.reset(); } @@ -201,17 +197,13 @@ void GLBackend::do_setUniformBuffer(const Batch& batch, size_t paramOffset) { } void GLBackend::releaseResourceTexture(uint32_t slot) { - auto tex = acquire(_resource._textures[slot]); - if (tex) { - auto* object = Backend::getGPUObject(*tex); - if (object) { - GLuint target = object->_target; - glActiveTexture(GL_TEXTURE0 + slot); - glBindTexture(target, 0); // RELEASE - (void)CHECK_GL_ERROR(); - } + auto& textureState = _resource._textures[slot]; + if (valid(textureState._texture)) { + glActiveTexture(GL_TEXTURE0 + slot); + glBindTexture(textureState._target, 0); // RELEASE + (void)CHECK_GL_ERROR(); + reset(textureState._texture); } - reset(_resource._textures[slot]); } void GLBackend::resetResourceStage() { @@ -299,8 +291,9 @@ void GLBackend::do_setResourceFramebufferSwapChainTexture(const Batch& batch, si } void GLBackend::setResourceTexture(unsigned int slot, const TexturePointer& resourceTexture) { + auto& textureState = _resource._textures[slot]; // check cache before thinking - if (compare(_resource._textures[slot], resourceTexture)) { + if (compare(textureState._texture, resourceTexture)) { return; } @@ -310,15 +303,12 @@ void GLBackend::setResourceTexture(unsigned int slot, const TexturePointer& reso // Always make sure the GLObject is in sync GLTexture* object = syncGPUObject(resourceTexture); if (object) { + assign(textureState._texture, resourceTexture); GLuint to = object->_texture; - GLuint target = object->_target; + textureState._target = object->_target; glActiveTexture(GL_TEXTURE0 + slot); - glBindTexture(target, to); - + glBindTexture(textureState._target, to); (void)CHECK_GL_ERROR(); - - assign(_resource._textures[slot], resourceTexture); - _stats._RSAmountTextureMemoryBounded += (int)object->size(); } else { @@ -343,7 +333,7 @@ void GLBackend::do_setResourceTextureTable(const Batch& batch, size_t paramOffse int GLBackend::ResourceStageState::findEmptyTextureSlot() const { // start from the end of the slots, try to find an empty one that can be used for (auto i = MAX_NUM_RESOURCE_TEXTURES - 1; i > 0; i--) { - if (!valid(_textures[i])) { + if (!valid(_textures[i]._texture)) { return i; } } diff --git a/libraries/gpu-gl/src/gpu/gl41/GL41BackendBuffer.cpp b/libraries/gpu-gl/src/gpu/gl41/GL41BackendBuffer.cpp index 80fd214515..d5193f892a 100644 --- a/libraries/gpu-gl/src/gpu/gl41/GL41BackendBuffer.cpp +++ b/libraries/gpu-gl/src/gpu/gl41/GL41BackendBuffer.cpp @@ -117,7 +117,11 @@ bool GL41Backend::bindResourceBuffer(uint32_t slot, const BufferPointer& buffer) } void GL41Backend::releaseResourceBuffer(uint32_t slot) { - reset(_resource._buffers[slot]); - glActiveTexture(GL_TEXTURE0 + GL41Backend::RESOURCE_BUFFER_SLOT0_TEX_UNIT + slot); - glBindTexture(GL_TEXTURE_BUFFER, 0); + auto& bufferReference = _resource._buffers[slot]; + auto buffer = acquire(bufferReference); + if (buffer) { + glActiveTexture(GL_TEXTURE0 + GL41Backend::RESOURCE_BUFFER_SLOT0_TEX_UNIT + slot); + glBindTexture(GL_TEXTURE_BUFFER, 0); + reset(bufferReference); + } } diff --git a/libraries/gpu-gl/src/gpu/gl41/GL41BackendInput.cpp b/libraries/gpu-gl/src/gpu/gl41/GL41BackendInput.cpp index bd88be0f0d..2b985c122e 100644 --- a/libraries/gpu-gl/src/gpu/gl41/GL41BackendInput.cpp +++ b/libraries/gpu-gl/src/gpu/gl41/GL41BackendInput.cpp @@ -74,8 +74,8 @@ void GL41Backend::updateInput() { bool hasColorAttribute{ false }; const auto& buffers = _input._buffers; - const Offsets& offsets = _input._bufferOffsets; - const Offsets& strides = _input._bufferStrides; + const auto& offsets = _input._bufferOffsets; + const auto& strides = _input._bufferStrides; const auto& attributes = format->getAttributes(); const auto& inputChannels = format->getChannels(); diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45BackendBuffer.cpp b/libraries/gpu-gl/src/gpu/gl45/GL45BackendBuffer.cpp index da8f7059bf..cb0591c31c 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45BackendBuffer.cpp +++ b/libraries/gpu-gl/src/gpu/gl45/GL45BackendBuffer.cpp @@ -76,11 +76,10 @@ bool GL45Backend::bindResourceBuffer(uint32_t slot, const BufferPointer& buffer) } void GL45Backend::releaseResourceBuffer(uint32_t slot) { - auto buf = acquire(_resource._buffers[slot]); - if (buf) { + auto& bufferReference = _resource._buffers[slot]; + auto buffer = acquire(bufferReference); + if (buffer) { glBindBufferBase(GL_SHADER_STORAGE_BUFFER, slot, 0); - reset(_resource._buffers[slot]); + reset(bufferReference); } } - -