Hi there,
I'm using SlimDX and DirectX 10. I'm rendering to an 8bit unsigned render target. Once I'm done rendering, I copy the render target over to a CPU readable texture map and try to read it out into an array of byte. I'm using Marshal.Copy and this has been working for a long time. Since I've started to use the November 2008 version of SlimDX, I've encountered cases where the extraction code would fail with a memory access error. This presists through application restarts and even computer reboots, and then suddently goes away again without any change in the code.
Does anyone know a better way to get a render target back into CPU accessible memory. It has to be very fast and the speed of Marshal.Copy has been satisfactory.
This is what I'm doing to get the Render Target read back into a byte array:
// copy the render target to a CPU accessible texture map
D3D10.Texture2D cpuTexture = new D3D10.Texture2D(device, RenderingDevice.CpuTextureDescription);
device.CopyResource(renderTexture, cpuTexture);
try
{
// now get the data out of the texture
DataRectangle data = cpuTexture.Map(0, D3D10.MapMode.Read, D3D10.MapFlags.None);
// and convert it to a byte array
result = ExtractByteArray(data.Data.DataPointer, data.Pitch, width, height);
}
catch (Exception ex)
{
ImgServerForm.AddLog(EventLoggerType.Exception, "Error during FastMap Rendering Layer: " + LayerId.ToString() + " Error: " + ex.ToString());
Exception newException = new Exception("Error during FastMap Rendering", ex);
throw newException;
}
finally
{
cpuTexture.Unmap(0);
}
cpuTexture.Dispose();
renderTarget.Dispose();
renderTexture.Dispose();
This is the extraction method:
private byte[] ExtractByteArray(IntPtr source, int pitch, int width, int height)
{
// Declare an array to hold the bytes of the bitmap.
int bytes = width * height;
byte[] newValues = new byte[bytes];
// Copy the RGB values into the array.
for (int y = 0; y < height; y++)
{
Marshal.Copy(new IntPtr(source.ToInt32() + y * pitch), newValues, y * width, width);
}
// !! This is the line that fails, though I believe it's the Marshal.Copy that causes the issue
return newValues;
}
These are the render target and cpu texture definitions:
_sampleDescription = new DXGI.SampleDescription();
_sampleDescription.Count = 1;
_sampleDescription.Quality = 0;
_renderTargetDescription = new D3D10.Texture2DDescription();
_renderTargetDescription.ArraySize = 1;
_renderTargetDescription.MipLevels = 1;
_renderTargetDescription.SampleDescription = _sampleDescription;
_renderTargetDescription.Format = DXGI.Format.R8_UInt;
_renderTargetDescription.CpuAccessFlags = D3D10.CpuAccessFlags.None;
_renderTargetDescription.BindFlags = D3D10.BindFlags.RenderTarget;
_renderTargetDescription.Usage = D3D10.ResourceUsage.Default;
_cpuTextureDescription = new D3D10.Texture2DDescription();
_cpuTextureDescription.ArraySize = 1;
_cpuTextureDescription.MipLevels = 1;
_cpuTextureDescription.SampleDescription = _sampleDescription;
_cpuTextureDescription.Format = DXGI.Format.R8_UInt;
_cpuTextureDescription.CpuAccessFlags = D3D10.CpuAccessFlags.Read;
_cpuTextureDescription.BindFlags = D3D10.BindFlags.None;
_cpuTextureDescription.Usage = D3D10.ResourceUsage.Staging;
And last but not least, these are the types of errors I'm receiving when the system doesn't work as it should:
[2009-01-22_00-11-38],Exception,Error during FastMap Rendering Layer:
52 Error: System.OverflowException: Arithmetic operation resulted in an overflow.
at RenderingServices.DataModel.Layer.ExtractByteArray(IntPtr source, Int32 pitch, Int32 width, Int32 height) in ...\DataModel\Layer.cs:line 414
at RenderingServices.DataModel.Layer.Render(Device device, Int32 timeSlot, Int32 width, Int32 height, Single left, Single right, Single top, Single bottom, TimeSpan& timeOnCard) in ...\DataModel\Layer.cs:line 237
[2009-01-22_00-11-38],Exception,Unhandled Exception in Rendering Code:
System.Exception: Error during FastMap Rendering ---> System.OverflowException: Arithmetic operation resulted in an overflow.
at RenderingServices.DataModel.Layer.ExtractByteArray(IntPtr source, Int32 pitch, Int32 width, Int32 height) in ...\DataModel\Layer.cs:line 414
at RenderingServices.DataModel.Layer.Render(Device device, Int32 timeSlot, Int32 width, Int32 height, Single left, Single right, Single top, Single bottom, TimeSpan& timeOnCard) in ...\DataModel\Layer.cs:line 237
--- End of inner exception stack trace ---
at RenderingServices.DataModel.Layer.Render(Device device, Int32 timeSlot, Int32 width, Int32 height, Single left, Single right, Single top, Single bottom, TimeSpan& timeOnCard) in ...\DataModel\Layer.cs:line 258
at RenderingServices.ImageServer.ImgService.GenerateImageArea(UInt32 clientId, Int32 layerId, Int32 slotNumber, FastMapArea area) in ...\ImageService\ImgService.cs:line 648
If anyone has encountered that problem, I'd be most grateful if you could tell me how to get around it or if someone has a better way to get the texture back into CPU memory in a fast way, that would work too.
Thanks
Marcel