Refactored a lot of the rendering in the metro system and improved the memory usage of the ParameterBuffer

This commit is contained in:
SND\AstrorEnales_cp 2012-08-19 21:01:29 +00:00
parent 2ffe3004cd
commit 947287b0ab
7 changed files with 144 additions and 158 deletions

View File

@ -1,8 +1,7 @@
using System;
using ANX.Framework.Graphics; using ANX.Framework.Graphics;
using ANX.Framework.NonXNA; using ANX.Framework.NonXNA;
using Dx11 = SharpDX.Direct3D11;
using ANX.RenderSystem.Windows.Metro.Shader; using ANX.RenderSystem.Windows.Metro.Shader;
using Dx11 = SharpDX.Direct3D11;
// This file is part of the ANX.Framework created by the // This file is part of the ANX.Framework created by the
// "ANX.Framework developer group" and released under the Ms-PL license. // "ANX.Framework developer group" and released under the Ms-PL license.
@ -31,34 +30,6 @@ namespace ANX.RenderSystem.Windows.Metro
get; get;
private set; private set;
} }
public Dx11.VertexShader VertexShader
{
get
{
if (vertexShader == null)
{
vertexShader = new Dx11.VertexShader(
NativeDxDevice.Current.NativeDevice, nativePass.VertexCode);
}
return vertexShader;
}
}
public Dx11.PixelShader PixelShader
{
get
{
if (pixelShader == null)
{
pixelShader = new Dx11.PixelShader(
NativeDxDevice.Current.NativeDevice, nativePass.PixelCode);
}
return pixelShader;
}
}
#endregion #endregion
#region Constructor #region Constructor
@ -72,10 +43,25 @@ namespace ANX.RenderSystem.Windows.Metro
} }
#endregion #endregion
public Dx11.InputLayout BuildLayout(Dx11.Device d3dDevice, #region BuildLayout
Dx11.InputElement[] elements) public Dx11.InputLayout BuildLayout(Dx11.Device d3dDevice, Dx11.InputElement[] elements)
{ {
return new Dx11.InputLayout(d3dDevice, nativePass.VertexCode, elements); return new Dx11.InputLayout(d3dDevice, nativePass.VertexCode, elements);
} }
#endregion
#region Apply
public void Apply(NativeDxDevice device)
{
if (vertexShader == null)
vertexShader = new Dx11.VertexShader(device.NativeDevice, nativePass.VertexCode);
if (pixelShader == null)
pixelShader = new Dx11.PixelShader(device.NativeDevice, nativePass.PixelCode);
device.NativeContext.VertexShader.Set(vertexShader);
device.NativeContext.PixelShader.Set(pixelShader);
}
#endregion
} }
} }

View File

@ -1,7 +1,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using ANX.Framework.Graphics; using ANX.Framework.Graphics;
using ANX.Framework.NonXNA; using ANX.Framework.NonXNA;
using Dx11 = SharpDX.Direct3D11;
using ANX.RenderSystem.Windows.Metro.Shader; using ANX.RenderSystem.Windows.Metro.Shader;
// This file is part of the ANX.Framework created by the // This file is part of the ANX.Framework created by the
@ -13,8 +12,7 @@ namespace ANX.RenderSystem.Windows.Metro
public class EffectTechnique_Metro : INativeEffectTechnique public class EffectTechnique_Metro : INativeEffectTechnique
{ {
#region Private #region Private
private Effect parentEffect; private EffectPass_Metro[] passes;
private List<EffectPass_Metro> passes;
#endregion #endregion
#region Public #region Public
@ -24,6 +22,14 @@ namespace ANX.RenderSystem.Windows.Metro
private set; private set;
} }
public int PassCount
{
get
{
return passes.Length;
}
}
public IEnumerable<EffectPass> Passes public IEnumerable<EffectPass> Passes
{ {
get get
@ -34,33 +40,28 @@ namespace ANX.RenderSystem.Windows.Metro
} }
} }
} }
public EffectPass_Metro this[int index]
{
get
{
return passes[index];
}
}
#endregion #endregion
#region Constructor #region Constructor
public EffectTechnique_Metro(string setName, Effect setParentEffect, public EffectTechnique_Metro(string setName, Effect parentEffect,
ExtendedShaderPass[] nativePasses) ExtendedShaderPass[] nativePasses)
{ {
Name = setName; Name = setName;
parentEffect = setParentEffect;
ParsePasses(nativePasses); passes = new EffectPass_Metro[nativePasses.Length];
for (int index = 0; index < nativePasses.Length; index++)
{
passes[index] = new EffectPass_Metro(parentEffect, nativePasses[index]);
}
} }
#endregion #endregion
#region ParsePasses
private void ParsePasses(ExtendedShaderPass[] nativePasses)
{
passes = new List<EffectPass_Metro>();
foreach (ExtendedShaderPass pass in nativePasses)
{
passes.Add(new EffectPass_Metro(parentEffect, pass));
}
}
#endregion
public EffectPass_Metro GetPass(int index)
{
return passes[index];
}
} }
} }

