[slimdx] r2193 committed - Finishing up the SpriteBatch.

22 views
Skip to first unread message

sli...@googlecode.com

unread,
Mar 20, 2012, 2:01:09 PM3/20/12
to slimdx...@googlegroups.com
Revision: 2193
Author: mike.popoloski
Date: Tue Mar 20 11:00:08 2012
Log: Finishing up the SpriteBatch.
http://code.google.com/p/slimdx/source/detail?r=2193

Added:
/branches/lite/SlimDX.Toolkit/Sprites/SpriteInfo.cs
Modified:
/branches/lite/SlimDX.Toolkit/SlimDX.Toolkit.csproj
/branches/lite/SlimDX.Toolkit/Sprites/SpriteBatch.cs
/branches/lite/SlimDX.Toolkit/Sprites/SpriteContextResources.cs
/branches/lite/SlimDX.Toolkit/Sprites/SpriteDeviceResources.cs
/branches/lite/SlimDX.Toolkit/Utilities/AlignedArray.cs
/branches/lite/SlimMath/Vector4.cs

=======================================
--- /dev/null
+++ /branches/lite/SlimDX.Toolkit/Sprites/SpriteInfo.cs Tue Mar 20 11:00:08
2012
@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Runtime.InteropServices;
+using SlimMath;
+using SlimDX.Direct3D11;
+
+namespace SlimDX.Toolkit
+{
+ // 80-byte sprite structure. The padding is to maintain a 16-byte
alignment.
+ [StructLayout(LayoutKind.Sequential, Size = 80)]
+ struct SpriteInfo
+ {
+ public Vector4 Source;
+ public Vector4 Destination;
+ public Color4 Color;
+ public Vector4 OriginRotationDepth;
+ public int Texture;
+ public int Flags;
+ }
+}
=======================================
--- /branches/lite/SlimDX.Toolkit/SlimDX.Toolkit.csproj Mon Mar 19 16:08:39
2012
+++ /branches/lite/SlimDX.Toolkit/SlimDX.Toolkit.csproj Tue Mar 20 11:00:08
2012
@@ -49,6 +49,7 @@
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Sprites\SpriteContextResources.cs" />
<Compile Include="Sprites\SpriteDeviceResources.cs" />
+ <Compile Include="Sprites\SpriteInfo.cs" />
<Compile Include="Sprites\SpriteShaders.cs" />
<Compile Include="Utilities\AlignedArray.cs" />
<Compile Include="Utilities\SafeHGlobal.cs" />
=======================================
--- /branches/lite/SlimDX.Toolkit/Sprites/SpriteBatch.cs Mon Mar 19
16:08:39 2012
+++ /branches/lite/SlimDX.Toolkit/Sprites/SpriteBatch.cs Tue Mar 20
11:00:08 2012
@@ -5,6 +5,7 @@
using SlimDX.Direct3D11;
using SlimMath;
using System.Drawing;
+using SlimDX.Toolkit.VertexTypes;

