diff --git a/ANX.Framework/Content/GraphicTypeReaders/Texture2DReader.cs b/ANX.Framework/Content/GraphicTypeReaders/Texture2DReader.cs index 77dedce8..f72174ea 100644 --- a/ANX.Framework/Content/GraphicTypeReaders/Texture2DReader.cs +++ b/ANX.Framework/Content/GraphicTypeReaders/Texture2DReader.cs @@ -1,11 +1,7 @@ -#region Using Statements -using System; -using System.Collections.Generic; +using System; using ANX.Framework.Graphics; using ANX.Framework.NonXNA; -#endregion // Using Statements - // This file is part of the ANX.Framework created by the // "ANX.Framework developer group" and released under the Ms-PL license. // For details see: http://anxframework.codeplex.com/license @@ -16,33 +12,26 @@ namespace ANX.Framework.Content { protected internal override Texture2D Read(ContentReader input, Texture2D existingInstance) { - IServiceProvider service = input.ContentManager.ServiceProvider; + //IServiceProvider service = input.ContentManager.ServiceProvider; + //var renderSystem = service.GetService(typeof(IRenderSystemCreator)) as IRenderSystemCreator; + //if (renderSystem == null) + // throw new ContentLoadException("Service not found IRenderSystemCreator"); - var rfc = service.GetService(typeof(IRenderSystemCreator)) as IRenderSystemCreator; - if (rfc == null) - { - throw new ContentLoadException("Service not found IRenderFrameworkCreator"); - } + //GraphicsDevice graphics = input.ResolveGraphicsDevice(); - GraphicsDevice graphics = input.ResolveGraphicsDevice(); - int surfaceFormat = input.ReadInt32(); + SurfaceFormat surfaceFormat = (SurfaceFormat)input.ReadInt32(); int width = input.ReadInt32(); int height = input.ReadInt32(); int mipCount = input.ReadInt32(); - SurfaceFormat sFormat = (SurfaceFormat)surfaceFormat; - List colorData = new List(); - - for (int i = 0; i < mipCount; i++) - { + var texture2D = new Texture2D(input.ResolveGraphicsDevice(), width, height, mipCount, surfaceFormat); + for (int level = 0; level < mipCount; level++) + { int size = input.ReadInt32(); - colorData.AddRange(input.ReadBytes(size)); - } - - Texture2D texture = new Texture2D(graphics, width, height, mipCount > 0, sFormat); - texture.SetData(colorData.ToArray()); - - return texture; + byte[] data = input.ReadBytes(size); + texture2D.SetData(level, null, data, 0, size); + } + return texture2D; } } } diff --git a/ANX.Framework/Graphics/Texture2D.cs b/ANX.Framework/Graphics/Texture2D.cs index 7f7764ad..57509efc 100644 --- a/ANX.Framework/Graphics/Texture2D.cs +++ b/ANX.Framework/Graphics/Texture2D.cs @@ -73,14 +73,26 @@ namespace ANX.Framework.Graphics CreateNativeTextureSurface(); } - public Texture2D(GraphicsDevice graphicsDevice, int width, int height, - [MarshalAsAttribute(UnmanagedType.U1)] bool mipMap, SurfaceFormat format) + public Texture2D(GraphicsDevice graphicsDevice, int width, int height, [MarshalAsAttribute(UnmanagedType.U1)] bool mipMap, + SurfaceFormat format) + : base(graphicsDevice) + { + this.width = width; + this.height = height; + // TODO: pass the mipmap parameter to the creation of the texture to let the graphics card generate mipmaps! + base.levelCount = 1; + base.format = format; + + CreateNativeTextureSurface(); + } + + internal Texture2D(GraphicsDevice graphicsDevice, int width, int height, int mipCount, SurfaceFormat format) : base(graphicsDevice) { this.width = width; this.height = height; - base.levelCount = 1; //TODO: mipmap paramter?!?!? + base.levelCount = mipCount; base.format = format; CreateNativeTextureSurface(); diff --git a/ANX.Framework/NonXNA/Reflection/AssemblyLoader.cs b/ANX.Framework/NonXNA/Reflection/AssemblyLoader.cs index fe91ab08..2ba28449 100644 --- a/ANX.Framework/NonXNA/Reflection/AssemblyLoader.cs +++ b/ANX.Framework/NonXNA/Reflection/AssemblyLoader.cs @@ -31,6 +31,8 @@ namespace ANX.Framework.NonXNA.Reflection "System.Xml.Linq.dll", "mscorlib.dll", "Sce.PlayStation.Core.dll", + "wrap_oal.dll", + "OpenAL32.dll", }; #endregion @@ -70,9 +72,12 @@ namespace ANX.Framework.NonXNA.Reflection LoadAssembliesFromFile(); LoadAssembliesFromNames(); -#if !WINDOWSMETRO // TODO: find way for metro // Also load the current assembly. This is needed when we run on android or win8 with merged assemblies. +#if !WINDOWSMETRO allAssemblies.Add(Assembly.GetEntryAssembly()); +#else + // TODO: a lot of testing is required! + allAssemblies.Add(typeof(AssemblyLoader).GetTypeInfo().Assembly); #endif } #endregion @@ -93,7 +98,7 @@ namespace ANX.Framework.NonXNA.Reflection bool ignore = false; foreach (string ignoreName in IgnoreAssemblies) { - if (file.EndsWith(ignoreName)) + if (file.EndsWith(ignoreName, StringComparison.InvariantCultureIgnoreCase)) { ignore = true; break; @@ -161,9 +166,7 @@ namespace ANX.Framework.NonXNA.Reflection private static void SearchForValidAddInTypes() { foreach (Assembly assembly in allAssemblies) - { SearchForValidAddInTypesInAssembly(assembly); - } } #endregion diff --git a/PlatformSystems/ANX.PlatformSystem.Metro/MetroGameTimer.cs b/PlatformSystems/ANX.PlatformSystem.Metro/MetroGameTimer.cs index 99e39a42..3a1ceaa9 100644 --- a/PlatformSystems/ANX.PlatformSystem.Metro/MetroGameTimer.cs +++ b/PlatformSystems/ANX.PlatformSystem.Metro/MetroGameTimer.cs @@ -1,6 +1,7 @@ #region Using Statements using System; using System.Diagnostics; +using ANX.Framework.NonXNA; using ANX.Framework.NonXNA.PlatformSystem; #endregion diff --git a/RenderSystems/ANX.BaseDirectX/BaseFormatConverter.cs b/RenderSystems/ANX.BaseDirectX/BaseFormatConverter.cs index 7380db6f..c673f5da 100644 --- a/RenderSystems/ANX.BaseDirectX/BaseFormatConverter.cs +++ b/RenderSystems/ANX.BaseDirectX/BaseFormatConverter.cs @@ -54,7 +54,7 @@ namespace ANX.BaseDirectX return SharpDX.DXGI.Format.BC3_UNorm; } - throw new Exception("can't translate SurfaceFormat: " + surfaceFormat.ToString()); + throw new Exception("Can't translate SurfaceFormat: " + surfaceFormat); } #endregion diff --git a/RenderSystems/ANX.BaseDirectX/BaseTexture2D.cs b/RenderSystems/ANX.BaseDirectX/BaseTexture2D.cs index 6f8379a8..1af04efc 100644 --- a/RenderSystems/ANX.BaseDirectX/BaseTexture2D.cs +++ b/RenderSystems/ANX.BaseDirectX/BaseTexture2D.cs @@ -12,19 +12,13 @@ namespace ANX.BaseDirectX public abstract class BaseTexture2D : IDisposable where S : class, IDisposable { #region Private + protected int mipCount; protected int tempSubresource; protected int pitch; - protected int formatSize; + private int formatSize; protected SurfaceFormat surfaceFormat; - - protected bool IsDxtTexture - { - get - { - return surfaceFormat == SurfaceFormat.Dxt5 || surfaceFormat == SurfaceFormat.Dxt3 || - surfaceFormat == SurfaceFormat.Dxt1; - } - } + protected bool useRenderTexture; + protected S NativeTextureStaging; #endregion #region Public @@ -45,13 +39,10 @@ namespace ANX.BaseDirectX #endregion #region Constructor - protected BaseTexture2D(GraphicsDevice graphicsDevice) - { - GraphicsDevice = graphicsDevice; - } - - protected BaseTexture2D(GraphicsDevice graphicsDevice, SurfaceFormat setSurfaceFormat) + protected BaseTexture2D(GraphicsDevice graphicsDevice, SurfaceFormat setSurfaceFormat, int setMipCount) { + mipCount = setMipCount; + useRenderTexture = mipCount > 1; GraphicsDevice = graphicsDevice; surfaceFormat = setSurfaceFormat; @@ -78,94 +69,135 @@ namespace ANX.BaseDirectX //TODO: handle offsetInBytes parameter //TODO: handle startIndex parameter //TODO: handle elementCount parameter - - if (surfaceFormat == SurfaceFormat.Color) + + unsafe { - IntPtr dataPtr = MapWrite(); + GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned); + byte* colorData = (byte*)handle.AddrOfPinnedObject(); - unsafe + switch (surfaceFormat) { - GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned); - byte* colorData = (byte*)handle.AddrOfPinnedObject(); + case SurfaceFormat.Color: + SetDataColor(0, offsetInBytes, colorData, startIndex, elementCount); + return; - byte* pTexels = (byte*)dataPtr; - int srcIndex = 0; - - for (int row = 0; row < Height; row++) - { - int rowStart = row * pitch; - - for (int col = 0; col < Width; col++) - { - int colStart = col * formatSize; - pTexels[rowStart + colStart + 0] = colorData[srcIndex++]; - pTexels[rowStart + colStart + 1] = colorData[srcIndex++]; - pTexels[rowStart + colStart + 2] = colorData[srcIndex++]; - pTexels[rowStart + colStart + 3] = colorData[srcIndex++]; - } - } - - handle.Free(); + case SurfaceFormat.Dxt1: + case SurfaceFormat.Dxt3: + case SurfaceFormat.Dxt5: + SetDataDxt(0, offsetInBytes, colorData, startIndex, elementCount, data.Length); + return; } - Unmap(); + handle.Free(); } - else if (IsDxtTexture) + + throw new Exception(String.Format("creating textures of format {0} not yet implemented...", surfaceFormat)); + } + #endregion + + #region SetDataColor + private unsafe void SetDataColor(int level, int offsetInBytes, byte* colorData, int startIndex, int elementCount) + { + int mipmapWidth = Math.Max(Width >> level, 1); + int mipmapHeight = Math.Max(Height >> level, 1); + + IntPtr dataPtr = MapWrite(level); + int srcIndex = 0; + + byte* pTexels = (byte*)dataPtr; + for (int row = 0; row < mipmapHeight; row++) { - unsafe + int rowStart = row * pitch; + + for (int col = 0; col < mipmapWidth; col++) { - GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned); - byte* colorData = (byte*)handle.AddrOfPinnedObject(); - - int w = (Width + 3) >> 2; - int h = (Height + 3) >> 2; - formatSize = (surfaceFormat == SurfaceFormat.Dxt1) ? 8 : 16; - - IntPtr dataPtr = MapWrite(); - var ds = new DataStream(dataPtr, Width * Height * 4 * 2, true, true); - int col = 0; - int index = 0; // startIndex - int count = data.Length; // elementCount - int actWidth = w * formatSize; - - for (int i = 0; i < h; i++) - { - ds.Position = (i * pitch) + (col * formatSize); - if (count <= 0) - break; - else if (count < actWidth) - { - for (int idx = index; idx < index + count; idx++) - ds.WriteByte(colorData[idx]); - break; - } - - for (int idx = index; idx < index + actWidth; idx++) - ds.WriteByte(colorData[idx]); - - index += actWidth; - count -= actWidth; - } - - handle.Free(); - - Unmap(); + int colStart = rowStart + (col * formatSize); + pTexels[colStart++] = colorData[srcIndex++]; + pTexels[colStart++] = colorData[srcIndex++]; + pTexels[colStart++] = colorData[srcIndex++]; + pTexels[colStart++] = colorData[srcIndex++]; } } - else - throw new Exception(String.Format("creating textures of format {0} not yet implemented...", surfaceFormat)); + + Unmap(); + } + #endregion + + #region SetDataDxt + private unsafe void SetDataDxt(int level, int offsetInBytes, byte* colorData, int startIndex, int elementCount, + int dataLength) + { + int mipmapWidth = Math.Max(Width >> level, 1); + int mipmapHeight = Math.Max(Height >> level, 1); + + int w = (mipmapWidth + 3) >> 2; + int h = (mipmapHeight + 3) >> 2; + formatSize = (surfaceFormat == SurfaceFormat.Dxt1) ? 8 : 16; + + IntPtr dataPtr = MapWrite(level); + var ds = new DataStream(dataPtr, mipmapWidth * mipmapHeight * 4 * 2, true, true); + int col = 0; + int index = 0; // startIndex + int count = dataLength; // elementCount + int actWidth = w * formatSize; + + for (int i = 0; i < h; i++) + { + ds.Position = (i * pitch) + (col * formatSize); + if (count <= 0) + break; + else if (count < actWidth) + { + for (int idx = index; idx < index + count; idx++) + ds.WriteByte(colorData[idx]); + break; + } + + for (int idx = index; idx < index + actWidth; idx++) + ds.WriteByte(colorData[idx]); + + index += actWidth; + count -= actWidth; + } + + Unmap(); } #endregion #region SetData (TODO) public void SetData(int level, Framework.Rectangle? rect, T[] data, int startIndex, int elementCount) where T : struct { - throw new NotImplementedException(); + //TODO: handle rect parameter + if (rect != null) + throw new Exception("Texture2D SetData with rectangle is not yet implemented!"); + + unsafe + { + GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned); + byte* colorData = (byte*)handle.AddrOfPinnedObject(); + + switch (surfaceFormat) + { + case SurfaceFormat.Color: + SetDataColor(level, 0, colorData, startIndex, elementCount); + return; + + case SurfaceFormat.Dxt1: + case SurfaceFormat.Dxt3: + case SurfaceFormat.Dxt5: + SetDataDxt(level, 0, colorData, startIndex, elementCount, data.Length); + return; + } + + handle.Free(); + } + + throw new Exception(String.Format("creating textures of format {0} not yet implemented...", surfaceFormat)); } #endregion - protected abstract IntPtr MapWrite(); - protected abstract IntPtr MapRead(); + protected abstract IntPtr MapWrite(int level); + protected abstract IntPtr MapRead(int level); protected abstract void Unmap(); #region Dispose diff --git a/RenderSystems/ANX.Framework.Windows.DX10/ANX.RenderSystem.Windows.DX10_WindowsMetro.csproj b/RenderSystems/ANX.Framework.Windows.DX10/ANX.RenderSystem.Windows.DX10_WindowsMetro.csproj index 0a33517e..5049d77b 100644 --- a/RenderSystems/ANX.Framework.Windows.DX10/ANX.RenderSystem.Windows.DX10_WindowsMetro.csproj +++ b/RenderSystems/ANX.Framework.Windows.DX10/ANX.RenderSystem.Windows.DX10_WindowsMetro.csproj @@ -103,7 +103,7 @@ {6899F0C9-70B9-4EB0-9DD3-E598D4BE3E35} ANX.Framework - + {A4D3AD34-E49C-4142-8620-2AFF44ED6719} ANX.BaseDirectX diff --git a/RenderSystems/ANX.Framework.Windows.DX10/GraphicsDeviceWindowsDX10.cs b/RenderSystems/ANX.Framework.Windows.DX10/GraphicsDeviceWindowsDX10.cs index 78fb0086..25b6b5b9 100644 --- a/RenderSystems/ANX.Framework.Windows.DX10/GraphicsDeviceWindowsDX10.cs +++ b/RenderSystems/ANX.Framework.Windows.DX10/GraphicsDeviceWindowsDX10.cs @@ -1,3 +1,4 @@ +#define DIRECTX_DEBUG_LAYER using System; using ANX.Framework; using ANX.Framework.Graphics; @@ -259,7 +260,10 @@ namespace ANX.RenderSystem.Windows.DX10 { technique.GetPassByIndex(i).Apply(); device.DrawIndexed(vertexCount, startIndex, baseVertex); - } + } + + device.InputAssembler.InputLayout.Dispose(); + device.InputAssembler.InputLayout = null; } #endregion @@ -277,6 +281,9 @@ namespace ANX.RenderSystem.Windows.DX10 technique.GetPassByIndex(i).Apply(); device.Draw(primitiveCount, vertexOffset); } + + device.InputAssembler.InputLayout.Dispose(); + device.InputAssembler.InputLayout = null; } #endregion @@ -345,6 +352,9 @@ namespace ANX.RenderSystem.Windows.DX10 pass.Apply(); device.Draw(primitiveCount, vertexOffset); } + + device.InputAssembler.InputLayout.Dispose(); + device.InputAssembler.InputLayout = null; } #endregion diff --git a/RenderSystems/ANX.Framework.Windows.DX10/Texture2D_DX10.cs b/RenderSystems/ANX.Framework.Windows.DX10/Texture2D_DX10.cs index 88284f0f..5d01f9a8 100644 --- a/RenderSystems/ANX.Framework.Windows.DX10/Texture2D_DX10.cs +++ b/RenderSystems/ANX.Framework.Windows.DX10/Texture2D_DX10.cs @@ -36,17 +36,32 @@ namespace ANX.RenderSystem.Windows.DX10 #region Constructor internal Texture2D_DX10(GraphicsDevice graphicsDevice, SurfaceFormat surfaceFormat) - : base(graphicsDevice, surfaceFormat) + : base(graphicsDevice, surfaceFormat, 1) { } public Texture2D_DX10(GraphicsDevice graphicsDevice, int width, int height, SurfaceFormat surfaceFormat, int mipCount) - : base(graphicsDevice, surfaceFormat) + : base(graphicsDevice, surfaceFormat, mipCount) { - if (mipCount > 1) - throw new Exception("creating textures with mip map not yet implemented"); + Dx10.Device device = (graphicsDevice.NativeDevice as GraphicsDeviceWindowsDX10).NativeDevice; - Dx10.Texture2DDescription description = new Dx10.Texture2DDescription() + if (useRenderTexture) + { + var descriptionStaging = new Dx10.Texture2DDescription() + { + Width = width, + Height = height, + MipLevels = mipCount, + ArraySize = mipCount, + Format = BaseFormatConverter.Translate(surfaceFormat), + SampleDescription = new SharpDX.DXGI.SampleDescription(1, 0), + Usage = Dx10.ResourceUsage.Staging, + CpuAccessFlags = Dx10.CpuAccessFlags.Write, + }; + NativeTextureStaging = new Dx10.Texture2D(device, descriptionStaging); + } + + var description = new Dx10.Texture2DDescription() { Width = width, Height = height, @@ -54,13 +69,12 @@ namespace ANX.RenderSystem.Windows.DX10 ArraySize = mipCount, Format = BaseFormatConverter.Translate(surfaceFormat), SampleDescription = new SharpDX.DXGI.SampleDescription(1, 0), - Usage = Dx10.ResourceUsage.Dynamic, + Usage = useRenderTexture ? Dx10.ResourceUsage.Default : Dx10.ResourceUsage.Dynamic, BindFlags = Dx10.BindFlags.ShaderResource, - CpuAccessFlags = Dx10.CpuAccessFlags.Write, + CpuAccessFlags = useRenderTexture ? Dx10.CpuAccessFlags.None : Dx10.CpuAccessFlags.Write, OptionFlags = Dx10.ResourceOptionFlags.None, }; - Dx10.Device device = (graphicsDevice.NativeDevice as GraphicsDeviceWindowsDX10).NativeDevice; NativeTexture = new Dx10.Texture2D(device, description); NativeShaderResourceView = new Dx10.ShaderResourceView(device, NativeTexture); } @@ -89,14 +103,16 @@ namespace ANX.RenderSystem.Windows.DX10 #region SaveAsJpeg (TODO) public void SaveAsJpeg(Stream stream, int width, int height) { - throw new NotImplementedException(); + // TODO: handle width and height? + Dx10.Texture2D.ToStream(NativeTexture, Dx10.ImageFileFormat.Jpg, stream); } #endregion #region SaveAsPng (TODO) public void SaveAsPng(Stream stream, int width, int height) { - throw new NotImplementedException(); + // TODO: handle width and height? + Dx10.Texture2D.ToStream(NativeTexture, Dx10.ImageFileFormat.Png, stream); } #endregion @@ -118,20 +134,23 @@ namespace ANX.RenderSystem.Windows.DX10 #endregion #region MapWrite - protected override IntPtr MapWrite() + protected override IntPtr MapWrite(int level) { - tempSubresource = Dx10.Texture2D.CalculateSubResourceIndex(0, 0, 1); - DataRectangle rect = NativeTexture.Map(tempSubresource, Dx10.MapMode.WriteDiscard, Dx10.MapFlags.None); + tempSubresource = Dx10.Texture2D.CalculateSubResourceIndex(level, 0, mipCount); + var texture = useRenderTexture ? NativeTextureStaging : NativeTexture; + DataRectangle rect = texture.Map(tempSubresource, useRenderTexture ? Dx10.MapMode.Write : Dx10.MapMode.WriteDiscard, + Dx10.MapFlags.None); pitch = rect.Pitch; return rect.DataPointer; } #endregion #region MapRead - protected override IntPtr MapRead() + protected override IntPtr MapRead(int level) { - tempSubresource = Dx10.Texture2D.CalculateSubResourceIndex(0, 0, 1); - DataRectangle rect = NativeTexture.Map(tempSubresource, Dx10.MapMode.Read, Dx10.MapFlags.None); + tempSubresource = Dx10.Texture2D.CalculateSubResourceIndex(level, 0, mipCount); + var texture = useRenderTexture ? NativeTextureStaging : NativeTexture; + DataRectangle rect = texture.Map(tempSubresource, Dx10.MapMode.Read, Dx10.MapFlags.None); pitch = rect.Pitch; return rect.DataPointer; } @@ -140,7 +159,10 @@ namespace ANX.RenderSystem.Windows.DX10 #region Unmap protected override void Unmap() { - NativeTexture.Unmap(tempSubresource); + var texture = useRenderTexture ? NativeTextureStaging : NativeTexture; + texture.Unmap(tempSubresource); + if (useRenderTexture) + texture.Device.CopyResource(NativeTextureStaging, NativeTexture); } #endregion } diff --git a/RenderSystems/ANX.Framework.Windows.GL3/Texture2DGL3.cs b/RenderSystems/ANX.Framework.Windows.GL3/Texture2DGL3.cs index f381e48e..ffd5e01c 100644 --- a/RenderSystems/ANX.Framework.Windows.GL3/Texture2DGL3.cs +++ b/RenderSystems/ANX.Framework.Windows.GL3/Texture2DGL3.cs @@ -1,11 +1,11 @@ using System; using System.IO; using System.Runtime.InteropServices; +using ANX.Framework; using ANX.Framework.Graphics; using ANX.Framework.NonXNA.RenderSystem; -using OpenTK.Graphics.OpenGL; -using ANX.Framework; using ANX.RenderSystem.Windows.GL3.Helpers; +using OpenTK.Graphics.OpenGL; // This file is part of the ANX.Framework created by the // "ANX.Framework developer group" and released under the Ms-PL license. @@ -13,58 +13,27 @@ using ANX.RenderSystem.Windows.GL3.Helpers; namespace ANX.RenderSystem.Windows.GL3 { - /// - /// Native OpenGL Texture implementation. - /// public class Texture2DGL3 : INativeTexture2D { #region Private - /// - /// The native OpenGL pixel format of the texture. - /// private PixelInternalFormat nativeFormat; /// - /// The number of mipmaps used by this texture [1-n]. + /// [1-n] /// private int numberOfMipMaps; - /// - /// Width of the texture. - /// private int width; - - /// - /// Height of the texture. - /// private int height; - - /// - /// Flag if the texture is a compressed format or not. - /// private bool isCompressed; - internal bool IsDisposed; - private int uncompressedDataSize; - private byte[] texData; - - /// - /// TODO: find better solution - /// private int maxSetDataSize; #endregion #region Public - /// - /// The OpenGL texture handle. - /// - protected internal int NativeHandle - { - get; - protected set; - } + protected internal int NativeHandle { get; protected set; } #endregion #region Constructor @@ -73,15 +42,7 @@ namespace ANX.RenderSystem.Windows.GL3 GraphicsResourceManager.UpdateResource(this, true); } - /// - /// Create a new native OpenGL texture. - /// - /// Surface format of the texture. - /// Width of the first mip level. - /// Height of the first mip level. - /// Number of mip levels [1-n]. - internal Texture2DGL3(SurfaceFormat surfaceFormat, int setWidth, - int setHeight, int mipCount) + internal Texture2DGL3(SurfaceFormat surfaceFormat, int setWidth, int setHeight, int mipCount) { GraphicsResourceManager.UpdateResource(this, true); @@ -106,27 +67,15 @@ namespace ANX.RenderSystem.Windows.GL3 private void CreateTexture() { NativeHandle = GL.GenTexture(); -#if DEBUG - ErrorHelper.Check("GenTexture"); -#endif GL.BindTexture(TextureTarget.Texture2D, NativeHandle); -#if DEBUG - ErrorHelper.Check("BindTexture"); -#endif int wrapMode = (int)All.ClampToEdge; - int filter = (int)(numberOfMipMaps > 1 ? - All.LinearMipmapLinear : - All.Linear); + All minFilter = numberOfMipMaps > 1 ? All.LinearMipmapLinear : All.Linear; - GL.TexParameter(TextureTarget.Texture2D, - TextureParameterName.TextureWrapS, wrapMode); - GL.TexParameter(TextureTarget.Texture2D, - TextureParameterName.TextureWrapT, wrapMode); - GL.TexParameter(TextureTarget.Texture2D, - TextureParameterName.TextureMagFilter, filter); - GL.TexParameter(TextureTarget.Texture2D, - TextureParameterName.TextureMinFilter, filter); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, wrapMode); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, wrapMode); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)All.Linear); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)minFilter); #if DEBUG ErrorHelper.Check("TexParameter"); #endif @@ -135,102 +84,87 @@ namespace ANX.RenderSystem.Windows.GL3 // TODO: offsetInBytes // TODO: elementCount - // TODO: get size of first mipmap! #region SetData - public void SetData(GraphicsDevice graphicsDevice, T[] data) - where T : struct + public void SetData(GraphicsDevice graphicsDevice, T[] data) where T : struct { SetData(graphicsDevice, 0, data, 0, data.Length); } - public void SetData(GraphicsDevice graphicsDevice, T[] data, - int startIndex, int elementCount) where T : struct + public void SetData(GraphicsDevice graphicsDevice, T[] data, int startIndex, int elementCount) where T : struct { SetData(graphicsDevice, 0, data, 0, data.Length); } - public void SetData(int level, Rectangle? rect, T[] data, int startIndex, - int elementCount) where T : struct + public void SetData(int level, Rectangle? rect, T[] data, int startIndex, int elementCount) where T : struct { - throw new NotImplementedException(); - } - - public void SetData(GraphicsDevice graphicsDevice, int offsetInBytes, - T[] data, int startIndex, int elementCount) where T : struct - { - if (numberOfMipMaps > 1) - { - throw new NotImplementedException( - "Loading mipmaps is not correctly implemented yet!"); - } + int size = Marshal.SizeOf(typeof(T)) * data.Length; + if (size > maxSetDataSize) + maxSetDataSize = size; GL.BindTexture(TextureTarget.Texture2D, NativeHandle); -#if DEBUG - ErrorHelper.Check("BindTexture"); -#endif - - if (data.Length > maxSetDataSize) - { - maxSetDataSize = data.Length; - } - GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned); - - // TODO: get size of first mipmap! - int mipmapByteSize = data.Length; - + try { IntPtr dataPointer = handle.AddrOfPinnedObject(); // Go to the starting point. dataPointer += startIndex; + int mipmapWidth = Math.Max(width >> level, 1); + int mipmapHeight = Math.Max(height >> level, 1); + if (isCompressed) { - GL.CompressedTexImage2D(TextureTarget.Texture2D, 0, nativeFormat, - width, height, 0, mipmapByteSize, dataPointer); + GL.CompressedTexImage2D(TextureTarget.Texture2D, level, nativeFormat, width, height, 0, data.Length, + dataPointer); #if DEBUG ErrorHelper.Check("CompressedTexImage2D Format=" + nativeFormat); #endif } else { - GL.TexImage2D(TextureTarget.Texture2D, 0, nativeFormat, - width, height, 0, (PixelFormat)nativeFormat, - PixelType.UnsignedByte, dataPointer); + GL.TexImage2D(TextureTarget.Texture2D, level, nativeFormat, mipmapWidth, mipmapHeight, 0, + (PixelFormat)nativeFormat, PixelType.UnsignedByte, dataPointer); #if DEBUG ErrorHelper.Check("TexImage2D Format=" + nativeFormat); #endif } + } + finally + { + handle.Free(); + } + } - int mipmapWidth = width; - int mipmapHeight = height; - for (int index = 1; index < numberOfMipMaps; index++) + public void SetData(GraphicsDevice graphicsDevice, int offsetInBytes, T[] data, int startIndex, int elementCount) + where T : struct + { + int size = Marshal.SizeOf(typeof(T)) * data.Length; + if (size > maxSetDataSize) + maxSetDataSize = size; + + GL.BindTexture(TextureTarget.Texture2D, NativeHandle); + GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned); + + try + { + IntPtr dataPointer = handle.AddrOfPinnedObject(); + dataPointer += startIndex; + + if (isCompressed) { - dataPointer += mipmapByteSize; - mipmapByteSize /= 4; - mipmapWidth /= 2; - mipmapHeight /= 2; - mipmapWidth = Math.Max(mipmapWidth, 1); - mipmapHeight = Math.Max(mipmapHeight, 1); - - if (isCompressed) - { - GL.CompressedTexImage2D(TextureTarget.Texture2D, index, - nativeFormat, width, height, 0, mipmapByteSize, dataPointer); + GL.CompressedTexImage2D(TextureTarget.Texture2D, 0, nativeFormat, width, height, 0, data.Length, dataPointer); #if DEBUG - ErrorHelper.Check("CompressedTexImage2D Format=" + nativeFormat); + ErrorHelper.Check("CompressedTexImage2D Format=" + nativeFormat); #endif - } - else - { - GL.TexImage2D(TextureTarget.Texture2D, index, nativeFormat, - mipmapWidth, mipmapHeight, 0, (PixelFormat)nativeFormat, - PixelType.UnsignedByte, dataPointer); + } + else + { + GL.TexImage2D(TextureTarget.Texture2D, 0, nativeFormat, width, height, 0, (PixelFormat)nativeFormat, + PixelType.UnsignedByte, dataPointer); #if DEBUG - ErrorHelper.Check("TexImage2D Format=" + nativeFormat); + ErrorHelper.Check("TexImage2D Format=" + nativeFormat); #endif - } } } finally @@ -240,81 +174,42 @@ namespace ANX.RenderSystem.Windows.GL3 } #endregion - // TODO: compressed texture, what about elementCount? #region GetData (TODO) - public void GetData(int level, Rectangle? rect, T[] data, int startIndex, - int elementCount) where T : struct + public void GetData(int level, Rectangle? rect, T[] data, int startIndex, int elementCount) where T : struct { throw new NotImplementedException(); } #endregion - // TODO: compressed texture (see: http://www.bearisgaming.com/texture2d-getdata-and-dxt-compression/) #region GetData public void GetData(T[] data) where T : struct { - if (isCompressed) - { - throw new NotImplementedException( - "GetData is currently not implemented for compressed texture " + - "formats! Format is " + nativeFormat + "."); - } - - if (data == null) - { - throw new ArgumentNullException("data"); - } - - int size = Marshal.SizeOf(typeof(T)) * data.Length; - - if (size != uncompressedDataSize) - { - throw new InvalidDataException( - "The size of the data passed in is too large or too small " + - "for this resource."); - } - - GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned); - - GL.GetTexImage(TextureTarget.Texture2D, 0, (PixelFormat)nativeFormat, - PixelType.UnsignedByte, handle.AddrOfPinnedObject()); - - handle.Free(); + GetData(data, 0, data.Length); } #endregion - // TODO: compressed texture, what about elementCount? + // TODO: compressed texture (see: http://www.bearisgaming.com/texture2d-getdata-and-dxt-compression/) + // TODO: elementCount #region GetData - public void GetData(T[] data, int startIndex, int elementCount) - where T : struct + public void GetData(T[] data, int startIndex, int elementCount) where T : struct { if (isCompressed) - { - throw new NotImplementedException( - "GetData is currently not implemented for compressed texture " + - "formats! Format is " + nativeFormat + "."); - } + throw new NotImplementedException("GetData is currently not implemented for compressed texture format " + + nativeFormat + "."); if (data == null) - { throw new ArgumentNullException("data"); - } int size = Marshal.SizeOf(typeof(T)) * data.Length; if (size < uncompressedDataSize) - { - throw new InvalidDataException( - "The size of the data passed in is too large or too small " + - "for this resource."); - } + throw new InvalidDataException("The size of the data passed in is too large or too small for this resource."); GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned); IntPtr ptr = handle.AddrOfPinnedObject(); ptr += startIndex; - GL.GetTexImage(TextureTarget.Texture2D, 0, (PixelFormat)nativeFormat, - PixelType.UnsignedByte, ptr); + GL.GetTexImage(TextureTarget.Texture2D, 0, (PixelFormat)nativeFormat, PixelType.UnsignedByte, ptr); handle.Free(); } @@ -330,8 +225,7 @@ namespace ANX.RenderSystem.Windows.GL3 texData = new byte[maxSetDataSize]; GCHandle handle = GCHandle.Alloc(texData, GCHandleType.Pinned); - GL.GetCompressedTexImage(TextureTarget.Texture2D, 0, - handle.AddrOfPinnedObject()); + GL.GetCompressedTexImage(TextureTarget.Texture2D, 0, handle.AddrOfPinnedObject()); handle.Free(); } @@ -340,8 +234,8 @@ namespace ANX.RenderSystem.Windows.GL3 texData = new byte[uncompressedDataSize]; GCHandle handle = GCHandle.Alloc(texData, GCHandleType.Pinned); - GL.GetTexImage(TextureTarget.Texture2D, 0, (PixelFormat)nativeFormat, - PixelType.UnsignedByte, handle.AddrOfPinnedObject()); + GL.GetTexImage(TextureTarget.Texture2D, 0, (PixelFormat)nativeFormat, PixelType.UnsignedByte, + handle.AddrOfPinnedObject()); handle.Free(); } diff --git a/RenderSystems/ANX.RenderSystem.Windows.DX11/ANX.RenderSystem.Windows.DX11_WindowsMetro.csproj b/RenderSystems/ANX.RenderSystem.Windows.DX11/ANX.RenderSystem.Windows.DX11_WindowsMetro.csproj index 91a5affb..2fec9e18 100644 --- a/RenderSystems/ANX.RenderSystem.Windows.DX11/ANX.RenderSystem.Windows.DX11_WindowsMetro.csproj +++ b/RenderSystems/ANX.RenderSystem.Windows.DX11/ANX.RenderSystem.Windows.DX11_WindowsMetro.csproj @@ -64,7 +64,7 @@ {6899F0C9-70B9-4EB0-9DD3-E598D4BE3E35} ANX.Framework - + {A4D3AD34-E49C-4142-8620-2AFF44ED6719} ANX.BaseDirectX diff --git a/RenderSystems/ANX.RenderSystem.Windows.DX11/GraphicsDeviceWindowsDX11.cs b/RenderSystems/ANX.RenderSystem.Windows.DX11/GraphicsDeviceWindowsDX11.cs index 20f78a1b..76766e9f 100644 --- a/RenderSystems/ANX.RenderSystem.Windows.DX11/GraphicsDeviceWindowsDX11.cs +++ b/RenderSystems/ANX.RenderSystem.Windows.DX11/GraphicsDeviceWindowsDX11.cs @@ -1,3 +1,4 @@ +#define DIRECTX_DEBUG_LAYER using System; using ANX.Framework; using ANX.Framework.Graphics; @@ -243,48 +244,54 @@ namespace ANX.RenderSystem.Windows.DX11 #endregion #region DrawPrimitives & DrawIndexedPrimitives - public void DrawIndexedPrimitives(PrimitiveType primitiveType, int baseVertex, int minVertexIndex, + public void DrawIndexedPrimitives(PrimitiveType primitiveType, int baseVertex, int minVertexIndex, int numVertices, int startIndex, int primitiveCount) - { - SharpDX.Direct3D11.EffectPass pass; - SharpDX.Direct3D11.EffectTechnique technique; - ShaderBytecode passSignature; - SetupEffectForDraw(out pass, out technique, out passSignature); + { + SharpDX.Direct3D11.EffectPass pass; + SharpDX.Direct3D11.EffectTechnique technique; + ShaderBytecode passSignature; + SetupEffectForDraw(out pass, out technique, out passSignature); - SetupInputLayout(passSignature); + var layout = SetupInputLayout(passSignature); - // Prepare All the stages + // Prepare All the stages deviceContext.InputAssembler.PrimitiveTopology = BaseFormatConverter.Translate(primitiveType); - deviceContext.Rasterizer.SetViewports(currentViewport); + deviceContext.Rasterizer.SetViewports(currentViewport); - deviceContext.OutputMerger.SetTargets(this.depthStencilView, this.renderView); + deviceContext.OutputMerger.SetTargets(this.depthStencilView, this.renderView); - for (int i = 0; i < technique.Description.PassCount; ++i) - { - pass.Apply(deviceContext); + for (int i = 0; i < technique.Description.PassCount; ++i) + { + pass.Apply(deviceContext); deviceContext.DrawIndexed(BaseFormatConverter.CalculateVertexCount(primitiveType, primitiveCount), startIndex, baseVertex); - } - } + } - public void DrawPrimitives(PrimitiveType primitiveType, int vertexOffset, int primitiveCount) - { - SharpDX.Direct3D11.EffectPass pass; SharpDX.Direct3D11.EffectTechnique technique; ShaderBytecode passSignature; - SetupEffectForDraw(out pass, out technique, out passSignature); + layout.Dispose(); + layout = null; + } - SetupInputLayout(passSignature); + public void DrawPrimitives(PrimitiveType primitiveType, int vertexOffset, int primitiveCount) + { + SharpDX.Direct3D11.EffectPass pass; SharpDX.Direct3D11.EffectTechnique technique; ShaderBytecode passSignature; + SetupEffectForDraw(out pass, out technique, out passSignature); - // Prepare All the stages + var layout = SetupInputLayout(passSignature); + + // Prepare All the stages deviceContext.InputAssembler.PrimitiveTopology = BaseFormatConverter.Translate(primitiveType); - deviceContext.Rasterizer.SetViewports(currentViewport); + deviceContext.Rasterizer.SetViewports(currentViewport); - deviceContext.OutputMerger.SetTargets(this.depthStencilView, this.renderView); + deviceContext.OutputMerger.SetTargets(this.depthStencilView, this.renderView); - for (int i = 0; i < technique.Description.PassCount; ++i) - { - pass.Apply(deviceContext); - deviceContext.Draw(primitiveCount, vertexOffset); - } - } + for (int i = 0; i < technique.Description.PassCount; ++i) + { + pass.Apply(deviceContext); + deviceContext.Draw(primitiveCount, vertexOffset); + } + + layout.Dispose(); + layout = null; + } #endregion // DrawPrimitives & DrawIndexedPrimitives @@ -297,26 +304,25 @@ namespace ANX.RenderSystem.Windows.DX11 #endregion // DrawInstancedPrimitives #region DrawUserIndexedPrimitives - public void DrawUserIndexedPrimitives(PrimitiveType primitiveType, T[] vertexData, int vertexOffset, int numVertices, Array indexData, int indexOffset, int primitiveCount, VertexDeclaration vertexDeclaration, IndexElementSize indexFormat) where T : struct, IVertexType + public void DrawUserIndexedPrimitives(PrimitiveType primitiveType, T[] vertexData, int vertexOffset, int numVertices, + Array indexData, int indexOffset, int primitiveCount, VertexDeclaration vertexDeclaration, + IndexElementSize indexFormat) where T : struct, IVertexType { int vertexCount = vertexData.Length; int indexCount = indexData.Length; - VertexBuffer_DX11 vb11 = new VertexBuffer_DX11(this.deviceContext.Device, vertexDeclaration, vertexCount, BufferUsage.None); + var vb11 = new VertexBuffer_DX11(this.deviceContext.Device, vertexDeclaration, vertexCount, BufferUsage.None); vb11.SetData(null, vertexData); - SharpDX.Direct3D11.VertexBufferBinding nativeVertexBufferBindings = new SharpDX.Direct3D11.VertexBufferBinding(vb11.NativeBuffer, vertexDeclaration.VertexStride, 0); + var nativeVertexBufferBindings = new SharpDX.Direct3D11.VertexBufferBinding(vb11.NativeBuffer, + vertexDeclaration.VertexStride, 0); deviceContext.InputAssembler.SetVertexBuffers(0, nativeVertexBufferBindings); IndexBuffer_DX11 idx10 = new IndexBuffer_DX11(this.deviceContext.Device, indexFormat, indexCount, BufferUsage.None); if (indexData.GetType() == typeof(Int16[])) - { idx10.SetData(null, (short[])indexData); - } else - { idx10.SetData(null, (int[])indexData); - } DrawIndexedPrimitives(primitiveType, 0, vertexOffset, numVertices, indexOffset, primitiveCount); } @@ -350,7 +356,10 @@ namespace ANX.RenderSystem.Windows.DX11 { pass.Apply(deviceContext); deviceContext.Draw(primitiveCount, vertexOffset); - } + } + + layout.Dispose(); + layout = null; } #endregion // DrawUserPrimitives @@ -369,7 +378,7 @@ namespace ANX.RenderSystem.Windows.DX11 passSignature = pass.Description.Signature; } - private void SetupInputLayout(ShaderBytecode passSignature) + private InputLayout SetupInputLayout(ShaderBytecode passSignature) { // get the VertexDeclaration from current VertexBuffer to create input layout for the input assembler //TODO: check for null and throw exception @@ -377,6 +386,7 @@ namespace ANX.RenderSystem.Windows.DX11 var layout = CreateInputLayout(deviceContext.Device, passSignature, vertexDeclaration); deviceContext.InputAssembler.InputLayout = layout; + return layout; } public void SetIndexBuffer(IndexBuffer indexBuffer) diff --git a/RenderSystems/ANX.RenderSystem.Windows.DX11/Texture2D_DX11.cs b/RenderSystems/ANX.RenderSystem.Windows.DX11/Texture2D_DX11.cs index e400b9aa..589ede63 100644 --- a/RenderSystems/ANX.RenderSystem.Windows.DX11/Texture2D_DX11.cs +++ b/RenderSystems/ANX.RenderSystem.Windows.DX11/Texture2D_DX11.cs @@ -36,16 +36,32 @@ namespace ANX.RenderSystem.Windows.DX11 #region Constructor internal Texture2D_DX11(GraphicsDevice graphicsDevice, SurfaceFormat surfaceFormat) - : base(graphicsDevice, surfaceFormat) + : base(graphicsDevice, surfaceFormat, 1) { } public Texture2D_DX11(GraphicsDevice graphicsDevice, int width, int height, SurfaceFormat surfaceFormat, int mipCount) - : base(graphicsDevice, surfaceFormat) + : base(graphicsDevice, surfaceFormat, mipCount) { - if (mipCount > 1) - throw new Exception("creating textures with mip map not yet implemented"); - + Dx11.Device device = (graphicsDevice.NativeDevice as GraphicsDeviceWindowsDX11).NativeDevice.Device; + var sampleDescription = new SharpDX.DXGI.SampleDescription(1, 0); + + if (useRenderTexture) + { + var descriptionStaging = new Dx11.Texture2DDescription() + { + Width = width, + Height = height, + MipLevels = mipCount, + ArraySize = mipCount, + Format = BaseFormatConverter.Translate(surfaceFormat), + SampleDescription = sampleDescription, + Usage = Dx11.ResourceUsage.Staging, + CpuAccessFlags = Dx11.CpuAccessFlags.Write, + }; + NativeTextureStaging = new Dx11.Texture2D(device, descriptionStaging); + } + var description = new Dx11.Texture2DDescription() { Width = width, @@ -53,16 +69,14 @@ namespace ANX.RenderSystem.Windows.DX11 MipLevels = mipCount, ArraySize = mipCount, Format = BaseFormatConverter.Translate(surfaceFormat), - SampleDescription = new SharpDX.DXGI.SampleDescription(1, 0), - Usage = Dx11.ResourceUsage.Dynamic, + SampleDescription = sampleDescription, + Usage = useRenderTexture ? Dx11.ResourceUsage.Default : Dx11.ResourceUsage.Dynamic, BindFlags = Dx11.BindFlags.ShaderResource, - CpuAccessFlags = Dx11.CpuAccessFlags.Write, - OptionFlags = Dx11.ResourceOptionFlags.None, + CpuAccessFlags = useRenderTexture ? Dx11.CpuAccessFlags.None : Dx11.CpuAccessFlags.Write, }; - Dx11.DeviceContext context = (graphicsDevice.NativeDevice as GraphicsDeviceWindowsDX11).NativeDevice; - NativeTexture = new Dx11.Texture2D(context.Device, description); - NativeShaderResourceView = new Dx11.ShaderResourceView(context.Device, NativeTexture); + NativeTexture = new Dx11.Texture2D(device, description); + NativeShaderResourceView = new Dx11.ShaderResourceView(device, NativeTexture); } #endregion @@ -82,6 +96,12 @@ namespace ANX.RenderSystem.Windows.DX11 NativeShaderResourceView = null; } + if (NativeTextureStaging != null) + { + NativeTextureStaging.Dispose(); + NativeTextureStaging = null; + } + base.Dispose(); } #endregion @@ -89,14 +109,16 @@ namespace ANX.RenderSystem.Windows.DX11 #region SaveAsJpeg (TODO) public void SaveAsJpeg(Stream stream, int width, int height) { - throw new NotImplementedException(); + // TODO: handle width and height? + Dx11.Texture2D.ToStream(NativeTexture.Device.ImmediateContext, NativeTexture, Dx11.ImageFileFormat.Jpg, stream); } #endregion #region SaveAsPng (TODO) public void SaveAsPng(Stream stream, int width, int height) { - throw new NotImplementedException(); + // TODO: handle width and height? + Dx11.Texture2D.ToStream(NativeTexture.Device.ImmediateContext, NativeTexture, Dx11.ImageFileFormat.Png, stream); } #endregion @@ -118,22 +140,25 @@ namespace ANX.RenderSystem.Windows.DX11 #endregion #region MapWrite - protected override IntPtr MapWrite() + protected override IntPtr MapWrite(int level) { Dx11.DeviceContext context = (GraphicsDevice.NativeDevice as GraphicsDeviceWindowsDX11).NativeDevice; - tempSubresource = Dx11.Texture2D.CalculateSubResourceIndex(0, 0, 1); - DataBox box = context.MapSubresource(NativeTexture, tempSubresource, Dx11.MapMode.WriteDiscard, Dx11.MapFlags.None); + tempSubresource = Dx11.Texture2D.CalculateSubResourceIndex(level, 0, mipCount); + var texture = useRenderTexture ? NativeTextureStaging : NativeTexture; + DataBox box = context.MapSubresource(texture, tempSubresource, + useRenderTexture ? Dx11.MapMode.Write : Dx11.MapMode.WriteDiscard, Dx11.MapFlags.None); pitch = box.RowPitch; return box.DataPointer; } #endregion #region MapRead - protected override IntPtr MapRead() + protected override IntPtr MapRead(int level) { Dx11.DeviceContext context = (GraphicsDevice.NativeDevice as GraphicsDeviceWindowsDX11).NativeDevice; - tempSubresource = Dx11.Texture2D.CalculateSubResourceIndex(0, 0, 1); - DataBox box = context.MapSubresource(NativeTexture, tempSubresource, Dx11.MapMode.Read, Dx11.MapFlags.None); + tempSubresource = Dx11.Texture2D.CalculateSubResourceIndex(level, 0, mipCount); + var texture = useRenderTexture ? NativeTextureStaging : NativeTexture; + DataBox box = context.MapSubresource(texture, tempSubresource, Dx11.MapMode.Read, Dx11.MapFlags.None); pitch = box.RowPitch; return box.DataPointer; } @@ -143,7 +168,11 @@ namespace ANX.RenderSystem.Windows.DX11 protected override void Unmap() { Dx11.DeviceContext context = (GraphicsDevice.NativeDevice as GraphicsDeviceWindowsDX11).NativeDevice; - context.UnmapSubresource(NativeTexture, tempSubresource); + var texture = useRenderTexture ? NativeTextureStaging : NativeTexture; + context.UnmapSubresource(texture, tempSubresource); + + if(useRenderTexture) + context.CopyResource(NativeTextureStaging, NativeTexture); } #endregion } diff --git a/RenderSystems/ANX.RenderSystem.Windows.Metro/Creator.cs b/RenderSystems/ANX.RenderSystem.Windows.Metro/Creator.cs index 0b0a3273..3a11f079 100644 --- a/RenderSystems/ANX.RenderSystem.Windows.Metro/Creator.cs +++ b/RenderSystems/ANX.RenderSystem.Windows.Metro/Creator.cs @@ -269,14 +269,11 @@ namespace ANX.RenderSystem.Windows.Metro } #endregion - #region IRenderSystemCreator Member - - + #region IsLanguageSupported public bool IsLanguageSupported(EffectSourceLanguage sourceLanguage) { - throw new NotImplementedException(); + return sourceLanguage == EffectSourceLanguage.HLSL_FX || sourceLanguage == EffectSourceLanguage.HLSL; } - #endregion #region SetTextureSampler (TODO) diff --git a/RenderSystems/ANX.RenderSystem.Windows.Metro/Texture2D_Metro.cs b/RenderSystems/ANX.RenderSystem.Windows.Metro/Texture2D_Metro.cs index eda030de..d9104b1f 100644 --- a/RenderSystems/ANX.RenderSystem.Windows.Metro/Texture2D_Metro.cs +++ b/RenderSystems/ANX.RenderSystem.Windows.Metro/Texture2D_Metro.cs @@ -15,11 +15,14 @@ namespace ANX.RenderSystem.Windows.Metro public class Texture2D_Metro : INativeTexture2D { #region Private + protected bool useRenderTexture; + protected Dx11.Texture2D NativeTextureStaging; protected internal Dx11.Texture2D NativeTexture; protected internal Dx11.ShaderResourceView NativeShaderResourceView; protected int formatSize; protected SurfaceFormat surfaceFormat; protected GraphicsDevice graphicsDevice; + private int mipCount; #endregion #region Public @@ -27,9 +30,7 @@ namespace ANX.RenderSystem.Windows.Metro { get { - return NativeTexture != null ? - NativeTexture.Description.Width : - 0; + return NativeTexture != null ? NativeTexture.Description.Width : 0; } } @@ -37,9 +38,7 @@ namespace ANX.RenderSystem.Windows.Metro { get { - return NativeTexture != null ? - NativeTexture.Description.Height : - 0; + return NativeTexture != null ? NativeTexture.Description.Height : 0; } } #endregion @@ -50,20 +49,32 @@ namespace ANX.RenderSystem.Windows.Metro this.graphicsDevice = graphicsDevice; } - public Texture2D_Metro(GraphicsDevice graphicsDevice, int width, int height, - SurfaceFormat surfaceFormat, int mipCount) + public Texture2D_Metro(GraphicsDevice graphicsDevice, int width, int height, SurfaceFormat surfaceFormat, int mipCount) { - if (mipCount > 1) - { - throw new Exception("creating textures with mip map not yet implemented"); - } - + this.mipCount = mipCount; + useRenderTexture = mipCount > 1; this.graphicsDevice = graphicsDevice; this.surfaceFormat = surfaceFormat; GraphicsDeviceWindowsMetro graphicsMetro = graphicsDevice.NativeDevice as GraphicsDeviceWindowsMetro; var device = graphicsMetro.NativeDevice.NativeDevice; + if (useRenderTexture) + { + var descriptionStaging = new Dx11.Texture2DDescription() + { + Width = width, + Height = height, + MipLevels = mipCount, + ArraySize = mipCount, + Format = FormatConverter.Translate(surfaceFormat), + SampleDescription = new SharpDX.DXGI.SampleDescription(1, 0), + Usage = Dx11.ResourceUsage.Staging, + CpuAccessFlags = Dx11.CpuAccessFlags.Write, + }; + NativeTextureStaging = new Dx11.Texture2D(device, descriptionStaging); + } + var description = new Dx11.Texture2DDescription() { Width = width, @@ -72,10 +83,9 @@ namespace ANX.RenderSystem.Windows.Metro ArraySize = mipCount, Format = FormatConverter.Translate(surfaceFormat), SampleDescription = new SharpDX.DXGI.SampleDescription(1, 0), - Usage = Dx11.ResourceUsage.Dynamic, + Usage = useRenderTexture ? Dx11.ResourceUsage.Default : Dx11.ResourceUsage.Dynamic, BindFlags = Dx11.BindFlags.ShaderResource, - CpuAccessFlags = Dx11.CpuAccessFlags.Write, - OptionFlags = Dx11.ResourceOptionFlags.None, + CpuAccessFlags = useRenderTexture ? Dx11.CpuAccessFlags.None : Dx11.CpuAccessFlags.Write, }; this.NativeTexture = new Dx11.Texture2D(device, description); this.NativeShaderResourceView = new Dx11.ShaderResourceView(device, this.NativeTexture); @@ -95,119 +105,153 @@ namespace ANX.RenderSystem.Windows.Metro #endregion #region SetData - public void SetData(int level, Rectangle? rect, T[] data, - int startIndex, int elementCount) where T : struct - { - throw new NotImplementedException(); - } - - public void SetData(GraphicsDevice graphicsDevice, T[] data) - where T : struct + public void SetData(GraphicsDevice graphicsDevice, T[] data) where T : struct { SetData(graphicsDevice, 0, data, 0, data.Length); } - public void SetData(GraphicsDevice graphicsDevice, T[] data, - int startIndex, int elementCount) where T : struct + public void SetData(GraphicsDevice graphicsDevice, T[] data, int startIndex, int elementCount) where T : struct { SetData(graphicsDevice, 0, data, startIndex, elementCount); } - public void SetData(GraphicsDevice graphicsDevice, int offsetInBytes, - T[] data, int startIndex, int elementCount) where T : struct + public void SetData(GraphicsDevice graphicsDevice, int offsetInBytes, T[] data, int startIndex, int elementCount) + where T : struct { //TODO: handle offsetInBytes parameter //TODO: handle startIndex parameter //TODO: handle elementCount parameter + + unsafe + { + GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned); + byte* colorData = (byte*)handle.AddrOfPinnedObject(); + + switch (surfaceFormat) + { + case SurfaceFormat.Color: + SetDataColor(0, offsetInBytes, colorData, startIndex, elementCount); + return; + + case SurfaceFormat.Dxt1: + case SurfaceFormat.Dxt3: + case SurfaceFormat.Dxt5: + SetDataDxt(0, offsetInBytes, colorData, startIndex, elementCount, data.Length); + return; + } + + handle.Free(); + } + + throw new Exception(String.Format("creating textures of format {0} not yet implemented...", surfaceFormat)); + } + + public void SetData(int level, Rectangle? rect, T[] data, int startIndex, int elementCount) where T : struct + { + //TODO: handle rect parameter + if (rect != null) + throw new Exception("Texture2D SetData with rectangle is not yet implemented!"); + + unsafe + { + GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned); + byte* colorData = (byte*)handle.AddrOfPinnedObject(); + + switch (surfaceFormat) + { + case SurfaceFormat.Color: + SetDataColor(level, 0, colorData, startIndex, elementCount); + return; + + case SurfaceFormat.Dxt1: + case SurfaceFormat.Dxt3: + case SurfaceFormat.Dxt5: + SetDataDxt(level, 0, colorData, startIndex, elementCount, data.Length); + return; + } + + handle.Free(); + } + + throw new Exception(String.Format("creating textures of format {0} not yet implemented...", surfaceFormat)); + } + #endregion + + #region SetDataColor + private unsafe void SetDataColor(int level, int offsetInBytes, byte* colorData, int startIndex, int elementCount) + { + int mipmapWidth = Math.Max(Width >> level, 1); + int mipmapHeight = Math.Max(Height >> level, 1); + + int subresource = Dx11.Texture2D.CalculateSubResourceIndex(level, 0, mipCount); + var texture = useRenderTexture ? NativeTextureStaging : NativeTexture; + SharpDX.DataBox rectangle = NativeDxDevice.Current.MapSubresource(texture, subresource); - if (this.surfaceFormat == SurfaceFormat.Color) + int srcIndex = 0; + byte* pTexels = (byte*)rectangle.DataPointer; + for (int row = 0; row < mipmapHeight; row++) { - int subresource = Dx11.Texture2D.CalculateSubResourceIndex(0, 0, 1); - SharpDX.DataBox rectangle = NativeDxDevice.Current.MapSubresource(NativeTexture, subresource); - int rowPitch = rectangle.RowPitch; + int rowStart = row * rectangle.RowPitch; - unsafe + for (int col = 0; col < mipmapWidth; col++) { - GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned); - byte* colorData = (byte*)handle.AddrOfPinnedObject(); - - byte* pTexels = (byte*)rectangle.DataPointer; - int srcIndex = 0; - - for (int row = 0; row < Height; row++) - { - int rowStart = row * rowPitch; - - for (int col = 0; col < Width; col++) - { - int colStart = col * formatSize; - pTexels[rowStart + colStart + 0] = colorData[srcIndex++]; - pTexels[rowStart + colStart + 1] = colorData[srcIndex++]; - pTexels[rowStart + colStart + 2] = colorData[srcIndex++]; - pTexels[rowStart + colStart + 3] = colorData[srcIndex++]; - } - } - - handle.Free(); - } - - NativeDxDevice.Current.UnmapSubresource(NativeTexture, subresource); - } - else if (surfaceFormat == SurfaceFormat.Dxt5 || surfaceFormat == SurfaceFormat.Dxt3 || surfaceFormat == SurfaceFormat.Dxt1) - { - unsafe - { - GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned); - byte* colorData = (byte*)handle.AddrOfPinnedObject(); - - int w = (Width + 3) >> 2; - int h = (Height + 3) >> 2; - formatSize = (surfaceFormat == SurfaceFormat.Dxt1) ? 8 : 16; - - int subresource = Dx11.Texture2D.CalculateSubResourceIndex(0, 0, 1); - SharpDX.DataBox rectangle = - NativeDxDevice.Current.MapSubresource(NativeTexture, subresource); - SharpDX.DataStream ds = new SharpDX.DataStream(rectangle.DataPointer, Width * Height * 4 * 2, true, true); - int pitch = rectangle.RowPitch; - int col = 0; - int index = 0; // startIndex - int count = data.Length; // elementCount - int actWidth = w * formatSize; - - for (int i = 0; i < h; i++) - { - ds.Position = (i * pitch) + (col * formatSize); - if (count <= 0) - { - break; - } - else if (count < actWidth) - { - for (int idx = index; idx < index + count; idx++) - { - ds.WriteByte(colorData[idx]); - } - break; - } - - for (int idx = index; idx < index + actWidth; idx++) - { - ds.WriteByte(colorData[idx]); - } - - index += actWidth; - count -= actWidth; - } - - handle.Free(); - - NativeDxDevice.Current.UnmapSubresource(NativeTexture, subresource); + int colStart = rowStart + (col * formatSize); + pTexels[colStart++] = colorData[srcIndex++]; + pTexels[colStart++] = colorData[srcIndex++]; + pTexels[colStart++] = colorData[srcIndex++]; + pTexels[colStart++] = colorData[srcIndex++]; } } - else + + NativeDxDevice.Current.UnmapSubresource(texture, subresource); + if (useRenderTexture) + NativeDxDevice.Current.NativeContext.CopyResource(NativeTextureStaging, NativeTexture); + } + #endregion + + #region SetDataDxt + private unsafe void SetDataDxt(int level, int offsetInBytes, byte* colorData, int startIndex, int elementCount, + int dataLength) + { + int mipmapWidth = Math.Max(Width >> level, 1); + int mipmapHeight = Math.Max(Height >> level, 1); + + int w = (mipmapWidth + 3) >> 2; + int h = (mipmapHeight + 3) >> 2; + formatSize = (surfaceFormat == SurfaceFormat.Dxt1) ? 8 : 16; + + int subresource = Dx11.Texture2D.CalculateSubResourceIndex(level, 0, mipCount); + var texture = useRenderTexture ? NativeTextureStaging : NativeTexture; + SharpDX.DataBox rectangle = NativeDxDevice.Current.MapSubresource(texture, subresource); + + var ds = new SharpDX.DataStream(rectangle.DataPointer, mipmapWidth * mipmapHeight * 4 * 2, true, true); + int col = 0; + int index = 0; // startIndex + int count = dataLength; // elementCount + int actWidth = w * formatSize; + + for (int i = 0; i < h; i++) { - throw new Exception(string.Format("creating textures of format {0} not yet implemented...", surfaceFormat.ToString())); + ds.Position = (i * rectangle.RowPitch) + (col * formatSize); + if (count <= 0) + break; + else if (count < actWidth) + { + for (int idx = index; idx < index + count; idx++) + ds.WriteByte(colorData[idx]); + break; + } + + for (int idx = index; idx < index + actWidth; idx++) + ds.WriteByte(colorData[idx]); + + index += actWidth; + count -= actWidth; } + + NativeDxDevice.Current.UnmapSubresource(texture, subresource); + if (useRenderTexture) + NativeDxDevice.Current.NativeContext.CopyResource(NativeTextureStaging, NativeTexture); } #endregion @@ -225,6 +269,12 @@ namespace ANX.RenderSystem.Windows.Metro NativeTexture.Dispose(); NativeTexture = null; } + + if (NativeTextureStaging != null) + { + NativeTextureStaging.Dispose(); + NativeTextureStaging = null; + } } #endregion diff --git a/Samples/SampleContent/SampleContent.contentproj b/Samples/SampleContent/SampleContent.contentproj index f89d981d..8f540c3f 100644 --- a/Samples/SampleContent/SampleContent.contentproj +++ b/Samples/SampleContent/SampleContent.contentproj @@ -141,6 +141,13 @@ ModelProcessor + + + dds-test + TextureImporter + TextureProcessor + +