View File

@ -87,10 +87,9 @@ namespace ANX.RenderSystem.Windows.Metro
{ {
techniques = new List<EffectTechnique>(); techniques = new List<EffectTechnique>();
foreach (string key in shader.Techniques.Keys) foreach (string key in shader.TechniqueNames)
{ {
var nativeTechnique = new EffectTechnique_Metro(key, ManagedEffect, var nativeTechnique = new EffectTechnique_Metro(key, ManagedEffect, shader[key]);
shader.Techniques[key]);
techniques.Add(new EffectTechnique(ManagedEffect, nativeTechnique)); techniques.Add(new EffectTechnique(ManagedEffect, nativeTechnique));
} }
} }
@ -131,7 +130,9 @@ namespace ANX.RenderSystem.Windows.Metro
#region Apply #region Apply
public void Apply(GraphicsDevice graphicsDevice) public void Apply(GraphicsDevice graphicsDevice)
{ {
((GraphicsDeviceWindowsMetro)graphicsDevice.NativeDevice).currentEffect = this; var metroDevice = (GraphicsDeviceWindowsMetro)graphicsDevice.NativeDevice;
metroDevice.currentTechnique =
ManagedEffect.CurrentTechnique.NativeTechnique as EffectTechnique_Metro;
paramBuffer.Apply(); paramBuffer.Apply();
} }
#endregion #endregion

View File

