Пример #1
0
        /// <summary>
        /// Sets the data contained by the vertex buffer.
        /// </summary>
        /// <param name="data">An array containing the data to set in the vertex buffer.</param>
        /// <param name="offset">The offset into <paramref name="data"/> at which to begin setting elements into the buffer.</param>
        /// <param name="count">The number of elements from <paramref name="data"/> to set into the buffer.</param>
        /// <param name="options">A hint to the underlying driver indicating whether data will be overwritten by this operation.</param>
        public override void SetData <T>(T[] data, Int32 offset, Int32 count, SetDataOptions options)
        {
            Contract.Require(data, nameof(data));
            Contract.EnsureRange(count > 0, nameof(count));
            Contract.EnsureRange(offset >= 0 && offset + count <= data.Length, nameof(offset));
            Contract.Ensure(count <= VertexCount, OpenGLStrings.DataTooLargeForBuffer);

            var handle = GCHandle.Alloc(data, GCHandleType.Pinned);

            try
            {
                using (OpenGLState.ScopedBindArrayBuffer(buffer))
                {
                    if (options == SetDataOptions.Discard)
                    {
                        gl.NamedBufferData(buffer, gl.GL_ARRAY_BUFFER, this.size, null, 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 (OpenGLState.SupportsVertexArrayObjects)
                        {
                            var vao = (uint)OpenGLState.GL_VERTEX_ARRAY_BINDING;
                            gl.BindVertexArray(vao);
                            gl.ThrowIfError();
                        }
                    }

                    var start = new IntPtr(offset * vdecl.VertexStride);
                    var size  = new IntPtr(vdecl.VertexStride * count);

                    gl.NamedBufferSubData(buffer, gl.GL_ARRAY_BUFFER, start, size, handle.AddrOfPinnedObject().ToPointer());
                    gl.ThrowIfError();
                }
            }
            finally
            {
                handle.Free();
            }
        }
Пример #2
0
        /// <summary>
        /// Sets the data contained by the vertex buffer.
        /// </summary>
        /// <param name="data">An array containing the data to set in the vertex buffer.</param>
        public override void SetData <T>(T[] data)
        {
            Contract.Require(data, nameof(data));
            Contract.Ensure(data.Length <= VertexCount, OpenGLStrings.DataTooLargeForBuffer);

            var handle = GCHandle.Alloc(data, GCHandleType.Pinned);

            try
            {
                using (OpenGLState.ScopedBindArrayBuffer(buffer))
                {
                    var size = new IntPtr(vdecl.VertexStride * data.Length);
                    gl.NamedBufferSubData(buffer, gl.GL_ARRAY_BUFFER, IntPtr.Zero, size, handle.AddrOfPinnedObject().ToPointer());
                    gl.ThrowIfError();
                }
            }
            finally
            {
                handle.Free();
            }
        }
Пример #3
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 (OpenGLState.SupportsVertexArrayObjects)
                        {
                            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();
            }
        }
Пример #4
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.SupportsMapBufferRange && 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 (OpenGLState.SupportsVertexArrayObjects)
                        {
                            var vao = (uint)OpenGLState.GL_VERTEX_ARRAY_BINDING;
                            gl.BindVertexArray(vao);
                            gl.ThrowIfError();
                        }
                    }

                    if (isPartialUpdate)
                    {
                        if (caps.SupportsMapBufferRange)
                        {
                            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();
            }
        }