Konstantin Koch d9e752b3b1 Fix AssimpImporter and that Rendersystems can be loaded when creating content files, also allows Reference and Null Device for DX
If a model was imported with TargetRealTimeMaximumQuality and then
drawn, it causes a blue screen on my system (Nvidia Geforce GTC 650,
Driver version 353.62)
Also disabled Content recreation if a content project is launched with
the visual studio debugger.
2015-11-22 14:12:43 +01:00

244 lines
8.0 KiB
C#

#region Using Statements
using System;
using System.Runtime.InteropServices;
using ANX.Framework.Graphics;
using SharpDX;
#endregion
// 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
#if DX10
namespace ANX.RenderSystem.Windows.DX10
#endif
#if DX11
namespace ANX.RenderSystem.Windows.DX11
#endif
{
public partial class DxTexture2D : IDisposable
{
#if DEBUG
static int textureCount = 0;
#endif
protected SurfaceFormat surfaceFormat;
public int Width
{
get;
protected set;
}
public int Height
{
get;
protected set;
}
#region Public
public GraphicsDeviceDX GraphicsDevice
{
get;
protected set;
}
#endregion
public void SetData<T>(T[] data) where T : struct
{
SetData<T>(0, null, data, 0, data.Length);
}
public void SetData<T>(T[] data, int startIndex, int elementCount) where T : struct
{
SetData<T>(0, null, data, startIndex, elementCount);
}
public void SetData<T>(int level, Framework.Rectangle? rect, T[] data, int startIndex, int elementCount) where T : struct
{
Framework.Rectangle realRect;
if (rect.HasValue)
realRect = rect.Value;
else
{
realRect.X = 0;
realRect.Y = 0;
realRect.Width = this.Width;
realRect.Height = this.Height;
}
//If we write too much, the graphics driver may break down and we cause a blue screen :(
if (SizeInBytes(level, realRect) != data.Length)
throw new ArgumentException("Not the correct amount of data to fill the region.");
UpdateSubresource(data, _nativeTexture, level, realRect);
}
public void GetData<T>(T[] data) where T : struct
{
if (data == null)
throw new ArgumentNullException("data");
this.GetData<T>(0, null, data, 0, data.Length);
}
public void GetData<T>(T[] data, int startIndex, int elementCount) where T : struct
{
this.GetData<T>(0, null, data, startIndex, elementCount);
}
private Framework.Rectangle ValidateRect<T>(int level, Framework.Rectangle? rect, T[] data, int startIndex, int elementCount)
{
if (data == null)
throw new ArgumentNullException("data");
if (startIndex + elementCount > data.Length)
throw new ArgumentOutOfRangeException("startIndex + elementCount is bigger than data.Length");
int mipmapWidth = Math.Max(Width >> level, 1);
int mipmapHeight = Math.Max(Height >> level, 1);
Framework.Rectangle finalRect;
if (rect != null)
{
finalRect = rect.Value;
if (finalRect.X < 0 || finalRect.Width <= 0 || finalRect.Y < 0 || finalRect.Height <= 0)
throw new ArgumentException("The given rectangle is invalid.");
if (finalRect.Right > mipmapWidth || finalRect.Bottom > mipmapHeight)
throw new ArgumentException("The given rectangle is bigger than the texture on the given mip level.");
}
else
finalRect = new Framework.Rectangle(0, 0, mipmapWidth, mipmapHeight);
int formatSize = DxFormatConverter.FormatSize(this.surfaceFormat);
int elementSize = Marshal.SizeOf(typeof(T));
if (elementSize * elementCount != formatSize * mipmapWidth * mipmapHeight)
throw new ArgumentException("\"data\" has the wrong size.");
return finalRect;
}
public void GetData<T>(int level, Framework.Rectangle? rect, T[] data, int startIndex, int elementCount) where T : struct
{
var finalRect = ValidateRect(level, rect, data, startIndex, elementCount);
using (var texture = CreateStagingTexture(ResourceMapping.Read))
{
GraphicsDevice.NativeDevice.CopyResource(NativeTexture, texture);
int subresource = GetSubresource(level);
int pitch;
using (var dataStream = Map(texture, subresource, level, ResourceMapping.Read, out pitch))
{
try
{
int elementIndex = startIndex;
for (int y = finalRect.Top; y < finalRect.Bottom; y++)
{
int width = Math.Min(finalRect.Width, elementCount);
if (width <= 0)
break;
dataStream.Position = y * pitch;
dataStream.ReadRange(data, elementIndex, width);
elementIndex += finalRect.Width;
elementCount -= width;
}
}
finally
{
Unmap(texture, subresource);
}
}
}
}
private bool IsDxt
{
get
{
return this.surfaceFormat == SurfaceFormat.Dxt1 || this.surfaceFormat == SurfaceFormat.Dxt3 || this.surfaceFormat == SurfaceFormat.Dxt5;
}
}
protected int SizeInBytes(int level, Framework.Rectangle? rect = null)
{
int width = this.Width;
int height = this.Height;
if (rect.HasValue)
{
width = rect.Value.Width;
height = rect.Value.Height;
}
int mipmapWidth = Math.Max(width >> level, 1);
int mipmapHeight = Math.Max(height >> level, 1);
if (this.IsDxt)
{
//Dxt uses 4x4 blocks and each of this block is 8 bytes in size for dxt1, so on average half a byte per pixel.
//For Dxt3 and Dxt5, it's 1 byte per pixel on average.
int w = (mipmapWidth + 3) / 4;
int h = (mipmapHeight + 3) / 4;
var formatSize = (surfaceFormat == SurfaceFormat.Dxt1) ? 8 : 16;
return w * h * formatSize;
}
else
{
return mipmapWidth * mipmapHeight * DxFormatConverter.FormatSize(this.surfaceFormat);
}
}
protected int GetPitch(int level)
{
int mipmapWidth = Math.Max(Width >> level, 1);
if (this.IsDxt)
{
//Dxt uses 4x4 blocks and each of this block is 8 bytes in size for dxt1, so on average half a byte per pixel.
//For Dxt3 and Dxt5, it's 1 byte per pixel on average.
int w = (mipmapWidth + 3) / 4;
var formatSize = (surfaceFormat == SurfaceFormat.Dxt1) ? 8 : 16;
return w * formatSize;
}
else
{
return mipmapWidth * DxFormatConverter.FormatSize(this.surfaceFormat);
}
}
#region Dispose
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool managed)
{
if (managed)
{
if (NativeShaderResourceView != null)
{
NativeShaderResourceView.Dispose();
NativeShaderResourceView = null;
}
if (NativeTexture != null)
{
NativeTexture.Dispose();
NativeTexture = null;
}
}
}
#endregion
}
}