Using Texture2DMS in shader

Started by
5 comments, last by MJP 9 years, 7 months ago

Hello. I am using sharpdx on WinRT with toolkit.

I draw to multisampled rendertarget and then resolve subresource to backbuffer to see MSAA texture as a result.

It works fine, but then I want just to draw this render target as minivariant of full view using spritebatch. And it also works, but I receive non-multisampled texture and visual studio says that


D3D11 ERROR: ID3D11DeviceContext::DrawIndexed: The Shader Resource View dimension declared in the shader code (TEXTURE2D) does not match the view type bound to slot 0 of the Pixel Shader unit (TEXTURE2DMS).  This mismatch is invalid if the shader actually uses the view (e.g. it is not skipped due to shader code branching). [ EXECUTION ERROR #354: DEVICE_DRAW_VIEW_DIMENSION_MISMATCH]

In my shader currently I use Texture2D instead Texture2DMS, but I don`t know how to correctly work with Texture2DMS.

Also drawing to texture2D not causing this error. IT appears when executing spriteBatch.End(); method in:


DepthStencilView oldDepth;
                    RenderTargetView[] oldTargets = GraphicsDevice.GetRenderTargets(out oldDepth);
                    GraphicsDevice.SetRenderTargets(depthStencilBuffer,rt);
                    GraphicsDevice.Clear(Color.CornflowerBlue);
                    
                    {


                        customEffect.CurrentTechnique.Passes[0].Apply();
                        //Setup the vertices
                        GraphicsDevice.SetVertexBuffer(vertices);
                        // Setup the indices
                        GraphicsDevice.SetIndexBuffer(indices, true);


                        GraphicsDevice.SetVertexInputLayout(inputLayout);
                        
                        GraphicsDevice.DrawIndexed(PrimitiveType.TriangleList, indices.ElementCount);


                        
                        fpsRenderer.Render(d2DService);
                        d2DService.Context.BeginDraw();
                        d2DService.Context.DrawText(D2DText, d2DService.TextFormat, d2DService.RectangleF,
                            d2DService.TextBrush);
                        d2DService.Context.EndDraw();
                        device.ResolveSubresource(rt, 0, GraphicsDevice.BackBuffer, 0, GraphicsDevice.BackBuffer.Format);
                        GraphicsDevice.SetRenderTargets(oldDepth, oldTargets);


                        spriteBatch.Begin();
                        spriteBatch.Draw(rt, new RectangleF((int)SwapChainPanel.ActualWidth - 500, (int)SwapChainPanel.ActualHeight - 350, 500, 350), new Rectangle(0, 0, 500, 350), Color.White, 0.0f, new Vector2(100, 100), SpriteEffects.None, 0.0f);                        
spriteBatch.End(); 

What I must do to solve this issue? Can someone help me with it please?

Advertisement

You can probably just replace 'Texture2D' with 'Texture2DMS' in the shader.

You'll want to resolve your MSAA texture before you can sample from it using SpriteBatch. Just create another render target texture that has the same dimensions/format as your MSAA texture but with 0 multisamples, and then resolve to that before using it with SpriteBatch.

You'll want to resolve your MSAA texture before you can sample from it using SpriteBatch. Just create another render target texture that has the same dimensions/format as your MSAA texture but with 0 multisamples, and then resolve to that before using it with SpriteBatch.

Interesting. It works. I thought about such solution, but was not sure to try it. Thanks a lot.

But I also want to know how to use Texture2DMS in shader. Currently if I just change Texture2d toTexture2DMS<float4, 8>, it says that Texture2DMS object does not have method 'Sample'

Here is my pixel shader.

float4 LightPixelShader(PixelInputType input) : SV_TARGET
{
float4 textureColor;
float3 lightDir = 0;
float lightIntensity;
float4 color;




// Sample the pixel color from the texture using the sampler at this texture coordinate location.
textureColor = shaderTexture.Sample(sampleType, input.tex);


// Invert the light direction for calculations.
    color = AmbientColor * AmbientIntensity;


    // Calculate the amount of light on this pixel.
lightIntensity = saturate(dot(input.normal, lightDirection));


    // Determine the final amount of diffuse color based on the diffuse color combined with the light intensity.
    color = saturate(diffuseColor * lightIntensity);


    // Multiply the texture pixel and the final diffuse color to get the final pixel color result.
    color = color + textureColor;


    return color;
}


So, I must use texture2dms in other way, than texture2d, but how exactly?

You can't use any of the "Sample" functions on a Texture2DMS, since MSAA textures don't support filtering or any of the "normal" texture operations. The only thing you can with them is load a single subsample at a time, by specifying integer pixel coordinates as well as a subsample index. See the documentation for more info.

For your case, if you wanted to resolve the texture on-the-fly in the pixel shader you can just load all of your subsamples for a given pixel and then average the result. Also, note that for ps_5_0 you're not required to declare the Texture2DMS with the number of subsamples as a template parameter. You only had to do this for ps_4_0.

So, if I use MS texture, shader will be like this?


Texture2DMS<float4> shaderTexture;

float4 LightPixelShader(PixelInputType input) : SV_TARGET
{
float4 textureColor;
float3 lightDir = 0;
float lightIntensity;
float4 color;
int sampleIndex = 8;



// Sample the pixel color from the texture using the sampler at this texture coordinate location.
textureColor = shaderTexture.Load(input.tex, sampleIndex);


// Invert the light direction for calculations.
    color = AmbientColor * AmbientIntensity;


    // Calculate the amount of light on this pixel.
lightIntensity = saturate(dot(input.normal, lightDirection));


    // Determine the final amount of diffuse color based on the diffuse color combined with the light intensity.
    color = saturate(diffuseColor * lightIntensity);


    // Multiply the texture pixel and the final diffuse color to get the final pixel color result.
    color = color + textureColor;


    return color;
}

Or I missing something?

Update

NO, it`s not working. Texture on the model in that case not rendered as it is not multisampled. I think, that I need separate shader or technique to resolve MS textures for rendertarget.

Like I said previously, Texture2DMS.Load takes integer pixel coordinates. You're passing the same [0,1] texture coordinates that you use for Texture2D.Sample, which isn't going to work. You can obtain the current pixel coordinate in a pixel shader by using the SV_Position semantic.

You're also only sampling one subsample from your Texture2DMS, and the index you're passing is too high. If you have 8 subsamples for your render target, then the valid indices that you can pass are 0-7. Try using a for loop that goes from 0-7, and averaging the result from all subsamples.

This topic is closed to new replies.

Advertisement