/// <summary>
        /// Link a <see cref="ShaderStorageBuffer"/> to this ShaderProgram.
        /// </summary>
        /// <param name="ctx">
        /// A <see cref="GraphicsContext"/> used for operations.
        /// </param>
        /// <param name="storageBufferName">
        /// A <see cref="String"/> that specify the variable name in the shader source.
        /// </param>
        /// <param name="storageBuffer">
        /// The <see cref="Buffer"/> to be linked to <paramref name="storageBufferName"/>.
        /// </param>
        public void SetStorageBuffer(GraphicsContext ctx, string storageBufferName, Buffer storageBuffer)
        {
            CheckCurrentContext(ctx);
            if (storageBufferName == null)
            {
                throw new ArgumentNullException(nameof(storageBufferName));
            }
            CheckThisExistence(ctx);
            CheckThatExistence(ctx, storageBuffer);

            if (!ctx.Extensions.ShaderStorageBufferObject_ARB)
            {
                throw new InvalidOperationException("GL_ARB_shader_storage_buffer_object not supported");
            }

            StorageBufferBinding storageBufferBinding;

            if (!_StorageBufferMap.TryGetValue(storageBufferName, out storageBufferBinding))
            {
                throw new InvalidOperationException($"unrecognized storage buffer '{storageBufferName}'");
            }

            // Bind to the most appropriate binding index
            IBindingIndexResource bindingIndexResource = storageBuffer;

            ctx.BindIndex(bindingIndexResource);

            // Avoid unnecessary glShaderStorageBlockBinding call
            //if (storageBufferBinding.BufferBinding == bindingIndexResource.BindingIndex)
            //	return;

            Gl.ShaderStorageBlockBinding(ObjectName, storageBufferBinding.Index, bindingIndexResource.BindingIndex);
            storageBufferBinding.BufferBinding = bindingIndexResource.BindingIndex;
        }