Multisampled Texture2D.SaveAsPng crashes

I am debugging some rendering issues on Windows (DirectX) and am trying to save a rendertarget as a file. But the rendertarget is multisampled, and the call throws an “Invalid arguments” exception. The rendertarget is not set as the current target for draw operations.

HRESULT: [0x80070057], Module: [General], ApiCode: [E_INVALIDARG/Invalid Arguments]
   ved SharpDX.Result.CheckError()
   ved SharpDX.Direct3D11.Device.CreateTexture2D(Texture2DDescription& descRef, DataBox[] initialDataRef, Texture2D texture2DOut)
   ved SharpDX.Direct3D11.Texture2D..ctor(Device device, Texture2DDescription description)
   ved Microsoft.Xna.Framework.Graphics.Texture2D.PlatformGetData[T](Int32 level, Int32 arraySlice, Rectangle rect, T[] data, Int32 startIndex, Int32 elementCount) i C:\Users\User\Documents\Visual Studio 2017\Projects\MonoGame\MonoGame.Framework\Graphics\Texture2D.DirectX.cs:linje 138
   ved Microsoft.Xna.Framework.Graphics.Texture2D.GetData[T](Int32 level, Int32 arraySlice, Nullable`1 rect, T[] data, Int32 startIndex, Int32 elementCount) i C:\Users\User\Documents\Visual Studio 2017\Projects\MonoGame\MonoGame.Framework\Graphics\Texture2D.cs:linje 206
   ved Microsoft.Xna.Framework.Graphics.Texture2D.GetData[T](Int32 level, Nullable`1 rect, T[] data, Int32 startIndex, Int32 elementCount) i C:\Users\User\Documents\Visual Studio 2017\Projects\MonoGame\MonoGame.Framework\Graphics\Texture2D.cs:linje 221
   ved Microsoft.Xna.Framework.Graphics.Texture2D.GetData[T](T[] data) i C:\Users\User\Documents\Visual Studio 2017\Projects\MonoGame\MonoGame.Framework\Graphics\Texture2D.cs:linje 247
   ved MonoGame.Utilities.Png.PngWriter.GetColorData(Texture2D texture2D) i C:\Users\User\Documents\Visual Studio 2017\Projects\MonoGame\MonoGame.Framework\Utilities\Png\PngWriter.cs:linje 227
   ved MonoGame.Utilities.Png.PngWriter.Write(Texture2D texture2D, Stream outputStream) i C:\Users\User\Documents\Visual Studio 2017\Projects\MonoGame\MonoGame.Framework\Utilities\Png\PngWriter.cs:linje 36
   ved Microsoft.Xna.Framework.Graphics.Texture2D.PlatformSaveAsPng(Stream stream, Int32 width, Int32 height) i C:\Users\User\Documents\Visual Studio 2017\Projects\MonoGame\MonoGame.Framework\Graphics\Texture2D.DirectX.cs:linje 311
   ved Microsoft.Xna.Framework.Graphics.Texture2D.SaveAsPng(Stream stream, Int32 width, Int32 height) i C:\Users\User\Documents\Visual Studio 2017\Projects\MonoGame\MonoGame.Framework\Graphics\Texture2D.cs:linje 294

This is the place in MonoGame that throws the exception:

   private void PlatformGetData<T>(int level, int arraySlice, Rectangle rect, T[] data, int startIndex, int elementCount) where T : struct
        {
            // Create a temp staging resource for copying the data.
            // 
            // TODO: We should probably be pooling these staging resources
            // and not creating a new one each time.
            //
            var min = _format.IsCompressedFormat() ? 4 : 1;
            var levelWidth = Math.Max(width >> level, min);
            var levelHeight = Math.Max(height >> level, min);

            if (_cachedStagingTexture == null)
            {
                var desc = new Texture2DDescription();
                desc.Width = levelWidth;
                desc.Height = levelHeight;
                desc.MipLevels = 1;
                desc.ArraySize = 1;
                desc.Format = SharpDXHelper.ToFormat(_format);
                desc.BindFlags = BindFlags.None;
                desc.CpuAccessFlags = CpuAccessFlags.Read;
                desc.SampleDescription = CreateSampleDescription();
                desc.Usage = ResourceUsage.Staging;
                desc.OptionFlags = ResourceOptionFlags.None;

                // Save sampling description.
                _sampleDescription = desc.SampleDescription;

                _cachedStagingTexture = new SharpDX.Direct3D11.Texture2D(GraphicsDevice._d3dDevice, desc); <- line that crashes
            }

Since we are here, my save png works but sometimes, in like 10% of cases bottom 25% of png isnt saved (0,0,0,0 pixels), only restart of applications help. Someone encountered that? Might be related.

First of all - multisampled RTs have problems, are they even working by default? There have been some threads on how to modify monogame to make them work.

did you resolve the texture beforehand, or do you expect that to be the default behaviour for savetopng? If so you might have to write an issue on the git repository, but as I said I think RTs don’t work with MSAA by default, since there were many cases, just like the one you reported, that were not covered by a basic implementation

MSAA RTs have been implemented lately and I can confirm that they work.

Oh, I ran into the same issue when implementing GraphicsDevice.GetBackBufferData. We need to explicitly handle ms texture by copying the multisampled texture to a non-multisampled texture first. Can you open an issue for this @monogany? I’ll take a look if I have some time this weekend :slight_smile:

Yes, I’ll do that. :seedling:

1 Like