/// <summary> /// Uploads buffer data to the graphics device. /// </summary> private void Upload(IntPtr data, Int32 offsetInBytes, Int32 countInBytes, SetDataOptions options) { using (OpenGLState.ScopedBindArrayBuffer(buffer)) { var isPartialUpdate = (offsetInBytes > 0 || countInBytes < SizeInBytes); var isDiscarding = (options == SetDataOptions.Discard); if (isDiscarding || !isPartialUpdate) { gl.NamedBufferData(buffer, gl.GL_ARRAY_BUFFER, this.size, isPartialUpdate ? null : (void *)data, usage); gl.ThrowIfError(); /* FIX: * I have no idea why the following code is necessary, but * it seems to fix flickering sprites on Intel HD 4000 devices. */ if (gl.IsVertexArrayObjectAvailable) { var vao = (uint)OpenGLState.GL_VERTEX_ARRAY_BINDING; gl.BindVertexArray(vao); gl.ThrowIfError(); } } if (isPartialUpdate) { gl.NamedBufferSubData(buffer, gl.GL_ARRAY_BUFFER, (IntPtr)offsetInBytes, (IntPtr)countInBytes, (void *)data); gl.ThrowIfError(); } } }
/// <summary> /// Sets the data contained by the vertex buffer. /// </summary> private void SetDataInternal <T>(T[] data, Int32 offsetInBytes, Int32 countInBytes, SetDataOptions options) { var handle = GCHandle.Alloc(data, GCHandleType.Pinned); try { using (OpenGLState.ScopedBindArrayBuffer(buffer)) { var isPartialUpdate = (offsetInBytes > 0 || countInBytes < SizeInBytes); var isDiscarding = (options == SetDataOptions.Discard); if (isDiscarding || !isPartialUpdate) { gl.NamedBufferData(buffer, gl.GL_ARRAY_BUFFER, this.size, isPartialUpdate ? null : handle.AddrOfPinnedObject().ToPointer(), usage); gl.ThrowIfError(); /* FIX: * I have no idea why the following code is necessary, but * it seems to fix flickering sprites on Intel HD 4000 devices. */ if (gl.IsVertexArrayObjectAvailable) { var vao = (uint)OpenGLState.GL_VERTEX_ARRAY_BINDING; gl.BindVertexArray(vao); gl.ThrowIfError(); } } if (isPartialUpdate) { gl.NamedBufferSubData(buffer, gl.GL_ARRAY_BUFFER, (IntPtr)offsetInBytes, (IntPtr)countInBytes, handle.AddrOfPinnedObject().ToPointer()); gl.ThrowIfError(); } } } finally { handle.Free(); } }
/// <inheritdoc/> public override void SetDataAligned <T>(T[] data, Int32 dataOffset, Int32 dataCount, Int32 bufferOffset, out Int32 bufferSize, SetDataOptions options) { Contract.Require(data, nameof(data)); Contract.EnsureRange(dataCount > 0, nameof(dataCount)); Contract.EnsureRange(dataOffset >= 0 && dataOffset + dataCount <= data.Length, nameof(dataOffset)); Contract.EnsureRange(bufferOffset >= 0, nameof(bufferOffset)); Contract.Ensure(dataCount <= VertexCount, OpenGLStrings.DataTooLargeForBuffer); bufferSize = vdecl.VertexStride * dataCount; var handle = GCHandle.Alloc(data, GCHandleType.Pinned); try { var caps = (OpenGLGraphicsCapabilities)Ultraviolet.GetGraphics().Capabilities; if (caps.MinMapBufferAlignment > 0) { bufferSize = Math.Min(Math.Max(caps.MinMapBufferAlignment, MathUtil.FindNextPowerOfTwo(bufferSize)), SizeInBytes - bufferOffset); } using (OpenGLState.ScopedBindArrayBuffer(buffer)) { var isPartialUpdate = (bufferOffset > 0 || bufferSize < SizeInBytes); var isDiscarding = (options == SetDataOptions.Discard); if (isDiscarding || !isPartialUpdate) { gl.NamedBufferData(buffer, gl.GL_ARRAY_BUFFER, this.size, isPartialUpdate ? null : handle.AddrOfPinnedObject().ToPointer(), usage); gl.ThrowIfError(); /* FIX: * I have no idea why the following code is necessary, but * it seems to fix flickering sprites on Intel HD 4000 devices. */ if (gl.IsVertexArrayObjectAvailable) { var vao = (uint)OpenGLState.GL_VERTEX_ARRAY_BINDING; gl.BindVertexArray(vao); gl.ThrowIfError(); } } if (isPartialUpdate) { if (caps.MinMapBufferAlignment >= 0) { var bufferRangeAccess = gl.GL_MAP_WRITE_BIT | (options == SetDataOptions.NoOverwrite ? gl.GL_MAP_UNSYNCHRONIZED_BIT : 0); var bufferRangePtr = (Byte *)gl.MapNamedBufferRange(buffer, gl.GL_ARRAY_BUFFER, (IntPtr)bufferOffset, (IntPtr)bufferSize, bufferRangeAccess); gl.ThrowIfError(); var sourceRangePtr = (Byte *)handle.AddrOfPinnedObject() + (dataOffset * vdecl.VertexStride); var sourceSizeInBytes = dataCount * vdecl.VertexStride; for (int i = 0; i < sourceSizeInBytes; i++) { *bufferRangePtr++ = *sourceRangePtr++; } gl.UnmapNamedBuffer(buffer, gl.GL_ARRAY_BUFFER); gl.ThrowIfError(); } else { gl.NamedBufferSubData(buffer, gl.GL_ARRAY_BUFFER, (IntPtr)bufferOffset, (IntPtr)bufferSize, (Byte *)handle.AddrOfPinnedObject().ToPointer() + (dataOffset * vdecl.VertexStride)); gl.ThrowIfError(); } } } } finally { handle.Free(); } }