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.NonXNA;
using Dx11 = SharpDX.Direct3D11;
using ANX.RenderSystem.Windows.Metro.Shader;
using Dx11 = SharpDX.Direct3D11;
// This file is part of the ANX.Framework created by the
// "ANX.Framework developer group" and released under the Ms-PL license.
@ -31,34 +30,6 @@ namespace ANX.RenderSystem.Windows.Metro
get;
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
#region Constructor
@ -72,10 +43,25 @@ namespace ANX.RenderSystem.Windows.Metro
}
#endregion
public Dx11.InputLayout BuildLayout(Dx11.Device d3dDevice,
Dx11.InputElement[] elements)
#region BuildLayout
public Dx11.InputLayout BuildLayout(Dx11.Device d3dDevice, Dx11.InputElement[] 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 ANX.Framework.Graphics;
using ANX.Framework.NonXNA;
using Dx11 = SharpDX.Direct3D11;
using ANX.RenderSystem.Windows.Metro.Shader;
// 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
{
#region Private
private Effect parentEffect;
private List<EffectPass_Metro> passes;
private EffectPass_Metro[] passes;
#endregion
#region Public
@ -24,6 +22,14 @@ namespace ANX.RenderSystem.Windows.Metro
private set;
}
public int PassCount
{
get
{
return passes.Length;
}
}
public IEnumerable<EffectPass> Passes
{
get
@ -34,33 +40,28 @@ namespace ANX.RenderSystem.Windows.Metro
}
}
}
public EffectPass_Metro this[int index]
{
get
{
return passes[index];
}
}
#endregion
#region Constructor
public EffectTechnique_Metro(string setName, Effect setParentEffect,
public EffectTechnique_Metro(string setName, Effect parentEffect,
ExtendedShaderPass[] nativePasses)
{
Name = setName;
parentEffect = setParentEffect;
ParsePasses(nativePasses);
Name = setName;
passes = new EffectPass_Metro[nativePasses.Length];
for (int index = 0; index < nativePasses.Length; index++)
{
passes[index] = new EffectPass_Metro(parentEffect, nativePasses[index]);
}
}
#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>();
foreach (string key in shader.Techniques.Keys)
foreach (string key in shader.TechniqueNames)
{
var nativeTechnique = new EffectTechnique_Metro(key, ManagedEffect,
shader.Techniques[key]);
var nativeTechnique = new EffectTechnique_Metro(key, ManagedEffect, shader[key]);
techniques.Add(new EffectTechnique(ManagedEffect, nativeTechnique));
}
}
@ -131,7 +130,9 @@ namespace ANX.RenderSystem.Windows.Metro
#region Apply
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();
}
#endregion

View File

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

View File

@ -9,21 +9,47 @@ using System.IO;
namespace ANX.RenderSystem.Windows.Metro.Shader
{
public class ExtendedShader
{
public Dictionary<string, ExtendedShaderPass[]> Techniques;
public List<ExtendedShaderParameter> Parameters;
{
#region Private
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[]>();
Parameters = new List<ExtendedShaderParameter>();
techniques = new Dictionary<string, ExtendedShaderPass[]>();
BinaryReader reader = new BinaryReader(stream);
int numberOfVariables = reader.ReadInt32();
Parameters = new ExtendedShaderParameter[numberOfVariables];
for (int index = 0; index < numberOfVariables; index++)
{
Parameters.Add(new ExtendedShaderParameter(reader));
Parameters[index] = new ExtendedShaderParameter(reader);
}
int numberOfStructures = reader.ReadInt32();
@ -45,13 +71,14 @@ namespace ANX.RenderSystem.Windows.Metro.Shader
string name = reader.ReadString();
int numberOfPasses = reader.ReadInt32();
ExtendedShaderPass[] passes = new ExtendedShaderPass[numberOfPasses];
Techniques.Add(name, passes);
techniques.Add(name, passes);
for (int passIndex = 0; passIndex < numberOfPasses; passIndex++)
{
passes[passIndex] = new ExtendedShaderPass(reader);
}
}
}
}
#endregion
}
}

View File

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

View File

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