From 947287b0ab659f9925265666f03cd06766835ad4 Mon Sep 17 00:00:00 2001 From: "SND\\AstrorEnales_cp" Date: Sun, 19 Aug 2012 21:01:29 +0000 Subject: [PATCH] Refactored a lot of the rendering in the metro system and improved the memory usage of the ParameterBuffer --- .../EffectPass_Metro.cs | 52 +++++-------- .../EffectTechnique_Metro.cs | 49 ++++++------ .../Effect_Metro.cs | 9 ++- .../GraphicsDeviceWindowsMetro.cs | 67 +++++++--------- .../Shader/ExtendedShader.cs | 45 ++++++++--- .../Shader/ExtendedShaderParameter.cs | 4 +- .../Shader/ParameterBuffer.cs | 76 +++++++------------ 7 files changed, 144 insertions(+), 158 deletions(-) diff --git a/RenderSystems/ANX.RenderSystem.Windows.Metro/EffectPass_Metro.cs b/RenderSystems/ANX.RenderSystem.Windows.Metro/EffectPass_Metro.cs index 0cba2d40..28f73ee4 100644 --- a/RenderSystems/ANX.RenderSystem.Windows.Metro/EffectPass_Metro.cs +++ b/RenderSystems/ANX.RenderSystem.Windows.Metro/EffectPass_Metro.cs @@ -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 } } diff --git a/RenderSystems/ANX.RenderSystem.Windows.Metro/EffectTechnique_Metro.cs b/RenderSystems/ANX.RenderSystem.Windows.Metro/EffectTechnique_Metro.cs index 01d92a71..81c4e6cd 100644 --- a/RenderSystems/ANX.RenderSystem.Windows.Metro/EffectTechnique_Metro.cs +++ b/RenderSystems/ANX.RenderSystem.Windows.Metro/EffectTechnique_Metro.cs @@ -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 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 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(); - - foreach (ExtendedShaderPass pass in nativePasses) - { - passes.Add(new EffectPass_Metro(parentEffect, pass)); - } - } - #endregion - - public EffectPass_Metro GetPass(int index) - { - return passes[index]; - } } } diff --git a/RenderSystems/ANX.RenderSystem.Windows.Metro/Effect_Metro.cs b/RenderSystems/ANX.RenderSystem.Windows.Metro/Effect_Metro.cs index b06d953a..a8726b48 100644 --- a/RenderSystems/ANX.RenderSystem.Windows.Metro/Effect_Metro.cs +++ b/RenderSystems/ANX.RenderSystem.Windows.Metro/Effect_Metro.cs @@ -87,10 +87,9 @@ namespace ANX.RenderSystem.Windows.Metro { techniques = new List(); - 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 diff --git a/RenderSystems/ANX.RenderSystem.Windows.Metro/GraphicsDeviceWindowsMetro.cs b/RenderSystems/ANX.RenderSystem.Windows.Metro/GraphicsDeviceWindowsMetro.cs index a5c15bff..0fb24911 100644 --- a/RenderSystems/ANX.RenderSystem.Windows.Metro/GraphicsDeviceWindowsMetro.cs +++ b/RenderSystems/ANX.RenderSystem.Windows.Metro/GraphicsDeviceWindowsMetro.cs @@ -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 + + #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); } diff --git a/RenderSystems/ANX.RenderSystem.Windows.Metro/Shader/ExtendedShader.cs b/RenderSystems/ANX.RenderSystem.Windows.Metro/Shader/ExtendedShader.cs index 1bc26d51..3db531a9 100644 --- a/RenderSystems/ANX.RenderSystem.Windows.Metro/Shader/ExtendedShader.cs +++ b/RenderSystems/ANX.RenderSystem.Windows.Metro/Shader/ExtendedShader.cs @@ -9,21 +9,47 @@ using System.IO; namespace ANX.RenderSystem.Windows.Metro.Shader { public class ExtendedShader - { - public Dictionary Techniques; - public List Parameters; + { + #region Private + private Dictionary techniques; + #endregion - public ExtendedShader(Stream stream) + #region Public + public ExtendedShaderPass[] this[string name] + { + get + { + return techniques[name]; + } + } + + public string[] TechniqueNames + { + get + { + return new List(techniques.Keys).ToArray(); + } + } + + public ExtendedShaderParameter[] Parameters + { + get; + private set; + } + #endregion + + #region Constructor + public ExtendedShader(Stream stream) { - Techniques = new Dictionary(); - Parameters = new List(); + techniques = new Dictionary(); 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 } } diff --git a/RenderSystems/ANX.RenderSystem.Windows.Metro/Shader/ExtendedShaderParameter.cs b/RenderSystems/ANX.RenderSystem.Windows.Metro/Shader/ExtendedShaderParameter.cs index bee6809c..fc518d5e 100644 --- a/RenderSystems/ANX.RenderSystem.Windows.Metro/Shader/ExtendedShaderParameter.cs +++ b/RenderSystems/ANX.RenderSystem.Windows.Metro/Shader/ExtendedShaderParameter.cs @@ -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]; diff --git a/RenderSystems/ANX.RenderSystem.Windows.Metro/Shader/ParameterBuffer.cs b/RenderSystems/ANX.RenderSystem.Windows.Metro/Shader/ParameterBuffer.cs index 4a750655..dbb17c35 100644 --- a/RenderSystems/ANX.RenderSystem.Windows.Metro/Shader/ParameterBuffer.cs +++ b/RenderSystems/ANX.RenderSystem.Windows.Metro/Shader/ParameterBuffer.cs @@ -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(); + 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