Sign in to follow this  
DwarvesH

Beginner DirectX 10 problems

Recommended Posts

DwarvesH    510

Hello everybody!

 

I'm trying to add DirectX 10 support using SharpDX to my app but I'm having problems using the Effect frameworks.

 

So I jumped over to the sample applications and tried to do some changes there. The "MiniCube " sample compiles a vertex shader and a pixel shader:

 

 

// Compile Vertex and Pixel shaders

            var vertexShaderByteCode = ShaderBytecode.CompileFromFile("MiniCube.fx", "VS", "vs_4_0");
            var vertexShader = new VertexShader(device, vertexShaderByteCode);
 
            var pixelShaderByteCode = ShaderBytecode.CompileFromFile("MiniCube.fx", "PS", "ps_4_0");
            var pixelShader = new PixelShader(device, pixelShaderByteCode);
 
            // Layout from VertexShader input signature
            var layout = new InputLayout(device, ShaderSignature.GetInputSignature(vertexShaderByteCode), new[]
                    {
                        new InputElement("POSITION", 0, Format.R32G32B32A32_Float, 0, 0),
                        new InputElement("COLOR", 0, Format.R32G32B32A32_Float, 16, 0)
                    });

 

Then it sets these values and the cube is rendering fine:

 

 

// Prepare All the stages

            context.InputAssembler.InputLayout = layout2;
            context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
            context.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(vertices, Utilities.SizeOf<Vector4>() * 2, 0));
            context.VertexShader.SetConstantBuffer(0, contantBuffer);
            context.VertexShader.Set(vertexShader);
            context.Rasterizer.SetViewports(new Viewport(0, 0, form.ClientSize.Width, form.ClientSize.Height, 0.0f, 1.0f));
            context.PixelShader.Set(pixelShader);

 

But then I tried using an Effect:

 

 

var effectByteCode = ShaderBytecode.CompileFromFile("MiniCube2.fx", "fx_4_0", ShaderFlags.None, EffectFlags.None);

            var effect10 = new Effect(device, effectByteCode);
            var technique = effect10.GetTechniqueByIndex(0);
            var pass = technique.GetPassByIndex(0);
            var passSignature = pass.Description.Signature;
 
            // Layout from VertexShader input signature
            var layout2 = new InputLayout(device, passSignature, new[]
                    {
                        new InputElement("POSITION", 0, Format.R32G32B32A32_Float, 0, 0),
                        new InputElement("COLOR", 0, Format.R32G32B32A32_Float, 16, 0)
                    });

 

 

context.InputAssembler.InputLayout = layout2;

            context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
            context.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(vertices, Utilities.SizeOf<Vector4>() * 2, 0));
            context.VertexShader.SetConstantBuffer(0, contantBuffer);
            //context.VertexShader.Set(vertexShader);
            context.Rasterizer.SetViewports(new Viewport(0, 0, form.ClientSize.Width, form.ClientSize.Height, 0.0f, 1.0f));
            //context.PixelShader.Set(pixelShader);

 

The rendering code remained the same, except for adding an Apply statement:

 

 

var a = context.VertexShader.GetConstantBuffers(0, 1);

                    pass.Apply();
                    var b = context.VertexShader.GetConstantBuffers(0, 1);
                    
                    context.Draw(36, 0);

 

The a and b variables are only there for some sanity checks. Yet this code does not render. If I change it to set the constant buffer after every apply it works:

 

 

                   var a = context.VertexShader.GetConstantBuffers(0, 1);

                    pass.Apply();
                    var b = context.VertexShader.GetConstantBuffers(0, 1);
                    context.VertexShader.SetConstantBuffer(0, contantBuffer);
                    context.Draw(36, 0);

 

Is this the correct way to use Effects or am I doing something else wrong? What are the rules here?

 

I need to get this sorted out and then move to my real app which does not work with this fix.

 

Thank you!

Share this post


Link to post
Share on other sites
gfxCahd    234

Yeah, you need to set any used buffer (vertex-instance-constant etc...) or shaderResource, topology,  as well as blend-depth-raster state every time before you call Draw.

Edited by gfxCahd

Share this post


Link to post
Share on other sites
DwarvesH    510

Thanks! I guess the pass.Apply() clobbers the buffer binding or something.

 

The learning curve for DirectX 10 is pretty steep. I'm facing often the problem of things working 99%, but not 100%.

 

Currently I'm struggling with the problem of MSAA not working. I'm setting:

SampleDescription = new SampleDescription(2, 0)

to both the swap chain descriptor and the depth buffer I create, yet AA is not active. In the debugger the descriptions have the correct value. I managed to get it to work in a small hello world app, but in my real app it is not working and I have no idea why.

Share this post


Link to post
Share on other sites
DwarvesH    510

I figured it out: it was the pass.Apply yet again!

            RasterizerStateDescription r = new RasterizerStateDescription();
            r.IsAntialiasedLineEnabled = true;
            r.IsMultisampleEnabled = true;
            r.CullMode = CullMode.Back;
            r.FillMode = FillMode.Solid;
            rs = new RasterizerState(device, r);

...


for (int i = 0; i < technique.Description.PassCount; ++i) {
                pass.Apply();
                Device.VertexShader.SetConstantBuffer(0, contantBuffer);
                Device.Rasterizer.State = rs;

                device.Draw(36, 0);
            }

Under DirectX 9 the effect framework was pretty good. I see that under 10 it seems to do more harm than good! The behavior is different enough at least to make it a sore point of the porting effort.

Share this post


Link to post
Share on other sites
DwarvesH    510

Also keep in mind that the effect framework isn't available with the SDK as of DirectX 11...

 

Thanks! I have moved past this phase. And I'm using less and less of the FX framework as the days go by, eventually phasing it out.

 

But for other reading this, I now have a clear explanation why this was happening. The FX framework assigns a hidden constant buffer (under DX10+) to all the constant in the FX file. This is completely independent from the constant buffer you create manually in code and set to be used.

 

Calling Apply will set in use this constant buffer, overriding my previous assignment. So I needed to set it back after the Apply call.

 

The moral of the story: when in DirectX 10, use either the FX framework and set FX variables or use constant buffers without the FX framework. Don't use both at the same time!

 

There is still one strange thing I have no explanation for. Calling Apply also wiped my flag that said that the primitive should be drawn with MSAA. I had to set that flag manually.

 

But I did not manage to do the jump to DirectX 10. I'm stuck with 9...

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