/// <summary> /// Updates a subset of the buffer object's data store. /// </summary> /// <typeparam name="T">The type of data in the data array.</typeparam> /// <param name="vboID">The VBO whose buffer will be updated.</param> /// <param name="target">Specifies the target buffer object. Must be ArrayBuffer, ElementArrayBuffer, PixelPackBuffer or PixelUnpackBuffer.</param> /// <param name="data">The new data that will be copied to the data store.</param> /// <param name="length">The size in bytes of the data store region being replaced.</param> public static void BufferSubData <T>(uint vboID, BufferTarget target, T[] data, int length) where T : struct { GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned); try { Gl.BindBuffer(target, vboID); Gl.BufferSubData(target, IntPtr.Zero, (IntPtr)(Marshal.SizeOf(data[0]) * length), handle.AddrOfPinnedObject()); } finally { handle.Free(); } }
/// <summary> /// Updates a subset of the buffer object's data store. /// </summary> /// <param name="data">The new data that will be copied to the data store.</param> /// <param name="size">The size in bytes of the data store region being replaced.</param> /// <param name="offset">The offset in bytes into the buffer object's data store where data replacement will begin.</param> public void BufferSubData(T[] data, int size, int offset) { if (BufferTarget != OpenGL.BufferTarget.ArrayBuffer && BufferTarget != OpenGL.BufferTarget.ElementArrayBuffer && BufferTarget != OpenGL.BufferTarget.PixelPackBuffer && BufferTarget != OpenGL.BufferTarget.PixelUnpackBuffer) { throw new InvalidOperationException(string.Format("BufferSubData cannot be called with a BufferTarget of type {0}", BufferTarget.ToString())); } GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned); try { Gl.BindBuffer(this); Gl.BufferSubData(BufferTarget, (IntPtr)offset, (IntPtr)size, handle.AddrOfPinnedObject()); } finally { handle.Free(); } }
/// <summary> /// Actually create this BufferObject resources. /// </summary> /// <param name="ctx"> /// A <see cref="GraphicsContext"/> used for allocating resources. /// </param> /// <exception cref="ArgumentNullException"> /// Exception thrown if <paramref name="ctx"/> is null. /// </exception> /// <exception cref="ArgumentException"> /// Exception thrown if <paramref name="ctx"/> is not current on the calling thread. /// </exception> /// <exception cref="InvalidOperationException"> /// Exception thrown if this BufferObject has not client memory allocated and the hint is different from /// <see cref="BufferObjectHint.StaticCpuDraw"/> or <see cref="BufferObjectHint.DynamicCpuDraw"/>. /// </exception> /// <exception cref="InvalidOperationException"> /// Exception thrown if this BufferObject is currently mapped. /// </exception> protected override void CreateObject(GraphicsContext ctx) { CheckCurrentContext(ctx); if ((ClientBufferAddress == IntPtr.Zero) && ((Hint != BufferObjectHint.StaticCpuDraw) && (Hint != BufferObjectHint.DynamicCpuDraw))) { throw new InvalidOperationException("no client buffer"); } // Determine the client buffer size uint clientBufferSize = _ClientBufferSize; if (ClientBufferAddress != IntPtr.Zero) { clientBufferSize = ClientBufferSize; } Debug.Assert(clientBufferSize > 0); // Buffer must be bound Bind(ctx); if (ctx.Caps.GlExtensions.VertexBufferObject_ARB) { if (IsMapped) { throw new InvalidOperationException("mapped"); } // Define buffer object (type, size and hints) Gl.BufferData((int)BufferType, clientBufferSize, null, (int)Hint); // Store GPU buffer size _GpuBufferSize = clientBufferSize; // Define buffer object contents if (ClientBufferAddress != IntPtr.Zero) { // Provide buffer contents Gl.BufferSubData(BufferType, IntPtr.Zero, _GpuBufferSize, ClientBufferAddress); // Release memory, if it is not required anymore if (_MemoryBufferAutoDispose) { ReleaseClientBuffer(); } } } else { // Discard previous GPU buffer, if any if (_GpuBuffer != null) { _GpuBuffer.Dispose(); } if (ClientBufferAddress == IntPtr.Zero) { // Note: GPU buffer size specified by _ClientBufferSize Debug.Assert(_ClientBufferSize > 0); // Allocate simulated GPU buffer _GpuBuffer = new AlignedMemoryBuffer(_ClientBufferSize, MinimumBufferAlignment); } else { // Let a virtual implementation decide how pass information from the client buffer and the "GPU" buffer UploadClientBuffer(); } // Store GPU buffer size _GpuBufferSize = _GpuBuffer.Size; } // Reset requested client buffer size _ClientBufferSize = 0; }