Revision: 2192
Author: mike.popoloski
Date: Mon Mar 19 16:08:39 2012
Log: Common states implementation.
http://code.google.com/p/slimdx/source/detail?r=2192
Added:
/branches/lite/SlimDX.Toolkit/Drawing
/branches/lite/SlimDX.Toolkit/Drawing/CommonStates.cs
/branches/lite/SlimDX.Toolkit/Drawing/ConstantBuffer.cs
Modified:
/branches/lite/SlimDX.Toolkit/SlimDX.Toolkit.csproj
/branches/lite/SlimDX.Toolkit/Sprites/SpriteBatch.cs
/branches/lite/SlimDX.Toolkit/Sprites/SpriteContextResources.cs
=======================================
--- /dev/null
+++ /branches/lite/SlimDX.Toolkit/Drawing/CommonStates.cs Mon Mar 19
16:08:39 2012
@@ -0,0 +1,254 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using SlimDX.Direct3D11;
+
+namespace SlimDX.Toolkit
+{
+ /// <summary>
+ /// Lightweight convenience class for creating commonly used state
objects.
+ /// </summary>
+ public class CommonStates : IDisposable
+ {
+ static SharedResourcePool<Device, CommonStatesImpl>
sharedResources = new SharedResourcePool<Device, CommonStatesImpl>();
+
+ class CommonStatesImpl : IDisposable
+ {
+ Device device;
+
+ public Lazy<BlendState> Opaque;
+ public Lazy<BlendState> AlphaBlend;
+ public Lazy<BlendState> Additive;
+ public Lazy<BlendState> NonPremultiplied;
+
+ public Lazy<DepthStencilState> DepthNone;
+ public Lazy<DepthStencilState> DepthDefault;
+ public Lazy<DepthStencilState> DepthRead;
+
+ public Lazy<RasterizerState> CullNone;
+ public Lazy<RasterizerState> CullClockwise;
+ public Lazy<RasterizerState> CullCounterClockwise;
+ public Lazy<RasterizerState> Wireframe;
+
+ public Lazy<SamplerState> PointWrap;
+ public Lazy<SamplerState> PointClamp;
+ public Lazy<SamplerState> LinearWrap;
+ public Lazy<SamplerState> LinearClamp;
+ public Lazy<SamplerState> AnisotropicWrap;
+ public Lazy<SamplerState> AnisotropicClamp;
+
+ public CommonStatesImpl(Device device)
+ {
+ this.device = device;
+
+ Opaque = new Lazy<BlendState>(() =>
CreateBlendState(BlendOption.One, BlendOption.Zero));
+ AlphaBlend = new Lazy<BlendState>(() =>
CreateBlendState(BlendOption.One, BlendOption.InverseSourceAlpha));
+ Additive = new Lazy<BlendState>(() =>
CreateBlendState(BlendOption.SourceAlpha, BlendOption.One));
+ NonPremultiplied = new Lazy<BlendState>(() =>
CreateBlendState(BlendOption.SourceAlpha, BlendOption.InverseSourceAlpha));
+
+ DepthNone = new Lazy<DepthStencilState>(() =>
CreateDepthStencilState(false, false));
+ DepthDefault = new Lazy<DepthStencilState>(() =>
CreateDepthStencilState(true, true));
+ DepthRead = new Lazy<DepthStencilState>(() =>
CreateDepthStencilState(true, false));
+
+ CullNone = new Lazy<RasterizerState>(() =>
CreateRasterizerState(CullMode.None, FillMode.Solid));
+ CullClockwise = new Lazy<RasterizerState>(() =>
CreateRasterizerState(CullMode.Front, FillMode.Solid));
+ CullCounterClockwise = new Lazy<RasterizerState>(() =>
CreateRasterizerState(CullMode.Back, FillMode.Solid));
+ Wireframe = new Lazy<RasterizerState>(() =>
CreateRasterizerState(CullMode.Back, FillMode.Wireframe));
+
+ PointWrap = new Lazy<SamplerState>(() =>
CreateSamplerState(Filter.MinMagMipPoint, TextureAddressMode.Wrap));
+ PointClamp = new Lazy<SamplerState>(() =>
CreateSamplerState(Filter.MinMagMipPoint, TextureAddressMode.Clamp));
+ LinearWrap = new Lazy<SamplerState>(() =>
CreateSamplerState(Filter.MinMagMipLinear, TextureAddressMode.Wrap));
+ LinearClamp = new Lazy<SamplerState>(() =>
CreateSamplerState(Filter.MinMagMipLinear, TextureAddressMode.Clamp));
+ AnisotropicWrap = new Lazy<SamplerState>(() =>
CreateSamplerState(Filter.Anisotropic, TextureAddressMode.Wrap));
+ AnisotropicClamp = new Lazy<SamplerState>(() =>
CreateSamplerState(Filter.Anisotropic, TextureAddressMode.Clamp));
+ }
+
+ public void Dispose()
+ {
+ Dispose(ref Opaque);
+ Dispose(ref AlphaBlend);
+ Dispose(ref Additive);
+ Dispose(ref NonPremultiplied);
+
+ Dispose(ref DepthNone);
+ Dispose(ref DepthDefault);
+ Dispose(ref DepthRead);
+
+ Dispose(ref CullNone);
+ Dispose(ref CullClockwise);
+ Dispose(ref CullCounterClockwise);
+ Dispose(ref Wireframe);
+
+ Dispose(ref PointWrap);
+ Dispose(ref PointClamp);
+ Dispose(ref LinearWrap);
+ Dispose(ref LinearClamp);
+ Dispose(ref AnisotropicWrap);
+ Dispose(ref AnisotropicClamp);
+ }
+
+ void Dispose<T>(ref Lazy<T> state) where T : IDisposable
+ {
+ if (state != null && state.IsValueCreated)
+ {
+ state.Value.Dispose();
+ state = null;
+ }
+ }
+
+ BlendState CreateBlendState(BlendOption sourceBlend,
BlendOption destinationBlend)
+ {
+ var desc = new BlendStateDescription();
+ desc.RenderTargets[0].BlendEnable = (sourceBlend !=
BlendOption.One) || (destinationBlend != BlendOption.Zero);
+ desc.RenderTargets[0].SourceBlend =
desc.RenderTargets[0].SourceBlendAlpha = sourceBlend;
+ desc.RenderTargets[0].DestinationBlend =
desc.RenderTargets[0].DestinationBlendAlpha = destinationBlend;
+ desc.RenderTargets[0].BlendOperation =
desc.RenderTargets[0].BlendOperationAlpha = BlendOperation.Add;
+ desc.RenderTargets[0].RenderTargetWriteMask =
ColorWriteMaskFlags.All;
+
+ return BlendState.FromDescription(device, desc);
+ }
+
+ DepthStencilState CreateDepthStencilState(bool enable, bool
writeEnable)
+ {
+ return DepthStencilState.FromDescription(device, new
DepthStencilStateDescription
+ {
+ IsDepthEnabled = enable,
+ DepthWriteMask = writeEnable ? DepthWriteMask.All :
DepthWriteMask.Zero,
+ DepthComparison = Comparison.LessEqual
+ });
+ }
+
+ RasterizerState CreateRasterizerState(CullMode cullMode,
FillMode fillMode)
+ {
+ return RasterizerState.FromDescription(device, new
RasterizerStateDescription
+ {
+ CullMode = cullMode,
+ FillMode = fillMode,
+ IsDepthClipEnabled = true,
+ IsMultisampleEnabled = true
+ });
+ }
+
+ SamplerState CreateSamplerState(Filter filter,
TextureAddressMode addressMode)
+ {
+ return SamplerState.FromDescription(device, new
SamplerDescription
+ {
+ Filter = filter,
+ AddressU = addressMode,
+ AddressV = addressMode,
+ AddressW = addressMode,
+ MaximumLod = float.MaxValue,
+ MaximumAnisotropy = 16,
+ ComparisonFunction = Comparison.Never
+ });
+ }
+ }
+
+ ISharedResource<CommonStatesImpl> resource;
+ CommonStatesImpl impl;
+
+ /// <summary>
+ /// An opaque blending mode.
+ /// </summary>
+ public BlendState Opaque { get { return impl.Opaque.Value; } }
+
+ /// <summary>
+ /// Alpha blending mode.
+ /// </summary>
+ public BlendState AlphaBlend { get { return impl.AlphaBlend.Value;
} }
+
+ /// <summary>
+ /// Additive blending mode.
+ /// </summary>
+ public BlendState Additive { get { return impl.Additive.Value; } }
+
+ /// <summary>
+ /// Specific-alpha blending mode.
+ /// </summary>
+ public BlendState NonPremultiplied { get { return
impl.NonPremultiplied.Value; } }
+
+ /// <summary>
+ /// No depth-testing.
+ /// </summary>
+ public DepthStencilState DepthNone { get { return
impl.DepthNone.Value; } }
+
+ /// <summary>
+ /// Depth reading and writing.
+ /// </summary>
+ public DepthStencilState DepthDefault { get { return
impl.DepthDefault.Value; } }
+
+ /// <summary>
+ /// Depth read but not write.
+ /// </summary>
+ public DepthStencilState DepthRead { get { return
impl.DepthRead.Value; } }
+
+ /// <summary>
+ /// No culling.
+ /// </summary>
+ public RasterizerState CullNone { get { return
impl.CullNone.Value; } }
+
+ /// <summary>
+ /// Clockwise culling.
+ /// </summary>
+ public RasterizerState CullClockwise { get { return
impl.CullClockwise.Value; } }
+
+ /// <summary>
+ /// Counter-clockwise culling.
+ /// </summary>
+ public RasterizerState CullCounterClockwise { get { return
impl.CullCounterClockwise.Value; } }
+
+ /// <summary>
+ /// Wireframe rendering.
+ /// </summary>
+ public RasterizerState Wireframe { get { return
impl.Wireframe.Value; } }
+
+ /// <summary>
+ /// Point filtering and wrap addressing.
+ /// </summary>
+ public SamplerState PointWrap { get { return impl.PointWrap.Value;
} }
+
+ /// <summary>
+ /// Point filtering and clamp addressing.
+ /// </summary>
+ public SamplerState PointClamp { get { return
impl.PointClamp.Value; } }
+
+ /// <summary>
+ /// Linear filtering and wrap addressing.
+ /// </summary>
+ public SamplerState LinearWrap { get { return
impl.LinearWrap.Value; } }
+
+ /// <summary>
+ /// Linear filtering and clamp addressing.
+ /// </summary>
+ public SamplerState LinearClamp { get { return
impl.LinearClamp.Value; } }
+
+ /// <summary>
+ /// Anisotropic filtering and wrap addressing.
+ /// </summary>
+ public SamplerState AnisotropicWrap { get { return
impl.AnisotropicWrap.Value; } }
+
+ /// <summary>
+ /// Anisotropic filtering and clamp addressing.
+ /// </summary>
+ public SamplerState AnisotropicClamp { get { return
impl.AnisotropicClamp.Value; } }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="CommonStates"/>
class.
+ /// </summary>
+ /// <param name="device">The device used to create the state
objects.</param>
+ public CommonStates(Device device)
+ {
+ resource = sharedResources.DemandCreate(device, () => new
CommonStatesImpl(device));
+ impl = resource.Resource;
+ }
+
+ /// <summary>
+ /// Performs application-defined tasks associated with freeing,
releasing, or resetting unmanaged resources.
+ /// </summary>
+ public void Dispose()
+ {
+ resource.Dispose();
+ }
+ }
+}
=======================================
--- /dev/null
+++ /branches/lite/SlimDX.Toolkit/Drawing/ConstantBuffer.cs Mon Mar 19
16:08:39 2012
@@ -0,0 +1,71 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Buffer = SlimDX.Direct3D11.Buffer;
+using SlimDX.Direct3D11;
+using System.Runtime.InteropServices;
+
+namespace SlimDX.Toolkit
+{
+ /// <summary>
+ /// Provides a wrapper around a constant buffer structure.
+ /// </summary>
+ /// <typeparam name="T">The type that will act as the constant buffer.
Its size must be a multiple of 16 bytes.</typeparam>
+ public class ConstantBuffer<T> : IDisposable where T : struct
+ {
+ /// <summary>
+ /// The underlying Direct3D buffer.
+ /// </summary>
+ public Buffer Buffer
+ {
+ get;
+ private set;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see
cref="ConstantBuffer<T>"/> class.
+ /// </summary>
+ /// <param name="device">The device used to create the constant
buffer.</param>
+ /// <exception cref="InvalidOperationException">Thrown if the
constant buffer type is not a multiple of 16 bytes.</exception>
+ public ConstantBuffer(Device device)
+ {
+ int size = Marshal.SizeOf(typeof(T));
+ if (size % 16 != 0)
+ throw new InvalidOperationException("Constant buffer sizes
must be a multiple of 16 bytes.");
+
+ Buffer = new Buffer(device, new BufferDescription
+ {
+ SizeInBytes = size,
+ Usage = ResourceUsage.Dynamic,
+ BindFlags = BindFlags.ConstantBuffer,
+ CpuAccessFlags = CpuAccessFlags.Write
+ });
+ }
+
+ /// <summary>
+ /// Writes new data into the constant buffer.
+ /// </summary>
+ /// <param name="context">The rendering context.</param>
+ /// <param name="data">The data to update.</param>
+ public void SetData(DeviceContext context, ref T data)
+ {
+ var box = context.MapSubresource(Buffer, MapMode.WriteDiscard,
MapFlags.None);
+ box.Data.Write(data);
+
+ context.UnmapSubresource(Buffer, 0);
+ }
+
+ /// <summary>
+ /// Performs application-defined tasks associated with freeing,
releasing, or resetting unmanaged resources.
+ /// </summary>
+ public void Dispose()
+ {
+ if (Buffer != null)
+ {
+ Buffer.Dispose();
+ Buffer = null;
+ }
+ }
+ }
+}
=======================================
--- /branches/lite/SlimDX.Toolkit/SlimDX.Toolkit.csproj Mon Mar 19 14:40:29
2012
+++ /branches/lite/SlimDX.Toolkit/SlimDX.Toolkit.csproj Mon Mar 19 16:08:39
2012
@@ -44,6 +44,8 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
+ <Compile Include="Drawing\CommonStates.cs" />
+ <Compile Include="Drawing\ConstantBuffer.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Sprites\SpriteContextResources.cs" />
<Compile Include="Sprites\SpriteDeviceResources.cs" />
=======================================
--- /branches/lite/SlimDX.Toolkit/Sprites/SpriteBatch.cs Mon Mar 19
14:40:29 2012
+++ /branches/lite/SlimDX.Toolkit/Sprites/SpriteBatch.cs Mon Mar 19
16:08:39 2012
@@ -84,8 +84,9 @@
static SharedResourcePool<Device, SpriteDeviceResources>
sharedDeviceResources = new SharedResourcePool<Device,
SpriteDeviceResources>();
static SharedResourcePool<DeviceContext, SpriteContextResources>
sharedContextResources = new SharedResourcePool<DeviceContext,
SpriteContextResources>();
- Device device;
bool started;
+ Device device;
+ DeviceContext context;
SpriteSortMode sortMode = SpriteSortMode.Deferred;
ISharedResource<SpriteDeviceResources> deviceResources;
ISharedResource<SpriteContextResources> contextResources;
@@ -158,6 +159,7 @@
{
TransformMatrix = Matrix.Identity;
device = context.Device;
+ this.context = context;
deviceResources = sharedDeviceResources.DemandCreate(device,
() => new SpriteDeviceResources(device, MaxBatchSize));
contextResources =
sharedContextResources.DemandCreate(context, () => new
SpriteContextResources(context, MaxBatchSize));
@@ -332,6 +334,7 @@
void PrepareForRendering()
{
+
}
void FlushBatch()
=======================================
--- /branches/lite/SlimDX.Toolkit/Sprites/SpriteContextResources.cs Mon Mar
19 14:40:29 2012
+++ /branches/lite/SlimDX.Toolkit/Sprites/SpriteContextResources.cs Mon Mar
19 16:08:39 2012
@@ -11,21 +11,15 @@
{
const int VerticesPerSprite = 4;
- public Buffer VertexBuffer;
- public Buffer ConstantBuffer;
public bool InImmediateMode;
public int VertexBufferPosition;
+ public Buffer VertexBuffer;
+ public ConstantBuffer<Matrix> ConstantBuffer;
public SpriteContextResources(DeviceContext context, int
maxBatchSize)
{
// create a dynamic write-only constant buffer for the sprite
transform
- ConstantBuffer = new Buffer(context.Device, new
BufferDescription
- {
- SizeInBytes = Matrix.SizeInBytes,
- Usage = ResourceUsage.Dynamic,
- BindFlags = BindFlags.ConstantBuffer,
- CpuAccessFlags = CpuAccessFlags.Write
- });
+ ConstantBuffer = new ConstantBuffer<Matrix>(context.Device);
// create a dynamic write-only vertex buffer for the sprite
vertices, limited by maxBatchSize
VertexBuffer = new Buffer(context.Device, new BufferDescription