@ -18,7 +18,7 @@ namespace ANX.RenderSystem.Windows.Metro
#endregion #endregion
#region Private #region Private
internal Effect_Metro currentEffect; internal EffectTechnique_Metro currentTechnique;
private VertexBuffer currentVertexBuffer; private VertexBuffer currentVertexBuffer;
private Dx11.Viewport currentViewport; private Dx11.Viewport currentViewport;
private uint lastClearColor; private uint lastClearColor;
@ -121,52 +121,34 @@ namespace ANX.RenderSystem.Windows.Metro
#region DrawIndexedPrimitives #region DrawIndexedPrimitives
public void DrawIndexedPrimitives(PrimitiveType primitiveType, int baseVertex, public void DrawIndexedPrimitives(PrimitiveType primitiveType, int baseVertex,
int minVertexIndex, int numVertices, int startIndex, int primitiveCount) int minVertexIndex, int numVertices, int startIndex, int primitiveCount)
{ {
var technique = currentEffect.ManagedEffect.CurrentTechnique; SetInputLayout();
var nativeTechnique = technique.NativeTechnique as EffectTechnique_Metro; ApplyPrimitiveType(primitiveType);
EffectPass_Metro nativePass = nativeTechnique.GetPass(0);
SetInputLayout(currentVertexBuffer.VertexDeclaration, nativePass);
var d3dContext = NativeDevice.NativeContext;
d3dContext.InputAssembler.PrimitiveTopology = FormatConverter.Translate(primitiveType);
d3dContext.VertexShader.Set(nativePass.VertexShader);
d3dContext.PixelShader.Set(nativePass.PixelShader);
//d3dContext.PixelShader.SetSampler(0, sampler);
NativeDevice.SetDefaultTargets(); NativeDevice.SetDefaultTargets();
//d3dContext.PixelShader.SetSampler(0, sampler);
//for (int i = 0; i < technique.Description.PassCount; ++i)
//{
// pass.Apply();
int indexCount = CalculateVertexCount(primitiveType, primitiveCount); int indexCount = CalculateVertexCount(primitiveType, primitiveCount);
d3dContext.DrawIndexed(indexCount, startIndex, baseVertex); for (int passIndex = 0; passIndex < currentTechnique.PassCount; passIndex++)
//} {
currentTechnique[passIndex].Apply(NativeDevice);
NativeDevice.NativeContext.DrawIndexed(indexCount, startIndex, baseVertex);
}
} }
#endregion #endregion
#region DrawPrimitives #region DrawPrimitives
public void DrawPrimitives(PrimitiveType primitiveType, int vertexOffset, int primitiveCount) public void DrawPrimitives(PrimitiveType primitiveType, int vertexOffset, int primitiveCount)
{ {
var technique = currentEffect.ManagedEffect.CurrentTechnique; SetInputLayout();
var nativeTechnique = technique.NativeTechnique as EffectTechnique_Metro; ApplyPrimitiveType(primitiveType);
EffectPass_Metro nativePass = nativeTechnique.GetPass(0);
SetInputLayout(currentVertexBuffer.VertexDeclaration, nativePass);
var d3dContext = NativeDevice.NativeContext;
d3dContext.InputAssembler.PrimitiveTopology = FormatConverter.Translate(primitiveType);
d3dContext.VertexShader.Set(nativePass.VertexShader);
d3dContext.PixelShader.Set(nativePass.PixelShader);
NativeDevice.SetDefaultTargets(); NativeDevice.SetDefaultTargets();
//d3dContext.PixelShader.SetSampler(0, sampler);
//for (int i = 0; i < technique.Description.PassCount; ++i) for (int passIndex = 0; passIndex < currentTechnique.PassCount; passIndex++)
//{ {
// pass.Apply(); currentTechnique[passIndex].Apply(NativeDevice);
d3dContext.Draw(primitiveCount, vertexOffset); NativeDevice.NativeContext.Draw(primitiveCount, vertexOffset);
//} }
} }
#endregion #endregion
@ -229,6 +211,14 @@ namespace ANX.RenderSystem.Windows.Metro
} }
#endregion // DrawUserPrimitives<T> #endregion // DrawUserPrimitives<T>
#region ApplyPrimitiveType
private void ApplyPrimitiveType(PrimitiveType primitiveType)
{
var d3dContext = NativeDevice.NativeContext;
d3dContext.InputAssembler.PrimitiveTopology = FormatConverter.Translate(primitiveType);
}
#endregion
#region CalculateVertexCount #region CalculateVertexCount
private int CalculateVertexCount(PrimitiveType type, int primitiveCount) private int CalculateVertexCount(PrimitiveType type, int primitiveCount)
@ -306,9 +296,9 @@ namespace ANX.RenderSystem.Windows.Metro
#endregion #endregion
#region SetInputLayout #region SetInputLayout
private void SetInputLayout(VertexDeclaration vertexDeclaration, EffectPass_Metro nativePass) private void SetInputLayout()
{ {
VertexElement[] vertexElements = vertexDeclaration.GetVertexElements(); VertexElement[] vertexElements = currentVertexBuffer.VertexDeclaration.GetVertexElements();
int elementCount = vertexElements.Length; int elementCount = vertexElements.Length;
var inputElements = new Dx11.InputElement[elementCount]; var inputElements = new Dx11.InputElement[elementCount];
@ -317,6 +307,7 @@ namespace ANX.RenderSystem.Windows.Metro
inputElements[i] = CreateInputElementFromVertexElement(vertexElements[i]); inputElements[i] = CreateInputElementFromVertexElement(vertexElements[i]);
} }
var nativePass = currentTechnique[0];
NativeDevice.NativeContext.InputAssembler.InputLayout = NativeDevice.NativeContext.InputAssembler.InputLayout =
nativePass.BuildLayout(NativeDevice.NativeDevice, inputElements); nativePass.BuildLayout(NativeDevice.NativeDevice, inputElements);
} }

View File

