/// <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();
                }
            }
        }
Example #2
0
        /// <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();
            }
        }
Example #3
0
        /// <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();
            }
        }