Revision: 2189
Author: mike.popoloski
Date: Sat Mar 17 22:22:28 2012
Log: Added input element helper.
http://code.google.com/p/slimdx/source/detail?r=2189
Added:
/branches/lite/SlimDX.Toolkit/VertexTypes/InputElementFactory.cs
/branches/lite/SlimDX.Toolkit/VertexTypes/VertexElementAttribute.cs
Modified:
/branches/lite/SlimDX.Toolkit/SlimDX.Toolkit.csproj
=======================================
--- /dev/null
+++ /branches/lite/SlimDX.Toolkit/VertexTypes/InputElementFactory.cs Sat
Mar 17 22:22:28 2012
@@ -0,0 +1,94 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using SlimDX.Direct3D11;
+using SlimDX.DXGI;
+using SlimMath;
+
+namespace SlimDX.Toolkit
+{
+ /// <summary>
+ /// Defines a factory for creating input layout descriptions for
various vertex types.
+ /// </summary>
+ public static class InputElementFactory
+ {
+ static Dictionary<Type, InputElement[]> cache = new
Dictionary<Type, InputElement[]>();
+
+ /// <summary>
+ /// Retrieves an input layout for the given vertex type from the
cache, or creates a new one if it cannot be found.
+ /// </summary>
+ /// <param name="vertexType">Vertex type for which to get a
layout.</param>
+ /// <returns>An set of elements describing the input layout for
the given vertex type.</returns>
+ /// <exception cref="ArgumentNullException">Thrown if <paramref
name="vertexType"/> is <c>null</c>.</exception>
+ /// <exception cref="ArgumentException">Thrown if <paramref
name="vertexType"/> does not refer to a value type.</exception>
+ /// <exception cref="InvalidOperationException">Thrown if the
vertex type does not have any marked fields or if one of the fields uses an
unknown data type.</exception>
+ public static InputElement[] DemandCreate(Type vertexType)
+ {
+ InputElement[] elements;
+ if (cache.TryGetValue(vertexType, out elements))
+ return elements;
+
+ if (vertexType == null)
+ throw new ArgumentNullException("vertexType");
+ if (!vertexType.IsValueType)
+ throw new ArgumentException("Vertex types must be value
types.", "vertexType");
+
+ // get all the fields on the type that have the VertexElement
attribute applied
+ var fields = from f in
vertexType.GetFields(BindingFlags.Instance | BindingFlags.Public |
BindingFlags.NonPublic)
+ let a =
f.GetCustomAttributes(typeof(VertexElementAttribute), false)
+ where a.Length != 0
+ select new { Field = f, Data =
(VertexElementAttribute)a[0] };
+
+ // create the set of input elements for the given fields
+ elements = fields.Select(f => CreateElement(vertexType,
f.Field, f.Data)).ToArray();
+ if (elements.Length == 0)
+ throw new InvalidOperationException("Provided vertex type
does not have any fields marked with the VertexElement attribute.");
+
+ cache.Add(vertexType, elements);
+ return elements;
+ }
+
+ static InputElement CreateElement(Type vertexType, FieldInfo
field, VertexElementAttribute attribute)
+ {
+ int offset = Marshal.OffsetOf(vertexType,
field.Name).ToInt32();
+ var format = attribute.Format;
+ if (format == Format.Unknown)
+ {
+ if (field.FieldType == typeof(Vector2))
+ format = Format.R32G32_Float;
+ else if (field.FieldType == typeof(Vector3))
+ format = Format.R32G32B32_Float;
+ else if (field.FieldType == typeof(Vector4))
+ format = Format.R32G32B32A32_Float;
+ else if (field.FieldType == typeof(Color3))
+ format = Format.R32G32B32_Float;
+ else if (field.FieldType == typeof(Color4))
+ format = Format.R32G32B32A32_Float;
+ else if (field.FieldType == typeof(float))
+ format = Format.R32_Float;
+ else if (field.FieldType == typeof(int))
+ format = Format.R8G8B8A8_UNorm;
+ else if (field.FieldType == typeof(uint))
+ format = Format.R32_UInt;
+ else if (field.FieldType == typeof(short))
+ format = Format.R16_SInt;
+ else if (field.FieldType == typeof(ushort))
+ format = Format.R16_UInt;
+ else if (field.FieldType == typeof(byte))
+ format = Format.R8_UInt;
+ else if (field.FieldType == typeof(Half2))
+ format = Format.R16G16_Float;
+ else if (field.FieldType == typeof(Half4))
+ format = Format.R16G16B16A16_Float;
+ else if (field.FieldType == typeof(Half))
+ format = Format.R16_Float;
+ else
+ throw new
InvalidOperationException(string.Format("Unrecognized type for field '{0}'.
Please specify the format explicitly.", field.Name));
+ }
+
+ return new InputElement(attribute.Semantic,
attribute.SemanticIndex, format, offset, attribute.Slot,
attribute.Classification, attribute.InstanceDataStepRate);
+ }
+ }
+}
=======================================
--- /dev/null
+++ /branches/lite/SlimDX.Toolkit/VertexTypes/VertexElementAttribute.cs Sat
Mar 17 22:22:28 2012
@@ -0,0 +1,94 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using SlimDX.DXGI;
+using SlimDX.Direct3D11;
+
+namespace SlimDX.Toolkit
+{
+ /// <summary>
+ /// Describes the usage and format of an element in a vertex structure.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
+ public sealed class VertexElementAttribute : Attribute
+ {
+ /// <summary>
+ /// The HLSL semantic associated with this element in a shader
input-signature.
+ /// </summary>
+ public string Semantic
+ {
+ get;
+ private set;
+ }
+
+ /// <summary>
+ /// The data type of the element data.
+ /// </summary>
+ public Format Format
+ {
+ get;
+ private set;
+ }
+
+ /// <summary>
+ /// The semantic index for the element. A semantic index modifies
a semantic, with an integer index number. A semantic index is only needed
in a
+ /// case where there is more than one element with the same
semantic. For example, a 4x4 matrix would have four components each with
the semantic
+ /// name matrix, however each of the four component would have
different semantic indices (0, 1, 2, and 3).
+ /// </summary>
+ public int SemanticIndex
+ {
+ get;
+ set;
+ }
+
+ /// <summary>
+ /// An integer value that identifies the input-assembler. Valid
values are between 0 and 15.
+ /// </summary>
+ public int Slot
+ {
+ get;
+ set;
+ }
+
+ /// <summary>
+ /// Identifies the input data class for a single input slot.
+ /// </summary>
+ public InputClassification Classification
+ {
+ get;
+ set;
+ }
+
+ /// <summary>
+ /// The number of instances to draw using the same per-instance
data before advancing in the buffer by one element.
+ /// This value must be 0 for an element that contains per-vertex
data.
+ /// </summary>
+ public int InstanceDataStepRate
+ {
+ get;
+ set;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see
cref="VertexElementAttribute"/> class.
+ /// </summary>
+ /// <param name="semantic">The HLSL semantic.</param>
+ public VertexElementAttribute(string semantic)
+ : this(semantic, Format.Unknown)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see
cref="VertexElementAttribute"/> class.
+ /// </summary>
+ /// <param name="semantic">The HLSL semantic.</param>
+ /// <param name="format">Format of the element data.</param>
+ public VertexElementAttribute(string semantic, Format format)
+ {
+ Semantic = semantic;
+ Format = format;
+ Classification = InputClassification.PerVertexData;
+ }
+ }
+}
=======================================
--- /branches/lite/SlimDX.Toolkit/SlimDX.Toolkit.csproj Sat Mar 17 21:28:36
2012
+++ /branches/lite/SlimDX.Toolkit/SlimDX.Toolkit.csproj Sat Mar 17 22:22:28
2012
@@ -47,6 +47,8 @@
<Compile Include="Sprites\SpriteShaders.cs" />
<Compile Include="Utilities\SharedResourcePool.cs" />
<Compile Include="Sprites\SpriteBatch.cs" />
+ <Compile Include="VertexTypes\InputElementFactory.cs" />
+ <Compile Include="VertexTypes\VertexElementAttribute.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\build\SlimDX.vcxproj">
@@ -58,9 +60,7 @@
<Name>SlimMath</Name>
</ProjectReference>
</ItemGroup>
- <ItemGroup>
- <Folder Include="VertexTypes\" />
- </ItemGroup>
+ <ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the
targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.