@ -9,21 +9,47 @@ using System.IO;
namespace ANX.RenderSystem.Windows.Metro.Shader namespace ANX.RenderSystem.Windows.Metro.Shader
{ {
public class ExtendedShader public class ExtendedShader
{ {
public Dictionary<string, ExtendedShaderPass[]> Techniques; #region Private
public List<ExtendedShaderParameter> Parameters; private Dictionary<string, ExtendedShaderPass[]> techniques;
#endregion
public ExtendedShader(Stream stream) #region Public
public ExtendedShaderPass[] this[string name]
{
get
{
return techniques[name];
}
}
public string[] TechniqueNames
{
get
{
return new List<string>(techniques.Keys).ToArray();
}
}
public ExtendedShaderParameter[] Parameters
{
get;
private set;
}
#endregion
#region Constructor
public ExtendedShader(Stream stream)
{ {
Techniques = new Dictionary<string, ExtendedShaderPass[]>(); techniques = new Dictionary<string, ExtendedShaderPass[]>();
Parameters = new List<ExtendedShaderParameter>();
BinaryReader reader = new BinaryReader(stream); BinaryReader reader = new BinaryReader(stream);
int numberOfVariables = reader.ReadInt32(); int numberOfVariables = reader.ReadInt32();
Parameters = new ExtendedShaderParameter[numberOfVariables];
for (int index = 0; index < numberOfVariables; index++) for (int index = 0; index < numberOfVariables; index++)
{ {
Parameters.Add(new ExtendedShaderParameter(reader)); Parameters[index] = new ExtendedShaderParameter(reader);
} }
int numberOfStructures = reader.ReadInt32(); int numberOfStructures = reader.ReadInt32();
@ -45,13 +71,14 @@ namespace ANX.RenderSystem.Windows.Metro.Shader
string name = reader.ReadString(); string name = reader.ReadString();
int numberOfPasses = reader.ReadInt32(); int numberOfPasses = reader.ReadInt32();
ExtendedShaderPass[] passes = new ExtendedShaderPass[numberOfPasses]; ExtendedShaderPass[] passes = new ExtendedShaderPass[numberOfPasses];
Techniques.Add(name, passes); techniques.Add(name, passes);
for (int passIndex = 0; passIndex < numberOfPasses; passIndex++) for (int passIndex = 0; passIndex < numberOfPasses; passIndex++)
{ {
passes[passIndex] = new ExtendedShaderPass(reader); passes[passIndex] = new ExtendedShaderPass(reader);
} }
} }
} }
#endregion
} }
} }

View File

@ -55,7 +55,9 @@ namespace ANX.RenderSystem.Windows.Metro.Shader
ArraySize = reader.ReadInt32(); ArraySize = reader.ReadInt32();
IsTexture = Type.ToLower().Contains("texture"); IsTexture = Type.ToLower().Contains("texture");
SizeInBytes = GetParameterTypeSize() * ArraySize; SizeInBytes = GetParameterTypeSize();
if (ArraySize > 0)
SizeInBytes *= ArraySize;
int numberOfDimensions = reader.ReadByte(); int numberOfDimensions = reader.ReadByte();
TypeDimensions = new int[numberOfDimensions]; TypeDimensions = new int[numberOfDimensions];

View File

