public static MapMode ConvertToMapMode(SetDataOptions options) { switch (options) { case SetDataOptions.None: return MapMode.Write; case SetDataOptions.Discard: return MapMode.WriteDiscard; case SetDataOptions.NoOverwrite: return MapMode.WriteNoOverwrite; } return MapMode.Write; }
/// <summary> /// /// </summary> /// <typeparam name="T"></typeparam> /// <param name="offsetInBytes"></param> /// <param name="data"></param> /// <param name="startIndex"></param> /// <param name="elementCount"></param> /// <param name="options"></param> protected void SetDataInternal <T>(int offsetInBytes, T[] data, int startIndex, int elementCount, SetDataOptions options) where T : struct { if (data == null) { throw new ArgumentNullException("data"); } if (data.Length < (startIndex + elementCount)) { throw new InvalidOperationException("The array specified in the data parameter is not the correct size for the amount of data requested."); } PlatformSetDataInternal(offsetInBytes, data, startIndex, elementCount, options); }
private unsafe void RenderBatch(Texture2D texture, SpriteData[] sprites, int offset, int count) { graphicsDevice.Textures[0] = texture; float num = 1f / (float)texture.Width; float num2 = 1f / (float)texture.Height; while (count > 0) { SetDataOptions options = SetDataOptions.NoOverwrite; int num3 = count; if (num3 > 2048 - vertexBufferPosition) { num3 = 2048 - vertexBufferPosition; if (num3 < 256) { vertexBufferPosition = 0; options = SetDataOptions.Discard; num3 = count; if (num3 > 2048) { num3 = 2048; } } } fixed(SpriteData *ptr = &sprites[offset]) { fixed(VertexPositionColorTexture *ptr3 = &vertices[0]) { SpriteData *ptr2 = ptr; VertexPositionColorTexture *ptr4 = ptr3; for (int i = 0; i < num3; i++) { float num4 = ptr2->Origin.X / ptr2->Source.Z; float num5 = ptr2->Origin.Y / ptr2->Source.W; ptr4->Color = ptr2->Colors.TopLeftColor; ptr4[1].Color = ptr2->Colors.TopRightColor; ptr4[2].Color = ptr2->Colors.BottomRightColor; ptr4[3].Color = ptr2->Colors.BottomLeftColor; for (int j = 0; j < 4; j++) { float num6 = xCornerOffsets[j]; float num7 = yCornerOffsets[j]; float num8 = (num6 - num4) * ptr2->Destination.Z; float num9 = (num7 - num5) * ptr2->Destination.W; float x = ptr2->Destination.X + num8; float y = ptr2->Destination.Y + num9; if ((ptr2->Effects & SpriteEffects.FlipVertically) != 0) { num6 = 1f - num6; } if ((ptr2->Effects & SpriteEffects.FlipHorizontally) != 0) { num7 = 1f - num7; } ptr4->Position.X = x; ptr4->Position.Y = y; ptr4->Position.Z = 0f; ptr4->TextureCoordinate.X = (ptr2->Source.X + num6 * ptr2->Source.Z) * num; ptr4->TextureCoordinate.Y = (ptr2->Source.Y + num7 * ptr2->Source.W) * num2; ptr4++; } ptr2++; } } } int offsetInBytes = vertexBufferPosition * sizeof(VertexPositionColorTexture) * 4; vertexBuffer.SetData(offsetInBytes, vertices, 0, num3 * 4, sizeof(VertexPositionColorTexture), options); int minVertexIndex = vertexBufferPosition * 4; int numVertices = num3 * 4; int startIndex = vertexBufferPosition * 6; int primitiveCount = num3 * 2; graphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, minVertexIndex, numVertices, startIndex, primitiveCount); vertexBufferPosition += num3; offset += num3; count -= num3; } }
/// <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 <= IndexCount, OpenGLStrings.DataTooLargeForBuffer); var indexStride = GetElementSize(); bufferSize = indexStride * 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.ScopedBindElementArrayBuffer(buffer)) { var isPartialUpdate = (bufferOffset > 0 || bufferSize < SizeInBytes); var isDiscarding = (options == SetDataOptions.Discard); if (isDiscarding || !isPartialUpdate) { gl.NamedBufferData(buffer, gl.GL_ELEMENT_ARRAY_BUFFER, this.size, isPartialUpdate ? null : handle.AddrOfPinnedObject().ToPointer(), usage); 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_ELEMENT_ARRAY_BUFFER, (IntPtr)bufferOffset, (IntPtr)bufferSize, bufferRangeAccess); gl.ThrowIfError(); var sourceRangePtr = (Byte *)handle.AddrOfPinnedObject() + (dataOffset * indexStride); var sourceSizeInBytes = dataCount * indexStride; for (int i = 0; i < sourceSizeInBytes; i++) { *bufferRangePtr++ = *sourceRangePtr++; } gl.UnmapNamedBuffer(buffer, gl.GL_ELEMENT_ARRAY_BUFFER); gl.ThrowIfError(); } else { gl.NamedBufferSubData(buffer, gl.GL_ELEMENT_ARRAY_BUFFER, (IntPtr)bufferOffset, (IntPtr)bufferSize, (Byte *)handle.AddrOfPinnedObject().ToPointer() + (dataOffset * indexStride)); gl.ThrowIfError(); } } } } finally { handle.Free(); } }
private void SetBufferData <T>(int bufferSize, int elementSizeInBytes, int offsetInBytes, T[] data, int startIndex, int elementCount, int vertexStride, SetDataOptions options) where T : struct { GenerateIfRequired(); var sizeInBytes = elementSizeInBytes * elementCount; GL.BindBuffer(BufferTarget.ArrayBuffer, vbo); GraphicsExtensions.CheckGLError(); if (options == SetDataOptions.Discard) { // By assigning NULL data to the buffer this gives a hint // to the device to discard the previous content. GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)bufferSize, IntPtr.Zero, _isDynamic ? BufferUsageHint.StreamDraw : BufferUsageHint.StaticDraw); GraphicsExtensions.CheckGLError(); } var dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned); var dataPtr = (IntPtr)(dataHandle.AddrOfPinnedObject().ToInt64() + startIndex * elementSizeInBytes); GL.BufferSubData(BufferTarget.ArrayBuffer, (IntPtr)offsetInBytes, (IntPtr)sizeInBytes, dataPtr); GraphicsExtensions.CheckGLError(); dataHandle.Free(); }
public void SetData <T>(T[] data, int startIndex, int elementCount, SetDataOptions options) where T : struct { base.SetDataInternal <T>(0, data, startIndex, elementCount, options); }
/// <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(); } }
public void SetData <T>(int offsetInBytes, T[] data, int startIndex, int elementCount, SetDataOptions options) where T : struct { throw new NotImplementedException(); }
/// <summary> /// Performs rendering of particles. /// </summary> /// <param name="iterator">The particle iterator object.</param> /// <param name="context">The render context containing rendering information.</param> protected override void Render(ref RenderContext context, ref ParticleIterator iterator) { Int32 vertexCount = 0; Vector3 cameraPos = context.CameraPosition; Vector3 rotationAxis = context.BillboardRotationalAxis; bool squareTexture = (context.Texture.Height == context.Texture.Width); float aspectRatio = context.Texture.Height / (float)context.Texture.Width ; SetDataOptions setDataOptions = SetDataOptions.NoOverwrite; //Use the SpriteBatch style of filling buffers //http://blogs.msdn.com/b/shawnhar/archive/2010/07/07/setdataoptions-nooverwrite-versus-discard.aspx if (_vertexBufferPosition + context.Count * VerticesPerParticle > NumVertices) { //Too much to fit in the remaining space - start at the beginning and discard _vertexBufferPosition = 0; setDataOptions = SetDataOptions.Discard; } #if UNSAFE unsafe { fixed (ParticleVertex* vertexArray = Vertices) { ParticleVertex* verts = vertexArray +_vertexBufferPosition; #else int vertexIndex = _vertexBufferPosition; #endif var particle = iterator.First; do { #if UNSAFE Single scale = particle->Scale; Vector3 position = particle->Position; Vector3 rotation = particle->Rotation; Vector4 colour = particle->Colour; //Work out our world transform - and set a flag to avoid some multiplies if world ends up as zero bool worldIsNotIdentity = true; Matrix effectWorld; if (context.WorldIsIdentity) { if (particle->EffectProxyIndex > 0) { effectWorld = ParticleEffectProxy.Proxies[particle->EffectProxyIndex].World; } else { worldIsNotIdentity = false; effectWorld = Matrix.Identity; //Makes the compiler happy though we will never actually use it. } } else { effectWorld = particle->EffectProxyIndex > 0 ? ParticleEffectProxy.Proxies[particle->EffectProxyIndex].FinalWorld : context.World; } #else Single scale = particle.Scale; Vector3 position = particle.Position; Vector3 rotation = particle.Rotation; Vector4 colour = particle.Colour; //If we have a proxy then multiply in the proxy world matrix bool worldIsNotIdentity = true; Matrix effectWorld; if (context.WorldIsIdentity) { if (particle.EffectProxyIndex > 0) { effectWorld = ParticleEffectProxy.Proxies[particle.EffectProxyIndex].World; } else { worldIsNotIdentity = false; effectWorld = Matrix.Identity; //Makes the compiler happy though we will never actually use it. } } else { effectWorld = particle.EffectProxyIndex > 0 ? ParticleEffectProxy.Proxies[particle.EffectProxyIndex].FinalWorld : context.World; } #endif //Individual particle transformations - scale and rotation //The Rotation setup will fill in the top 3x3 so we just need to initialise 44 var transform = new Matrix {M44 = 1}; float scaleX = scale; float scaleY = squareTexture ? scale : scale * aspectRatio; //ScaleZ is always 1 so no need multiple into M_3 //Inline the rotation and scale calculations and do each element in one go //Fast rotation matrix - see http://en.wikipedia.org/wiki/Rotation_matrix#General_rotations //This set matches //Matrix temp2 = Matrix.CreateRotationX(rotation.X) * Matrix.CreateRotationY(rotation.Y) * Matrix.CreateRotationZ(rotation.Z); //Matches math od Rotx*RotY*RotZ //var cosX = (float) Math.Cos(rotation.X); //var cosY = (float) Math.Cos(rotation.Y); //var cosZ = (float) Math.Cos(rotation.Z); //var sinX = (float) Math.Sin(rotation.X); //var sinY = (float) Math.Sin(rotation.Y); //var sinZ = (float) Math.Sin(rotation.Z); //transform.M11 = cosY*cosZ; //transform.M12 = cosY * sinZ; //transform.M13 = -sinY; //transform.M21 = sinX*sinY*cosZ - cosX * sinZ; //transform.M22 = sinX*sinY*sinZ + cosX*cosZ; //transform.M23 = sinX*cosY; //transform.M31 = cosX*sinY*cosZ + sinX * sinZ; //transform.M32 = cosX*sinY*sinZ - sinX * cosZ; //transform.M33 = cosX * cosY; //This set matches //Matrix temp2 = Matrix.CreateScale(new VEctor3(scaleX, scaleY,1) * Matrix.CreateRotationZ(rotation.Z) * Matrix.CreateRotationX(rotation.Y) * Matrix.CreateRotationY(rotation.X) ; //Matches YawPitchRoll order //Matrix temp = Matrix.CreateScale(new VEctor3(scaleX, scaleY,1) * Matrix.CreateFromYawPitchRoll(rotation.X, rotation.Y, rotation.Z); //TODO - can we optimise out a rotation e.g.fast path if rotation.Y=0 etc //TODO - can we optimise out rotation(s) if we know its a billboard? That overwrites much of the transform var cosX = (float)Math.Cos(rotation.Y); var cosY = (float)Math.Cos(rotation.X); var cosZ = (float)Math.Cos(rotation.Z); var sinX = (float)Math.Sin(rotation.Y); var sinY = (float)Math.Sin(rotation.X); var sinZ = (float)Math.Sin(rotation.Z); var cosYcosZ = cosY*cosZ; var cosYsinZ = cosY*sinZ; var sinXsinY = sinX*sinY; transform.M11 = (cosYcosZ + sinXsinY * sinZ) * scaleX; transform.M12 = (cosX * sinZ) * scaleX; transform.M13 = (sinX * cosYsinZ - sinY * cosZ) * scaleX; transform.M21 = (sinXsinY * cosZ - cosYsinZ) * scaleY; transform.M22 = (cosX * cosZ) *scaleY; transform.M23 = (sinY * sinZ + sinX * cosYcosZ) * scaleY; transform.M31 = cosX * sinY; transform.M32 = -sinX; transform.M33 = cosX * cosY; switch (context.BillboardStyle) { case BillboardStyle.None: //Position the particle without a multiplication! transform.M41 = position.X; transform.M42 = position.Y; transform.M43 = position.Z; //Just apply the world //TODO - we can just do this in Basic effect instead of per vertex - only if there is no proxy, sort of a fast path! if (worldIsNotIdentity) { Matrix.Multiply(ref transform, ref effectWorld, out transform); } break; default: //Its billboarded Vector3 worldPos; if (worldIsNotIdentity) { Vector3.Transform(ref position, ref effectWorld, out worldPos); } else { worldPos = position; } //Apply the billboard (which includes the world translation) Matrix billboardMatrix; if (context.BillboardStyle == BillboardStyle.Spherical) { //Spherical billboards (always face the camera) Matrix.CreateBillboard(ref worldPos, ref cameraPos, ref Up, Forward, out billboardMatrix); } else { //HACK: For progenitor DBP use the velocity as the axis for a per particle axis if (context.UseVelocityAsBillboardAxis) { #if UNSAFE Matrix.CreateConstrainedBillboard(ref worldPos, ref cameraPos, ref particle->Velocity, Forward, null, out billboardMatrix); #else Matrix.CreateConstrainedBillboard(ref worldPos, ref cameraPos, ref particle.Velocity, Forward, null, out billboardMatrix); #endif } else { //Cylindrical billboards have a vector they are allowed to rotate around Matrix.CreateConstrainedBillboard(ref worldPos, ref cameraPos, ref rotationAxis, Forward, null, out billboardMatrix); } } Matrix.Multiply(ref transform, ref billboardMatrix, out transform); break; } Vector3 v1; Vector3 v2; Vector3 v3; Vector3 v4; Vector3.Transform(ref inv1, ref transform, out v1); Vector3.Transform(ref inv2, ref transform, out v2); Vector3.Transform(ref inv3, ref transform, out v3); Vector3.Transform(ref inv4, ref transform, out v4); #if UNSAFE //inline particle value assignments - removes 4 calls with their parameters and its a struct anyway verts->Position.X = v1.X; verts->Position.Y = v1.Y; verts->Position.Z = v1.Z; verts->Colour.X = colour.X; verts->Colour.Y = colour.Y; verts->Colour.Z = colour.Z; verts->Colour.W = colour.W; verts++; verts->Position.X = v2.X; verts->Position.Y = v2.Y; verts->Position.Z = v2.Z; verts->Colour.X = colour.X; verts->Colour.Y = colour.Y; verts->Colour.Z = colour.Z; verts->Colour.W = colour.W; verts++; verts->Position.X = v3.X; verts->Position.Y = v3.Y; verts->Position.Z = v3.Z; verts->Colour.X = colour.X; verts->Colour.Y = colour.Y; verts->Colour.Z = colour.Z; verts->Colour.W = colour.W; verts++; verts->Position.X = v4.X; verts->Position.Y = v4.Y; verts->Position.Z = v4.Z; verts->Colour.X = colour.X; verts->Colour.Y = colour.Y; verts->Colour.Z = colour.Z; verts->Colour.W = colour.W; verts++; #else //inline particle value assignments - removes 4 calls with their parameters and its a struct anyway this.Vertices[vertexIndex].Position = v1; this.Vertices[vertexIndex].Colour = colour; this.Vertices[vertexIndex++].TextureCoordinate = uv1; this.Vertices[vertexIndex].Position = v2; this.Vertices[vertexIndex].Colour = colour; this.Vertices[vertexIndex++].TextureCoordinate = uv2; this.Vertices[vertexIndex].Position = v3; this.Vertices[vertexIndex].Colour = colour; this.Vertices[vertexIndex++].TextureCoordinate = uv3; this.Vertices[vertexIndex].Position = v4; this.Vertices[vertexIndex].Colour = colour; this.Vertices[vertexIndex++].TextureCoordinate = uv4; #endif vertexCount += 4; } #if UNSAFE while (iterator.MoveNext(&particle)); #else while (iterator.MoveNext(ref particle)); #endif base.GraphicsDeviceService.GraphicsDevice.BlendState = context.BlendState; this.BasicEffect.Texture = context.Texture; //Xbox need the vertex buffer to be set to null before SetData is called //Windows does not //TODO: Is this a bug? see http://forums.create.msdn.com/forums/p/61885/399495.aspx#399495 #if XBOX if (setDataOptions == SetDataOptions.Discard) { base.GraphicsDeviceService.GraphicsDevice.SetVertexBuffer(null); } #endif _vertexBuffer.SetData(_vertexBufferPosition * ParticleVertex.Size, Vertices, _vertexBufferPosition, vertexCount, ParticleVertex.Size, setDataOptions); Debug.WriteLine(String.Format("position: {0} Count: {1} Hint: {2}", _vertexBufferPosition, vertexCount, setDataOptions)); base.GraphicsDeviceService.GraphicsDevice.SetVertexBuffer(_vertexBuffer); foreach (EffectPass pass in this.BasicEffect.CurrentTechnique.Passes) { pass.Apply(); base.GraphicsDeviceService.GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, _vertexBufferPosition, vertexCount, _vertexBufferPosition/4*6, vertexCount/2); } //Move to the next free part of the array _vertexBufferPosition += vertexCount; #if UNSAFE } } #endif }
public void SetData <T>(T[] data, int startIndex, int elementCount, SetDataOptions options) where T : struct { var elementSizeInBytes = Utilities.ReflectionHelpers.SizeOf <T> .Get(); base.SetDataInternal <T>(0, data, startIndex, elementCount, elementSizeInBytes, options); }
public void SetData <T>(int offsetInBytes, T[] data, int startIndex, int elementCount, int vertexStride, SetDataOptions options) where T : struct { base.SetDataInternal <T>(offsetInBytes, data, startIndex, elementCount, vertexStride, options); }
private void PlatformSetDataInternal <T>(int offsetInBytes, T[] data, int startIndex, int elementCount, int vertexStride, SetDataOptions options, int bufferSize, int elementSizeInBytes) where T : struct { GenerateIfRequired(); if (_isDynamic) { // We assume discard by default. var mode = SharpDX.Direct3D11.MapMode.WriteDiscard; if ((options & SetDataOptions.NoOverwrite) == SetDataOptions.NoOverwrite) { mode = SharpDX.Direct3D11.MapMode.WriteNoOverwrite; } var d3dContext = GraphicsDevice._d3dContext; lock (d3dContext) { var dataBox = d3dContext.MapSubresource(_buffer, 0, mode, SharpDX.Direct3D11.MapFlags.None); if (vertexStride == elementSizeInBytes) { SharpDX.Utilities.Write(dataBox.DataPointer + offsetInBytes, data, startIndex, elementCount); } else { for (int i = 0; i < elementCount; i++) { SharpDX.Utilities.Write(dataBox.DataPointer + offsetInBytes + i * vertexStride, data, startIndex + i, 1); } } d3dContext.UnmapSubresource(_buffer, 0); } } else { var dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned); try { var startBytes = startIndex * elementSizeInBytes; var dataPtr = (IntPtr)(dataHandle.AddrOfPinnedObject().ToInt64() + startBytes); var d3dContext = GraphicsDevice._d3dContext; if (vertexStride == elementSizeInBytes) { var box = new SharpDX.DataBox(dataPtr, elementCount * elementSizeInBytes, 0); var region = new SharpDX.Direct3D11.ResourceRegion(); region.Top = 0; region.Front = 0; region.Back = 1; region.Bottom = 1; region.Left = offsetInBytes; region.Right = offsetInBytes + (elementCount * elementSizeInBytes); lock (d3dContext) d3dContext.UpdateSubresource(box, _buffer, 0, region); } else { // Copy the buffer to a staging resource, so that any elements we don't write to will still be correct. var stagingDesc = _buffer.Description; stagingDesc.BindFlags = SharpDX.Direct3D11.BindFlags.None; stagingDesc.CpuAccessFlags = SharpDX.Direct3D11.CpuAccessFlags.Read | SharpDX.Direct3D11.CpuAccessFlags.Write; stagingDesc.Usage = SharpDX.Direct3D11.ResourceUsage.Staging; stagingDesc.OptionFlags = SharpDX.Direct3D11.ResourceOptionFlags.None; using (var stagingBuffer = new SharpDX.Direct3D11.Buffer(GraphicsDevice._d3dDevice, stagingDesc)) { lock (d3dContext) { d3dContext.CopyResource(_buffer, stagingBuffer); // Map the staging resource to a CPU accessible memory var box = d3dContext.MapSubresource(stagingBuffer, 0, SharpDX.Direct3D11.MapMode.Read, SharpDX.Direct3D11.MapFlags.None); for (int i = 0; i < elementCount; i++) { SharpDX.Utilities.CopyMemory( box.DataPointer + i * vertexStride + offsetInBytes, dataPtr + i * elementSizeInBytes, elementSizeInBytes); } // Make sure that we unmap the resource in case of an exception d3dContext.UnmapSubresource(stagingBuffer, 0); // Copy back from staging resource to real buffer. d3dContext.CopyResource(stagingBuffer, _buffer); } } } } finally { dataHandle.Free(); } } }
/// <summary> /// As long as we did not put anything new into the buffer we can discard the old content. /// However once AddDataNative was called we need to use NoOverwrite until drawing happens. /// </summary> protected override void BufferIsFullResetToBeginning() { base.BufferIsFullResetToBeginning(); currentDataHint = SetDataOptions.Discard; }
protected void SetDataInternal <T>(int offsetInBytes, T[] data, int startIndex, int elementCount, int vertexStride, SetDataOptions options) where T : struct { if (data == null) { throw new ArgumentNullException("data is null"); } if (data.Length < (startIndex + elementCount)) { throw new InvalidOperationException("The array specified in the data parameter is not the correct size for the amount of data requested."); } var bufferSize = VertexCount * VertexDeclaration.VertexStride; if ((vertexStride > bufferSize) || (vertexStride < VertexDeclaration.VertexStride)) { throw new ArgumentOutOfRangeException("One of the following conditions is true:\nThe vertex stride is larger than the vertex buffer.\nThe vertex stride is too small for the type of data requested."); } #if !PSM var elementSizeInBytes = Marshal.SizeOf(typeof(T)); #endif #if DIRECTX GenerateIfRequired(); if (_isDynamic) { // We assume discard by default. var mode = SharpDX.Direct3D11.MapMode.WriteDiscard; if ((options & SetDataOptions.NoOverwrite) == SetDataOptions.NoOverwrite) { mode = SharpDX.Direct3D11.MapMode.WriteNoOverwrite; } var d3dContext = GraphicsDevice._d3dContext; lock (d3dContext) { var dataBox = d3dContext.MapSubresource(_buffer, 0, mode, SharpDX.Direct3D11.MapFlags.None); SharpDX.Utilities.Write(IntPtr.Add(dataBox.DataPointer, offsetInBytes), data, startIndex, elementCount); d3dContext.UnmapSubresource(_buffer, 0); } } else { var dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned); var startBytes = startIndex * elementSizeInBytes; var dataPtr = (IntPtr)(dataHandle.AddrOfPinnedObject().ToInt64() + startBytes); var box = new SharpDX.DataBox(dataPtr, 1, 0); var region = new SharpDX.Direct3D11.ResourceRegion(); region.Top = 0; region.Front = 0; region.Back = 1; region.Bottom = 1; region.Left = offsetInBytes; region.Right = offsetInBytes + (elementCount * elementSizeInBytes); lock (GraphicsDevice._d3dContext) GraphicsDevice._d3dContext.UpdateSubresource(box, _buffer, 0, region); dataHandle.Free(); } #elif PSM if (_vertexArray == null) { _vertexArray = new T[VertexCount]; } Array.Copy(data, offsetInBytes / vertexStride, _vertexArray, startIndex, elementCount); #else if (Threading.IsOnUIThread()) { SetBufferData(bufferSize, elementSizeInBytes, offsetInBytes, data, startIndex, elementCount, vertexStride, options); } else { Threading.BlockOnUIThread(() => SetBufferData(bufferSize, elementSizeInBytes, offsetInBytes, data, startIndex, elementCount, vertexStride, options)); } #endif }
public void SetData <T>(int offsetInBytes, T[] data, int startIndex, int elementCount, SetDataOptions options) { int indexSize = indexElementSize == IndexElementSize.SixteenBits ? 2 : 4; data = getSubData <T>(data, startIndex, elementCount); Gl.glBindBuffer(Gl.GL_ARRAY_BUFFER, bufferIdentifier); Gl.glBufferSubData(Gl.GL_ARRAY_BUFFER, new IntPtr(offsetInBytes), new IntPtr(indexSize * elementCount), data); }
/// <summary> /// Sets the data contained by the index buffer. /// </summary> /// <typeparam name="T">The type of the elements of the array to set as the buffer's data.</typeparam> /// <param name="data">An array containing the data to set in the index 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 abstract void SetData <T>(T[] data, Int32 offset, Int32 count, SetDataOptions options);
/// <summary> /// Sets the index buffer's data from the data at the specified pointer. /// </summary> /// <param name="data">A pointer to the data to set.</param> /// <param name="srcOffsetInBytes">The offset from the beginning of the source data, in bytes, at which to begin copying.</param> /// <param name="dstOffsetInBytes">The offset from the beginning of the index buffer, in bytes, at which to begin copying.</param> /// <param name="sizeInBytes">The number of bytes to copy.</param> /// <param name="options">A hint to the underlying driver indicating whether data will be overwritten by this operation.</param> public abstract void SetRawData(IntPtr data, Int32 srcOffsetInBytes, Int32 dstOffsetInBytes, Int32 sizeInBytes, SetDataOptions options);
/// <summary> /// Forces drawing of the current batch. /// </summary> public void Flush() { var graphicsDevice = _instanceVertexBuffer.GraphicsDevice; int numberOfInstances = _nextInstance - _startInstance; if (numberOfInstances > 0) { #if XBOX // Required by Xbox 360: if (_setDataOptions == SetDataOptions.Discard) { graphicsDevice.SetVertexBuffer(null); graphicsDevice.Indices = null; } #endif var vertexBuffer = _submesh.VertexBuffer; var indexBuffer = _submesh.IndexBuffer; Debug.Assert(indexBuffer != null, "Hardware instancing failed: The submesh has no index buffer."); // Copy instance data to instance vertex buffer. int vertexSize = _vertexDeclaration.VertexStride; _instanceVertexBuffer.SetData(_startInstance * vertexSize, Instances, _startInstance, numberOfInstances, vertexSize, _setDataOptions); // Set vertex buffers and index buffer. _vertexBuffers[0] = new VertexBufferBinding(vertexBuffer, _submesh.StartVertex, 0); _vertexBuffers[1] = new VertexBufferBinding(_instanceVertexBuffer, _startInstance, 1); graphicsDevice.SetVertexBuffers(_vertexBuffers); graphicsDevice.Indices = indexBuffer; foreach (var pass in _effectPassBinding) { // Update and apply local, per-instance and per-pass bindings. foreach (var binding in _effectPassParameterBindings) { if (binding.Description.Hint == EffectParameterHint.PerPass) { binding.Update(_renderContext); } binding.Apply(_renderContext); } pass.Apply(); graphicsDevice.DrawInstancedPrimitives( _submesh.PrimitiveType, 0, 0, _submesh.VertexCount, _submesh.StartIndex, _submesh.PrimitiveCount, numberOfInstances); } _startInstance = _nextInstance; _setDataOptions = SetDataOptions.NoOverwrite; } //// Restart from beginning if remaining capacity is low. //var vertexBufferBatchCapacity = Vertices.Length - _startVertex; //var indexBufferBatchCapacity = Indices.Length - _startIndex; //if (vertexBufferBatchCapacity < 128 || indexBufferBatchCapacity < 128 * 3) // Reset(); // Remove strong references. _vertexBuffers[0] = new VertexBufferBinding(); // Reset vertex buffer to remove second vertex stream. graphicsDevice.SetVertexBuffer(null); }
/// <summary> /// Sets the data contained by the index buffer, allowing the driver to align the data in such a way as to /// optimize the speed of the operation, perhaps at the cost of video memory. /// </summary> /// <typeparam name="T">The type of the elements of the array to set as the buffer's data.</typeparam> /// <param name="data">An array containing the data to set in the index buffer.</param> /// <param name="dataOffset">The offset into <paramref name="data"/> at which to begin setting elements into the buffer.</param> /// <param name="dataCount">The number of elements from <paramref name="data"/> to set into the buffer.</param> /// <param name="bufferOffset">The offset into the index buffer at which to begin uploading index data.</param> /// <param name="bufferSize">The size, in bytes, of the buffer region to which the data was uploaded. This may be larger than /// is strictly required by the uploaded data due to driver-specific alignment concerns.</param> /// <param name="options">A hint to the underlying driver indicating whether data will be overwritten by this operation.</param> public abstract void SetDataAligned <T>(T[] data, Int32 dataOffset, Int32 dataCount, Int32 bufferOffset, out Int32 bufferSize, SetDataOptions options) where T : struct;
/// <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(); } }
private void PlatformSetDataInternal <T>(int offsetInBytes, T[] data, int startIndex, int elementCount, SetDataOptions options) where T : struct { GenerateIfRequired(); if (_isDynamic) { // We assume discard by default. var mode = SharpDX.Direct3D11.MapMode.WriteDiscard; if ((options & SetDataOptions.NoOverwrite) == SetDataOptions.NoOverwrite) { mode = SharpDX.Direct3D11.MapMode.WriteNoOverwrite; } var d3dContext = GraphicsDevice._d3dContext; lock (d3dContext) { var dataBox = d3dContext.MapSubresource(_buffer, 0, mode, SharpDX.Direct3D11.MapFlags.None); SharpDX.Utilities.Write(IntPtr.Add(dataBox.DataPointer, offsetInBytes), data, startIndex, elementCount); d3dContext.UnmapSubresource(_buffer, 0); } } else { var elementSizeInBytes = Marshal.SizeOf(typeof(T)); var dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned); try { var startBytes = startIndex * elementSizeInBytes; var dataPtr = (IntPtr)(dataHandle.AddrOfPinnedObject().ToInt64() + startBytes); var box = new SharpDX.DataBox(dataPtr, 1, 0); var region = new SharpDX.Direct3D11.ResourceRegion(); region.Top = 0; region.Front = 0; region.Back = 1; region.Bottom = 1; region.Left = offsetInBytes; region.Right = offsetInBytes + (elementCount * elementSizeInBytes); // TODO: We need to deal with threaded contexts here! var d3dContext = GraphicsDevice._d3dContext; lock (d3dContext) d3dContext.UpdateSubresource(box, _buffer, 0, region); } finally { dataHandle.Free(); } } }
private void PlatformSetDataInternal <T>(int offsetInBytes, T[] data, int startIndex, int elementCount, int vertexStride, SetDataOptions options, int bufferSize, int elementSizeInBytes) where T : struct { if (Threading.IsOnUIThread()) { SetBufferData(bufferSize, elementSizeInBytes, offsetInBytes, data, startIndex, elementCount, vertexStride, options); } else { Threading.BlockOnUIThread(() => SetBufferData(bufferSize, elementSizeInBytes, offsetInBytes, data, startIndex, elementCount, vertexStride, options)); } }
public void SetIndexBufferData( IGLBuffer buffer, int offsetInBytes, IntPtr data, int startIndex, int elementCount, int elementSizeInBytes, SetDataOptions options ) { #if !DISABLE_THREADING ForceToMainThread(() => { #endif BindIndexBuffer(buffer); if (options == SetDataOptions.Discard) { glBufferData( GLenum.GL_ELEMENT_ARRAY_BUFFER, buffer.BufferSize, IntPtr.Zero, (buffer as OpenGLBuffer).Dynamic ); } glBufferSubData( GLenum.GL_ELEMENT_ARRAY_BUFFER, (IntPtr) offsetInBytes, (IntPtr) (elementSizeInBytes * elementCount), data + (startIndex * elementSizeInBytes) ); #if !DISABLE_THREADING }); #endif }
/// <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.ScopedBindElementArrayBuffer(buffer)) { var isPartialUpdate = (offsetInBytes > 0 || countInBytes < SizeInBytes); var isDiscarding = (options == SetDataOptions.Discard); if (isDiscarding || !isPartialUpdate) { gl.NamedBufferData(buffer, gl.GL_ELEMENT_ARRAY_BUFFER, this.size, isPartialUpdate ? null : handle.AddrOfPinnedObject().ToPointer(), usage); gl.ThrowIfError(); } if (isPartialUpdate) { gl.NamedBufferSubData(buffer, gl.GL_ELEMENT_ARRAY_BUFFER, (IntPtr)offsetInBytes, (IntPtr)countInBytes, handle.AddrOfPinnedObject().ToPointer()); gl.ThrowIfError(); } } } finally { handle.Free(); } }
public void SetData <T>(int offsetInBytes, T[] data, int startIndex, int elementCount, SetDataOptions options) where T : struct { this.SetDataInternal <T>(offsetInBytes, data, startIndex, elementCount, options); }
public void SetData <T> (int level, Rectangle?rect, T[] data, int startIndex, int elementCount, SetDataOptions options) { if (data == null) { throw new ArgumentException("data cannot be null"); } if (data.Length < startIndex + elementCount) { throw new ArgumentException("The data passed has a length of " + data.Length + " but " + elementCount + " pixels have been requested."); } Rectangle r; if (rect != null) { r = rect.Value; } else { r = new Rectangle(0, 0, Width, Height); } }
private void PlatformSetDataInternal <T>(int offsetInBytes, T[] data, int startIndex, int elementCount, SetDataOptions options) where T : struct { if (Threading.IsOnUIThread()) { BufferData(offsetInBytes, data, startIndex, elementCount, options); } else { Threading.BlockOnUIThread(() => BufferData(offsetInBytes, data, startIndex, elementCount, options)); } }
protected void SetData <T>(int offsetInBytes, T[] data, int startIndex, int elementCount, int vertexStride, SetDataOptions options) where T : struct { if (data == null) { throw new ArgumentNullException("data is null"); } if (data.Length < startIndex + elementCount) { throw new InvalidOperationException("The array specified in the data parameter is not the correct size for the amount of data requested."); } int bufferSize = this.VertexCount * this.VertexDeclaration.VertexStride; if (vertexStride > bufferSize || vertexStride < this.VertexDeclaration.VertexStride) { throw new ArgumentOutOfRangeException("One of the following conditions is true:\nThe vertex stride is larger than the vertex buffer.\nThe vertex stride is too small for the type of data requested."); } int elementSizeInBytes = Marshal.SizeOf(typeof(T)); Threading.BlockOnUIThread((Action)(() => { int local_0 = elementSizeInBytes * elementCount; GL.BindBuffer(BufferTarget.ArrayBuffer, this.vbo); if (options == SetDataOptions.Discard) { GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)bufferSize, IntPtr.Zero, this._isDynamic ? BufferUsageHint.StreamDraw : BufferUsageHint.StaticDraw); } GL.BufferSubData <T>(BufferTarget.ArrayBuffer, (IntPtr)offsetInBytes, (IntPtr)local_0, data); })); }
public void SetData <T>(T[] data, int startIndex, int elementCount, SetDataOptions options) { throw new NotImplementedException(); }
public void SetData <T>(T[] data, int startIndex, int elementCount, SetDataOptions options) { SetData <T>(0, data, startIndex, elementCount, options); }
public void SetData <T>(int level, Rectangle?rect, T[] data, int startIndex, int elementCount, SetDataOptions options) { throw new NotImplementedException(); }
protected void SetDataInternal <T>(int offsetInBytes, T[] data, int startIndex, int elementCount, int vertexStride, SetDataOptions options) where T : struct { if (data == null) { throw new ArgumentNullException("data"); } var elementSizeInBytes = Marshal.SizeOf(typeof(T)); var bufferSize = VertexCount * VertexDeclaration.VertexStride; if (vertexStride == 0) { vertexStride = elementSizeInBytes; } if (startIndex + elementCount > data.Length || elementCount <= 0) { throw new ArgumentOutOfRangeException("data", "The array specified in the data parameter is not the correct size for the amount of data requested."); } if (elementCount > 1 && (elementCount * vertexStride > bufferSize)) { throw new InvalidOperationException("The vertex stride is larger than the vertex buffer."); } if (vertexStride < elementSizeInBytes) { throw new ArgumentOutOfRangeException("The vertex stride must be greater than or equal to the size of the specified data (" + elementSizeInBytes + ")."); } PlatformSetDataInternal <T> (offsetInBytes, data, startIndex, elementCount, vertexStride, options, bufferSize, elementSizeInBytes); }
public void SetVertexBufferData( IGLBuffer buffer, int offsetInBytes, IntPtr data, int startIndex, int elementCount, int elementSizeInBytes, SetDataOptions options ) { #if !DISABLE_THREADING ForceToMainThread(() => { #endif uint handle = (buffer as OpenGLBuffer).Handle; if (options == SetDataOptions.Discard) { glNamedBufferData( handle, buffer.BufferSize, IntPtr.Zero, (buffer as OpenGLBuffer).Dynamic ); } glNamedBufferSubData( handle, (IntPtr) offsetInBytes, (IntPtr) (elementSizeInBytes * elementCount), data + (startIndex * elementSizeInBytes) ); #if !DISABLE_THREADING }); #endif }