0
votes

I'm trying to draw a single triangle on-screen using SharpDX (DX11). For whatever reason, the triangle only seems to be drawn every second frame. My device initialization code looks like this:

public void Init()
    {
        renderForm = new RenderForm(Engine.GameTitle);
        renderForm.ClientSize = new Size(Engine.Settings.Screen.Width, Engine.Settings.Screen.Height);
        renderForm.MaximizeBox = false;

        var desc = new SwapChainDescription()
        {
          BufferCount = 2,
          ModeDescription = new ModeDescription(renderForm.ClientSize.Width, renderForm.ClientSize.Height, new Rational(60, 1), Format.R8G8B8A8_UNorm),
          IsWindowed = true,
          OutputHandle = renderForm.Handle,
          SampleDescription = new SampleDescription(1, 0),
          SwapEffect = SwapEffect.Sequential,
          Usage = Usage.RenderTargetOutput
        };  

        Device.CreateWithSwapChain(DriverType.Hardware, DeviceCreationFlags.Debug, desc, out device, out swapChain);
        deviceContext = device.ImmediateContext;  

        var factory = swapChain.GetParent<Factory>();
        factory.MakeWindowAssociation(renderForm.Handle, WindowAssociationFlags.IgnoreAll); 

        backBuffer = Texture2D.FromSwapChain<Texture2D>(swapChain, 0);
        renderView = new RenderTargetView(device, backBuffer);

        backBuffer.Dispose();

        deviceContext.OutputMerger.SetTargets(renderView);

        deviceContext.Rasterizer.SetViewports(new Viewport(0, 0, renderForm.ClientSize.Width, renderForm.ClientSize.Height, 0.0f, 1.0f));

        ProjectionMatrix = Matrix.PerspectiveFovLH(
            (float)(Math.PI / 4),
            (float)(renderForm.ClientSize.Width / renderForm.ClientSize.Height),
            nearPlane,
            farPlane);

        WorldMatrix = Matrix.Identity;

        renderForm.Location = new Point(Screen.PrimaryScreen.Bounds.Width / 2 - Engine.Settings.Screen.Width / 2, Screen.PrimaryScreen.Bounds.Height / 2 - Engine.Settings.Screen.Height / 2);
    }

The code for rendering the triangle looks like this:

public void Render()
{
    DeviceContext context = D3DRenderer.Instance.GetDevice().ImmediateContext;

    context.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(VertexBuffer, Utilities.SizeOf<Vertex>(), 0));
    context.InputAssembler.SetIndexBuffer(IndexBuffer, Format.R32_UInt, 0);
    context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
}

public void RenderShader(int indexCount)
{
    device.ImmediateContext.DrawIndexed(indexCount, 0, 0);
}

Whereas Render() is called before RenderShader(). There's no error message returned by any function except for an Direct3D warning:

D3D11: WARNING: ID3D11DeviceContext::DrawIndexed: The size of the Constant Buffer at slot 0 of the Vertex Shader unit is too small (64 bytes provided, 192 bytes, at least, expected).

My MatrixBuffer structure looks like the following:

[StructLayout(LayoutKind.Sequential)]
internal struct MatrixBuffer
{
    public Matrix world;
    public Matrix view;
    public Matrix projection;
}

I have been clearing the backbuffer every other frame with a different color to make sure it's not an issue with not correctly swapping the backbuffer. This is working fine.

I am quite baffled as to why this isn't working right now. I hope anyone knows an answer to this.

1
You probably specify the wrong constant buffer size. Check this. However, I doubt that this is the cause for your problem. Do you have more than one Present calls within the render loop?Nico Schertler
In fact, I did. I changed it and the warning disappeared. However, as you guessed, this wasn't the cause of the issue. As for present() -Calls, nope, just one. Right now I'm at the point where I have reverted every single line of code I adjusted from a rastertek tutorial I read. The tutorial's code is working fine, mine (which is the same, line by line) in another solution isn't.. I'll try and use the tutorial as a base for transferring over my own code now and see when exactly the error will pop up.Philipp Christoph

1 Answers

1
votes

Ladies and gentleman, learn a lesson today.. Never copy and paste tutorial code. Ever. Turns out the issue was in the shader rendering code. The tutorial I copied the declarations from (and didn't post on here, otherwise it might've been pretty obvious to you guys) had the world/view/projection matrices declared as follows:

public Matrix WorldMatrix { get; private set; }

Then I tried to do this:

D3DRenderer.Instance.WorldMatrix.Transpose();

Which for now obvious reasons doesn't work. Interestingly it did seem to work every other frame. Why that is I have no idea. But after changing the matrix definitions from private set to set everything is now working fine.