@ -1,5 +1,4 @@
using System; using System;
using System.IO;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using Dx11 = SharpDX.Direct3D11; using Dx11 = SharpDX.Direct3D11;
@ -16,8 +15,8 @@ namespace ANX.RenderSystem.Windows.Metro.Shader
private NativeDxDevice graphicsDevice; private NativeDxDevice graphicsDevice;
private Effect_Metro parentEffect; private Effect_Metro parentEffect;
private Array[] setData; private int[] parameterOffsets;
private byte[] setData;
private int dataSize; private int dataSize;
#endregion #endregion
@ -27,7 +26,20 @@ namespace ANX.RenderSystem.Windows.Metro.Shader
{ {
graphicsDevice = setGraphicsDevice; graphicsDevice = setGraphicsDevice;
parentEffect = setParentEffect; parentEffect = setParentEffect;
setData = new Array[parentEffect.shader.Parameters.Count]; dataSize = 0;
var offsets = new System.Collections.Generic.List<int>();
foreach(var parameter in parentEffect.shader.Parameters)
{
if (parameter.IsTexture == false)
{
offsets.Add(dataSize);
dataSize += parameter.SizeInBytes;
}
}
parameterOffsets = offsets.ToArray();
setData = new byte[dataSize];
} }
#endregion #endregion
@ -38,7 +50,8 @@ namespace ANX.RenderSystem.Windows.Metro.Shader
if (indexOfParameter == -1) if (indexOfParameter == -1)
return; return;
setData[indexOfParameter] = StructureToBytes(value); byte[] dataToAdd = StructureToBytes(value);
Array.Copy(dataToAdd, 0, setData, parameterOffsets[indexOfParameter], dataToAdd.Length);
} }
#endregion #endregion
@ -52,18 +65,15 @@ namespace ANX.RenderSystem.Windows.Metro.Shader
value = FillArrayIfNeeded(value, indexOfParameter); value = FillArrayIfNeeded(value, indexOfParameter);
int sizePerItem = Marshal.SizeOf(typeof(T)); int sizePerItem = Marshal.SizeOf(typeof(T));
byte[] result = new byte[sizePerItem * value.Length];
int offset = 0; int offset = 0;
IntPtr ptr = Marshal.AllocHGlobal(sizePerItem); IntPtr ptr = Marshal.AllocHGlobal(sizePerItem);
for (int index = 0; index < value.Length; index++) for (int index = 0; index < value.Length; index++)
{ {
Marshal.StructureToPtr(value[index], ptr, true); Marshal.StructureToPtr(value[index], ptr, true);
Marshal.Copy(ptr, result, offset, sizePerItem); Marshal.Copy(ptr, setData, parameterOffsets[indexOfParameter] + offset, sizePerItem);
offset += sizePerItem; offset += sizePerItem;
} }
Marshal.FreeHGlobal(ptr); Marshal.FreeHGlobal(ptr);
setData[indexOfParameter] = result;
} }
#endregion #endregion
@ -76,12 +86,8 @@ namespace ANX.RenderSystem.Windows.Metro.Shader
value = FillArrayIfNeeded(value, indexOfParameter); value = FillArrayIfNeeded(value, indexOfParameter);
byte[] convertData = null; byte[] result = UnionArraySerializer.Unify(value);
byte[] result = UnionArraySerializer.Unify(value); Array.Copy(result, 0, setData, parameterOffsets[indexOfParameter], result.Length);
convertData = new byte[result.Length];
Array.Copy(result, convertData, result.Length);
setData[indexOfParameter] = convertData;
} }
#endregion #endregion
@ -94,12 +100,8 @@ namespace ANX.RenderSystem.Windows.Metro.Shader
value = FillArrayIfNeeded(value, indexOfParameter); value = FillArrayIfNeeded(value, indexOfParameter);
byte[] convertData = null; byte[] result = UnionArraySerializer.Unify(value);
byte[] result = UnionArraySerializer.Unify(value); Array.Copy(result, 0, setData, parameterOffsets[indexOfParameter], result.Length);
convertData = new byte[result.Length];
Array.Copy(result, convertData, result.Length);
setData[indexOfParameter] = convertData;
} }
#endregion #endregion
@ -110,7 +112,7 @@ namespace ANX.RenderSystem.Windows.Metro.Shader
if (indexOfParameter == -1) if (indexOfParameter == -1)
return; return;
setData[indexOfParameter] = value; Array.Copy(value, 0, setData, parameterOffsets[indexOfParameter], value.Length);
} }
#endregion #endregion
@ -178,41 +180,17 @@ namespace ANX.RenderSystem.Windows.Metro.Shader
#region CreateBufferData #region CreateBufferData
private SharpDX.DataBox CreateBufferData() private SharpDX.DataBox CreateBufferData()
{ {
MemoryStream stream = new MemoryStream();
BinaryWriter writer = new BinaryWriter(stream);
for(int index = 0; index < setData.Length; index++)
{
byte[] data = (byte[])setData[index];
if (data != null)
{
writer.Write(data);
}
else
{
var parameter = parentEffect.shader.Parameters[index];
if (parameter.IsTexture)
continue;
writer.Write(new byte[parameter.SizeInBytes]);
}
}
byte[] streamBytes = stream.ToArray();
stream.Dispose();
IntPtr dataPtr; IntPtr dataPtr;
unsafe unsafe
{ {
fixed (byte* ptr = &streamBytes[0]) fixed (byte* ptr = &setData[0])
{ {
dataPtr = (IntPtr)ptr; dataPtr = (IntPtr)ptr;
} }
} }
dataSize = streamBytes.Length; // Reset really needed? evaluate
setData = new byte[dataSize];
setData = new Array[parentEffect.shader.Parameters.Count];
return new SharpDX.DataBox(dataPtr); return new SharpDX.DataBox(dataPtr);
} }
#endregion #endregion