namespace SlimDX.Toolkit
{
@@ -78,6 +79,19 @@
public class SpriteBatch : IDisposable
{
const int MaxBatchSize = 2048;
+ const int MinBatchSize = 128;
+ const int InitialQueueSize = 64;
+ const int SourceInTexels = 4;
+ const int DestSizeInPixels = 8;
+ internal const int VerticesPerSprite = 4;
+ internal const int IndicesPerSprite = 6;
+
+ static readonly Vector2[] CornerOffsets = {
+ Vector2.Zero,
+ Vector2.UnitX,
+ Vector2.UnitY,
+ Vector2.One
+ };

// these resource pools allow resources to be shared between
sprite batches
// the local copies in each sprite batch are wrapped in
ref-counted containers
@@ -90,6 +104,10 @@
SpriteSortMode sortMode = SpriteSortMode.Deferred;
ISharedResource<SpriteDeviceResources> deviceResources;
ISharedResource<SpriteContextResources> contextResources;
+ List<ShaderResourceView> textures;
+ AlignedArray<SpriteInfo> sprites;
+ List<int> sortedSprites;
+ int spriteCount;

/// <summary>
/// The custom blend state to apply to sprites rendered in the
current batch. Set it to <c>null</c> to use the default settings,
@@ -161,6 +179,10 @@
device = context.Device;
this.context = context;

+ sprites = new AlignedArray<SpriteInfo>(InitialQueueSize);
+ textures = new List<ShaderResourceView>();
+ sortedSprites = new List<int>();
+
deviceResources = sharedDeviceResources.DemandCreate(device,
() => new SpriteDeviceResources(device, MaxBatchSize));
contextResources =
sharedContextResources.DemandCreate(context, () => new
SpriteContextResources(context, MaxBatchSize));
}
@@ -239,6 +261,8 @@
/// </summary>
/// <param name="texture">The sprite's texture.</param>
/// <param name="position">The 2D position at which to draw the
sprite.</param>
+ /// <exception cref="ArgumentNullException">Thrown if <paramref
name="texture"/> is <c>null</c>.</exception>
+ /// <exception cref="InvalidOperationException">Thrown if Draw is
called outside of a Begin/End pair.</exception>
public void Draw(ShaderResourceView texture, Vector2 position)
{
unsafe { Draw(texture, new Vector4(position, 1.0f, 1.0f),
null, new Color4(1.0f), Vector4.Zero, SpriteEffects.None); }
@@ -250,6 +274,8 @@
/// <param name="texture">The sprite's texture.</param>
/// <param name="position">The 2D position at which to draw the
sprite.</param>
/// <param name="color">The color used to tint the sprite.</param>
+ /// <exception cref="ArgumentNullException">Thrown if <paramref
name="texture"/> is <c>null</c>.</exception>
+ /// <exception cref="InvalidOperationException">Thrown if Draw is
called outside of a Begin/End pair.</exception>
public void Draw(ShaderResourceView texture, Vector2 position,
Color4 color)
{
unsafe { Draw(texture, new Vector4(position, 1.0f, 1.0f),
null, color, Vector4.Zero, SpriteEffects.None); }
@@ -267,6 +293,8 @@
/// <param name="origin">The origin point for position, scaling,
and rotation effects.</param>
/// <param name="effects">Various effects to apply to the rendered
sprite.</param>
/// <param name="layerDepth">The layer depth to use for sorting
the sprite.</param>
+ /// <exception cref="ArgumentNullException">Thrown if <paramref
name="texture"/> is <c>null</c>.</exception>
+ /// <exception cref="InvalidOperationException">Thrown if Draw is
called outside of a Begin/End pair.</exception>
public void Draw(ShaderResourceView texture, Vector2 position,
Color4 color, Rectangle sourceRectangle, float rotation = 0.0f, float scale
= 1.0f, Vector2 origin = new Vector2(), SpriteEffects effects =
SpriteEffects.None, float layerDepth = 0.0f)
{
unsafe { Draw(texture, new Vector4(position, scale, scale),
&sourceRectangle, color, new Vector4(origin.X, origin.Y, rotation,
layerDepth), effects); }
@@ -284,6 +312,8 @@
/// <param name="origin">The origin point for position, scaling,
and rotation effects.</param>
/// <param name="effects">Various effects to apply to the rendered
sprite.</param>
/// <param name="layerDepth">The layer depth to use for sorting
the sprite.</param>
+ /// <exception cref="ArgumentNullException">Thrown if <paramref
name="texture"/> is <c>null</c>.</exception>
+ /// <exception cref="InvalidOperationException">Thrown if Draw is
called outside of a Begin/End pair.</exception>
public void Draw(ShaderResourceView texture, Vector2 position,
Color4 color, Rectangle sourceRectangle, Vector2 scale, float rotation =
0.0f, Vector2 origin = new Vector2(), SpriteEffects effects =
SpriteEffects.None, float layerDepth = 0.0f)
{
unsafe { Draw(texture, new Vector4(position, scale.X,
scale.Y), &sourceRectangle, color, new Vector4(origin.X, origin.Y,
rotation, layerDepth), effects); }
@@ -294,9 +324,11 @@
/// </summary>
/// <param name="texture">The sprite's texture.</param>
/// <param name="destinationRectangle">The destination position
and size.</param>
+ /// <exception cref="ArgumentNullException">Thrown if <paramref
name="texture"/> is <c>null</c>.</exception>
+ /// <exception cref="InvalidOperationException">Thrown if Draw is
called outside of a Begin/End pair.</exception>
public void Draw(ShaderResourceView texture, Rectangle
destinationRectangle)
{
- unsafe { Draw(texture, new Vector4(destinationRectangle.X,
destinationRectangle.Y, destinationRectangle.Width,
destinationRectangle.Height), null, new Color4(1.0f), Vector4.Zero,
SpriteEffects.None); }
+ unsafe { Draw(texture, new Vector4(destinationRectangle.X,
destinationRectangle.Y, destinationRectangle.Width,
destinationRectangle.Height), null, new Color4(1.0f), Vector4.Zero,
(SpriteEffects)DestSizeInPixels); }
}

/// <summary>
@@ -305,9 +337,11 @@
/// <param name="texture">The sprite's texture.</param>
/// <param name="destinationRectangle">The destination position
and size.</param>
/// <param name="color">The color used to tint the sprite.</param>
+ /// <exception cref="ArgumentNullException">Thrown if <paramref
name="texture"/> is <c>null</c>.</exception>
+ /// <exception cref="InvalidOperationException">Thrown if Draw is
called outside of a Begin/End pair.</exception>
public void Draw(ShaderResourceView texture, Rectangle
destinationRectangle, Color4 color)
{
- unsafe { Draw(texture, new Vector4(destinationRectangle.X,
destinationRectangle.Y, destinationRectangle.Width,
destinationRectangle.Height), null, color, Vector4.Zero,
SpriteEffects.None); }
+ unsafe { Draw(texture, new Vector4(destinationRectangle.X,
destinationRectangle.Y, destinationRectangle.Width,
destinationRectangle.Height), null, color, Vector4.Zero,
(SpriteEffects)DestSizeInPixels); }
}

/// <summary>
@@ -321,24 +355,294 @@
/// <param name="origin">The origin point for position, scaling,
and rotation effects.</param>
/// <param name="effects">Various effects to apply to the rendered
sprite.</param>
/// <param name="layerDepth">The layer depth to use for sorting
the sprite.</param>
+ /// <exception cref="ArgumentNullException">Thrown if <paramref
name="texture"/> is <c>null</c>.</exception>
+ /// <exception cref="InvalidOperationException">Thrown if Draw is
called outside of a Begin/End pair.</exception>
public void Draw(ShaderResourceView texture, Rectangle
destinationRectangle, Rectangle sourceRectangle, Color4 color, float
rotation = 0.0f, Vector2 origin = new Vector2(), SpriteEffects effects =
SpriteEffects.None, float layerDepth = 0.0f)
{
- unsafe { Draw(texture, new Vector4(destinationRectangle.X,
destinationRectangle.Y, destinationRectangle.Width,
destinationRectangle.Height), &sourceRectangle, color, new
Vector4(origin.X, origin.Y, rotation, layerDepth), effects); }
+ unsafe { Draw(texture, new Vector4(destinationRectangle.X,
destinationRectangle.Y, destinationRectangle.Width,
destinationRectangle.Height), &sourceRectangle, color, new
Vector4(origin.X, origin.Y, rotation, layerDepth), effects |
(SpriteEffects)DestSizeInPixels); }
}

#endregion

- unsafe void Draw(ShaderResourceView texture, Vector4 destination,
Rectangle* source, Color4 color, Vector4 originRotationDepth, SpriteEffects
flags)
- {
+ unsafe void Draw(ShaderResourceView texture, Vector4 destination,
Rectangle* source, Color4 color, Vector4 originRotationDepth, SpriteEffects
effects)
+ {
+ if (texture == null)
+ throw new ArgumentNullException("texture");
+ if (!started)
+ throw new InvalidOperationException("Begin must be called
before Draw.");
+
+ if (spriteCount >= sprites.Length)
+ {
+ // double the size of the array if we've run out of room
+ sprites.Realloc(sprites.Length * 2);
+ sortedSprites.Clear();
+ }
+
+ int flags = (int)effects;
+ var sprite = (SpriteInfo*)sprites[spriteCount];
+
+ if (source != null)
+ {
+ var sourceVec = new Vector4(source->X, source->Y,
source->Width, source->Height);
+ sprite->Source = sourceVec;
+
+ // if the destination size is relative to the source
region, convert it to pixels
+ if ((flags & DestSizeInPixels) == 0)
+ {
+ destination.Z *= sourceVec.Z;
+ destination.W *= sourceVec.W;
+ }
+
+ flags |= SourceInTexels | DestSizeInPixels;
+ }
+ else
+ {
+ // no explicit source region, so use the entire texture
+ sprite->Source = new Vector4(0, 0, 1, 1);
+ }
+
+ sprite->Destination = destination;
+ sprite->Color = color;
+ sprite->OriginRotationDepth = originRotationDepth;
+ sprite->Flags = flags;
+
+ // if we are in immediate mode, draw the sprite right away
+ if (sortMode == SpriteSortMode.Immediate)
+ {
+ if (textures.Count == 0)
+ textures.Add(texture);
+ else
+ textures[0] = texture;
+
+ if (sortedSprites.Count == 0)
+ sortedSprites.Add(0);
+ else
+ sortedSprites[0] = 0;
+
+ RenderBatch(0, 0, 1);
+ }
+ else
+ {
+ // queue the sprite for later sorting and batched rendering
+ spriteCount++;
+ if (textures.Count == 0 || texture !=
textures[textures.Count - 1])
+ textures.Add(texture);
+
+ sprite->Texture = textures.Count - 1;
+ }
}

void PrepareForRendering()
{
-
+ var dr = deviceResources.Resource;
+ var cr = contextResources.Resource;
+
+ // set state objects
+ var blendState = BlendState ?? dr.States.AlphaBlend;
+ var depthStencilState = DepthStencilState ??
dr.States.DepthNone;
+ var rasterizerState = RasterizerState ??
dr.States.CullCounterClockwise;
+ var samplerState = SamplerState ?? dr.States.LinearClamp;
+
+ context.OutputMerger.BlendState = blendState;
+ context.OutputMerger.DepthStencilState = depthStencilState;
+ context.Rasterizer.State = rasterizerState;
+ context.PixelShader.SetSampler(samplerState, 0);
+
+ // set shaders
+ context.InputAssembler.PrimitiveTopology =
PrimitiveTopology.TriangleList;
+ context.InputAssembler.InputLayout = dr.InputLayout;
+ context.VertexShader.Set(dr.VertexShader);
+ context.PixelShader.Set(dr.PixelShader);
+
+ // set vertex and index buffers
+ context.InputAssembler.SetVertexBuffers(0, new
VertexBufferBinding(cr.VertexBuffer,
VertexPositionColorTexture.SizeInBytes, 0));
+ context.InputAssembler.SetIndexBuffer(dr.IndexBuffer,
DXGI.Format.R16_UInt, 0);
+
+ // set transform matrix
+ var viewport = context.Rasterizer.GetViewport();
+ var transform = TransformMatrix *
Matrix.OrthoOffCenterLH(0.0f, viewport.Width, viewport.Height, 0.0f, 0.0f,
1.0f);
+
+ // if this is on a deferred device context, reset the position
so that the first Map call can use Discard
+ if (context.Type == DeviceContextType.Deferred)
+ cr.VertexBufferPosition = 0;
+
+ // let the user do any custom shader settings
+ if (CustomShaderSetup != null)
+ CustomShaderSetup();
}

- void FlushBatch()
- {
+ unsafe void FlushBatch()
+ {
+ if (spriteCount == 0)
+ return;
+
+ SortSprites();
+
+ // walk through the sorted sprite list, looking for adjacent
entries that share a texture
+ int currentTexture = -1;
+ int batchStart = 0;
+
+ for (int i = 0; i < spriteCount; i++)
+ {
+ var sprite = (SpriteInfo*)sprites[sortedSprites[i]];
+
+ // flush whenever the texture changes
+ if (sprite->Texture != currentTexture)
+ {
+ if (i > batchStart)
+ RenderBatch(currentTexture, batchStart, i -
batchStart);
+
+ currentTexture = sprite->Texture;
+ batchStart = i;
+ }
+ }
+
+ // flush the final batch
+ RenderBatch(currentTexture, batchStart, spriteCount -
batchStart);
+
+ // reset the queue
+ spriteCount = 0;
+ textures.Clear();
+
+ // if we're using sorting, clear the sort array to avoid
problems due to unstable sorts
+ if (sortMode != SpriteSortMode.Deferred)
+ sortedSprites.Clear();
+ }
+
+ unsafe void SortSprites()
+ {
+ // increase the size of the sort array if necessary
+ if (sortedSprites.Count < spriteCount)
+ {
+ for (int i = sortedSprites.Count; i < spriteCount; i++)
+ sortedSprites.Add(i);
+ }
+
+ switch (sortMode)
+ {
+ // sort by texture
+ case SpriteSortMode.Texture:
+ sortedSprites.Sort((x, y) =>
((SpriteInfo*)sprites[x])->Texture.CompareTo(((SpriteInfo*)sprites[y])->Texture));
+ break;
+
+ // sort by depth from back to front
+ case SpriteSortMode.BackToFront:
+ sortedSprites.Sort((x, y) =>
((SpriteInfo*)sprites[y])->OriginRotationDepth.W.CompareTo(((SpriteInfo*)sprites[x])->OriginRotationDepth.W));
+ break;
+
+ // sort by depth from front to back
+ case SpriteSortMode.FrontToBack:
+ sortedSprites.Sort((x, y) =>
((SpriteInfo*)sprites[x])->OriginRotationDepth.W.CompareTo(((SpriteInfo*)sprites[y])->OriginRotationDepth.W));
+ break;
+ }
+ }
+
+ unsafe void RenderBatch(int textureIndex, int start, int count)
+ {
+ var cr = contextResources.Resource;
+ var texture = textures[textureIndex];
+ context.PixelShader.SetShaderResource(texture, 0);
+
+ Vector2 textureSize = GetTextureSize(texture);
+ Vector2 inverseSize = Vector2.Reciprocal(textureSize);
+
+ while (count > 0)
+ {
+ // figure out how many sprites we *want* to draw, and how
many can fit in the vertex buffer
+ int batchSize = count;
+ int remainingSpace = MaxBatchSize -
cr.VertexBufferPosition;
+
+ if (batchSize > remainingSpace)
+ {
+ if (remainingSpace < MinBatchSize)
+ {
+ // if we are out of room, or are about to submit
an excessively small batch, wrap back to the start of the buffer
+ cr.VertexBufferPosition = 0;
+ batchSize = Math.Min(count, MaxBatchSize);
+ }
+ else
+ batchSize = remainingSpace;
+ }
+
+ // write sprites into the vertex buffer
+ var box = context.MapSubresource(cr.VertexBuffer,
cr.VertexBufferPosition == 0 ? MapMode.WriteDiscard :
MapMode.WriteNoOverwrite, MapFlags.None);
+ box.Data.Position += cr.VertexBufferPosition *
VerticesPerSprite * VertexPositionColorTexture.SizeInBytes;
+
+ for (int i = 0; i < batchSize; i++)
+ RenderSprite((SpriteInfo*)sprites[sortedSprites[i +
start]], box.Data, textureSize, inverseSize);
+
+ context.UnmapSubresource(cr.VertexBuffer, 0);
+
+ // do the actual drawing
+ context.DrawIndexed(batchSize * IndicesPerSprite,
cr.VertexBufferPosition * IndicesPerSprite, 0);
+
+ cr.VertexBufferPosition += batchSize;
+ start += batchSize;
+ count -= batchSize;
+ }
+ }
+
+ unsafe void RenderSprite(SpriteInfo* sprite, DataStream vertices,
Vector2 textureSize, Vector2 inverseTextureSize)
+ {
+ int flags = sprite->Flags;
+ float rotation = sprite->OriginRotationDepth.Z;
+ float depth = sprite->OriginRotationDepth.W;
+ var sourcePos = sprite->Source.XY;
+ var sourceSize = sprite->Source.ZW;
+ var destPos = sprite->Destination.XY;
+ var destSize = sprite->Destination.ZW;
+
+ // compute the scaled origin
+ var origin = sprite->OriginRotationDepth.XY;
+ origin.X /= sourceSize.X == 0 ? float.Epsilon : sourceSize.X;
+ origin.Y /= sourceSize.Y == 0 ? float.Epsilon : sourceSize.Y;
+
+ // convert the source region from texels to mod-1 texture
coordinate format
+ if ((flags & SourceInTexels) != 0)
+ {
+ Vector2.Modulate(ref sourcePos, ref inverseTextureSize,
out sourcePos);
+ Vector2.Modulate(ref sourceSize, ref inverseTextureSize,
out sourcePos);
+ }
+ else
+ Vector2.Modulate(ref origin, ref inverseTextureSize, out
sourcePos);
+
+ // if the destination size is relative to the source region,
convert it to pixels
+ if ((flags & DestSizeInPixels) == 0)
+ Vector2.Modulate(ref destSize, ref textureSize, out
sourcePos);
+
+ // compute a 2x2 rotation matrix
+ var rotationMatrix = rotation == 0 ? Matrix.Identity :
Matrix.RotationZ(rotation);
+
+ // Tricksy alert! Texture coordinates are computed from the
same cornerOffsets
+ // table as vertex positions, but if the sprite is mirrored,
this table
+ // must be indexed in a different order. This is done as
follows:
+ // position = cornerOffsets[i]
+ // texcoord = cornerOffsets[i ^ SpriteEffects]
+
+ int mirrorBits = flags & 3;
+ for (int i = 0; i < VerticesPerSprite; i++)
+ {
+ // calculate position
+ Vector2 position;
+ var offset = Vector2.Modulate(CornerOffsets[i] - origin,
destSize);
+ Vector2.TransformNormal(ref offset, ref rotationMatrix,
out position);
+
+ // calculate texture coordinates
+ var texcoords = Vector2.Modulate(CornerOffsets[i ^
mirrorBits], sourceSize) + sourcePos;
+
+ // write out the vertex into the stream
+ vertices.Write(new VertexPositionColorTexture(new
Vector3(position, depth), sprite->Color, texcoords));
+ }
+ }
+
+ static Vector2 GetTextureSize(ShaderResourceView view)
+ {
+ var texture = view.Resource as Texture2D;
+ if (texture == null)
+ throw new InvalidOperationException("SpriteBatch can only
draw 2D textures.");
+
+ var desc = texture.Description;
+ return new Vector2(desc.Width, desc.Height);
}
}
}
=======================================
--- /branches/lite/SlimDX.Toolkit/Sprites/SpriteContextResources.cs Mon Mar
19 16:08:39 2012
+++ /branches/lite/SlimDX.Toolkit/Sprites/SpriteContextResources.cs Tue Mar
20 11:00:08 2012
@@ -9,8 +9,6 @@
// contains shared resources that are associated with a particular
device context
class SpriteContextResources : IDisposable
{
- const int VerticesPerSprite = 4;
-
public bool InImmediateMode;
public int VertexBufferPosition;
public Buffer VertexBuffer;
@@ -24,7 +22,7 @@
// create a dynamic write-only vertex buffer for the sprite
vertices, limited by maxBatchSize
VertexBuffer = new Buffer(context.Device, new BufferDescription
{
- SizeInBytes = VertexPositionColorTexture.SizeInBytes *
maxBatchSize * VerticesPerSprite,
+ SizeInBytes = VertexPositionColorTexture.SizeInBytes *
maxBatchSize * SpriteBatch.VerticesPerSprite,
BindFlags = BindFlags.VertexBuffer,
Usage = ResourceUsage.Dynamic,
CpuAccessFlags = CpuAccessFlags.Write
=======================================
--- /branches/lite/SlimDX.Toolkit/Sprites/SpriteDeviceResources.cs Mon Mar
19 14:40:29 2012
+++ /branches/lite/SlimDX.Toolkit/Sprites/SpriteDeviceResources.cs Tue Mar
20 11:00:08 2012
@@ -9,13 +9,11 @@
// contains shared resources that are associated with a particular
device
class SpriteDeviceResources : IDisposable
{
- const int IndicesPerSprite = 6;
- const int VerticesPerSprite = 4;
-
public VertexShader VertexShader;
public PixelShader PixelShader;
public InputLayout InputLayout;
public Buffer IndexBuffer;
+ public CommonStates States;

public SpriteDeviceResources(Device device, int maxBatchSize)
{
@@ -31,9 +29,9 @@
PixelShader = new PixelShader(device, bytecode);

// generate indices for simple quads
- int size = maxBatchSize * IndicesPerSprite * sizeof(short);
+ int size = maxBatchSize * SpriteBatch.IndicesPerSprite *
sizeof(short);
var indices = new DataStream(size, true, true);
- for (short i = 0; i < maxBatchSize * VerticesPerSprite; i +=
VerticesPerSprite)
+ for (short i = 0; i < maxBatchSize *
SpriteBatch.VerticesPerSprite; i += SpriteBatch.VerticesPerSprite)
{
indices.Write(i);
indices.Write(i + 1);
@@ -52,6 +50,8 @@
BindFlags = BindFlags.IndexBuffer,
Usage = ResourceUsage.Default
});
+
+ States = new CommonStates(device);
}

public void Dispose()
@@ -60,6 +60,7 @@
PixelShader.Dispose();
InputLayout.Dispose();
IndexBuffer.Dispose();
+ States.Dispose();
}
}
}
=======================================
--- /branches/lite/SlimDX.Toolkit/Utilities/AlignedArray.cs Mon Mar 19
14:40:29 2012
+++ /branches/lite/SlimDX.Toolkit/Utilities/AlignedArray.cs Tue Mar 20
11:00:08 2012
@@ -14,6 +14,7 @@
{
SafeHGlobal memory;
byte* ptr;
+ int elementSize;

/// <summary>
/// Gets a pointer to the aligned block of memory.
@@ -31,6 +32,14 @@
get;
private set;
}
+
+ /// <summary>
+ /// Gets a pointer to the element at the specified index.
+ /// </summary>
+ public byte* this[int index]
+ {
+ get { return Pointer + elementSize * index; }
+ }

/// <summary>
/// Initializes a new instance of the <see
cref="AlignedArray&lt;T&gt;"/> class.
@@ -46,12 +55,38 @@
throw new ArgumentOutOfRangeException("count",
count, "Invalid size passed for length of the array.");

Length = count;
- memory = new SafeHGlobal(Marshal.SizeOf(typeof(T)) * count +
15);
+ elementSize = Marshal.SizeOf(typeof(T));
+ memory = new SafeHGlobal(elementSize * count + 15);
void *mem = memory.DangerousGetHandle().ToPointer();

// make sure we get a 16-byte aligned pointer
ptr = (byte*)(((long)mem + 15) & ~0x0F);
}
+
+ /// <summary>
+ /// Reallocates the array with the new size and copies over the
existing elements.
+ /// </summary>
+ /// <param name="newCount">The number of elements in the new
array.</param>
+ /// <exception cref="ArgumentOutOfRangeException">Thrown if
<paramref name="newCount"/> is not a valid array length.</exception>
+ public void Realloc(int newCount)
+ {
+ if (newCount <= Length)
+ throw new ArgumentOutOfRangeException("newCount",
newCount, "Invalid size passed for length of the array.");
+
+ var newMemory = new SafeHGlobal(elementSize * newCount + 15);
+ void* mem = newMemory.DangerousGetHandle().ToPointer();
+
+ // make sure we get a 16-byte aligned pointer
+ var newPtr = (byte*)(((long)mem + 15) & ~0x0F);
+
+ for (int i = 0; i < Length * elementSize; i++)
+ newPtr[i] = ptr[i];
+
+ memory.Close();
+ memory = newMemory;
+ ptr = newPtr;
+ Length = newCount;
+ }

/// <summary>
/// Performs application-defined tasks associated with freeing,
releasing, or resetting unmanaged resources.
=======================================
--- /branches/lite/SlimMath/Vector4.cs Sat Mar 17 11:15:48 2012
+++ /branches/lite/SlimMath/Vector4.cs Tue Mar 20 11:00:08 2012
@@ -229,6 +229,22 @@
}
}
}
+
+ /// <summary>
+ /// Gets the X and Y components of the vector.
+ /// </summary>
+ public Vector2 XY
+ {
+ get { return new Vector2(X, Y); }
+ }
+
+ /// <summary>
+ /// Gets the Z and W components of the vector.
+ /// </summary>
+ public Vector2 ZW
+ {
+ get { return new Vector2(Z, W); }
+ }

/// <summary>
/// Converts the vector into a unit vector.
Reply all
Reply to author
Forward
0 new messages