Sign in to follow this  
captain_crunch

Multisample RenderTarget is blank after drawing to it

Recommended Posts

I am working with the MonoGame source and trying to make MSAA work in RenderTarget2D. Something that MonoGame currently does not support.

 

I can create an MS RenderTarget now, but the problem is that when I draw to it, the result is blank. I can verify that the result is blank by using Intel GPA and comparing with drawing to a non-MS RenderTarget. So it is not because I don't call ResolveSubresource (unless GPA can't display an MS render target?)

 

I can call ResolveSubresource later, but it only transfers the blank color of the texture to the destination.

 

I cannot work out why it doesn't render anything, or how to fix it.

 

 


Here is the modified MonoGame code that creates the MS render target, using SharpDX:

     private void GenerateIfRequired()
        {
            if (_renderTargetViews != null)
                return;


            // Create a view interface on the rendertarget to use on bind.
            if (ArraySize > 1)
            {
                _renderTargetViews = new RenderTargetView[ArraySize];
                for (var i = 0; i < ArraySize; i++)
                {
                    var renderTargetViewDescription = new RenderTargetViewDescription();
                    if (MultiSampleCount > 1)
                    {
                        renderTargetViewDescription.Dimension = RenderTargetViewDimension.Texture2DMultisampledArray;
                        renderTargetViewDescription.Texture2DMSArray.ArraySize = 1;
                        renderTargetViewDescription.Texture2DMSArray.FirstArraySlice = i;
                    }
                    else
                    {
                        renderTargetViewDescription.Dimension = RenderTargetViewDimension.Texture2DArray;
                        renderTargetViewDescription.Texture2DArray.ArraySize = 1;
                        renderTargetViewDescription.Texture2DArray.FirstArraySlice = i;
                        renderTargetViewDescription.Texture2DArray.MipSlice = 0;
                    }
                    _renderTargetViews[i] = new RenderTargetView(
                        GraphicsDevice._d3dDevice, GetTexture(),
                        renderTargetViewDescription);
                }
            }
            else
            {
                _renderTargetViews = new[] { new RenderTargetView(GraphicsDevice._d3dDevice, GetTexture()) };
            }


            // If we don't need a depth buffer then we're done.
            if (DepthStencilFormat == DepthFormat.None)
                return;


            // Setup the multisampling description.
            var multisampleDesc = new SharpDX.DXGI.SampleDescription(1, 0);
            if (MultiSampleCount > 1)
            {
                multisampleDesc.Count = MultiSampleCount;
                multisampleDesc.Quality = (int)StandardMultisampleQualityLevels.StandardMultisamplePattern;
            }


            // Create a descriptor for the depth/stencil buffer.
            // Allocate a 2-D surface as the depth/stencil buffer.
            // Create a DepthStencil view on this surface to use on bind.
            using (var depthBuffer = new SharpDX.Direct3D11.Texture2D(GraphicsDevice._d3dDevice, new Texture2DDescription
            {
                Format = SharpDXHelper.ToFormat(DepthStencilFormat),
                ArraySize = 1,
                MipLevels = 1,
                Width = width,
                Height = height,
                SampleDescription = multisampleDesc,
                BindFlags = BindFlags.DepthStencil,
            }))
            {
                DepthStencilViewDimension dsvDimension;
                if (MultiSampleCount > 1)
                {
                    dsvDimension = DepthStencilViewDimension.Texture2DMultisampled;
                }
                else
                {
                    dsvDimension = DepthStencilViewDimension.Texture2D;
                }


                DepthStencilViewDescription desc = new DepthStencilViewDescription()
                    {
                        Format = SharpDXHelper.ToFormat(DepthStencilFormat),
                        Dimension = dsvDimension          
                    };




                // Create the view for binding to the device.
                _depthStencilView = new DepthStencilView(GraphicsDevice._d3dDevice, depthBuffer,
                    desc);
            }
        }

 

Share this post


Link to post
Share on other sites

I am wondering if some flags need to be set differently when rendering to an MS render target. Currently I am setting 

device.DepthStencilState = DepthStencilState.None;

or

device.DepthStencilState = DepthStencilState.Default;

before rendering.

 

I am using this code to resolve the MS rendertarget into a normal rendertarget (not the screen/backbuffer) after drawing is completed:

GraphicsDevice._d3dContext.ResolveSubresource(this._texture, 0, destination._texture, 0, SharpDXHelper.ToFormat(destination._format)); 
           
Edited by captain_crunch

Share this post


Link to post
Share on other sites

RenderDoc tells me that there are some errors: "Invalid output merger - Depth target is different size or MS count to render target(s)".

 

Also, by inspecting the code, MonoGame looks like it is always creating the main texture without multisampling. Only the depth buffer takes multisampling into account.

 

I got it working after fixing these things.

Edited by captain_crunch

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this