MyAccount
MyAccount

Reputation: 1

SharpDX Constant/Texture Buffers Don't Work

I've been trying to get the constant/texture buffers to work in SharpDX (it's just like SlimDX), but the data I put in it doesn't seem to get into the shaders.

I've looked up how to do it and followed examples but I just can't get it to work.

Ultimately I will need to be able to input multiple large arrays of various data types into my shaders, so if anyone can give me a working example that can do that, it would be great!

But for now I've written a simple example that I've tried to test, and I just can't get it to work. Usually I can at least get something to display when I draw a triangle but right now it won't even do that.

That's probably a silly mistake I overlooked, but anyway, if someone could just take a look at it and point out what's wrong, or better yet, fix it and post the updated code (it is complete and should compile).

I'm sorry if the code is long but I tried to make it as simple as possible. Anyway, here it is:

using SharpDX;
using SharpDX.Direct3D;
using SharpDX.Direct3D11;
using SharpDX.DXGI;
using SharpDX.Windows;
using SharpDX.D3DCompiler;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace test_namespace
{
    class Test
    {
        [StructLayout(LayoutKind.Explicit, Size = 80, Pack = 16)]
        public struct Data
        {
            [FieldOffset(0)]
            public Matrix mat;
            [FieldOffset(64)]
            public Vector4 testColor;
        }

        [StructLayout(LayoutKind.Explicit)]
        public struct Point
        {
            [FieldOffset(0)]
            public Vector4 pos;
            [FieldOffset(16)]
            public Vector2 tex;
        }

        int width = 1000;
        int height = 1000;
        const int vertSize = 6 * sizeof(float);
        RenderForm form;
        PictureBox pic;
        SharpDX.Direct3D11.Device dev;
        DeviceContext dc;
        SwapChainDescription scd;
        SwapChain sc;
        RasterizerStateDescription rsd;
        RasterizerState rs;
        Viewport vp;
        Texture2DDescription depthDesc;
        DepthStencilView dsv;
        RenderTargetView rtv;
        SharpDX.Direct3D11.Buffer buffer;
        InputLayout il;
        VertexShader vs;
        ShaderBytecode vsCode;
        PixelShader ps;
        ShaderBytecode psCode;
        Matrix view;
        Matrix proj;
        Matrix mat;
        Data data;
        DataStream pointStream;
        SharpDX.Direct3D11.Buffer pointBuffer;

        public Test()
        {
            init();
            initMat();

            data.testColor = new Vector4(1.0f, 0.5f, 0.25f, 0.0f);

            string code = "struct vert { float4 pos : POSITION; float2 tex : TEXCOORD; };\n"
              + "struct pix { float4 pos : SV_POSITION; float2 tex : TEXCOORD; };\n"
              + "cbuffer buf1 : register(b0) { float4x4 mat; float4 testColor; }\n"
              + "pix VS(vert vertIn) { pix pixOut = (pix)0; pixOut.pos = mul(vertIn.pos, mat); pixOut.tex = vertIn.tex; return pixOut; }\n"
              + "float4 PS(pix pixIn) : SV_Target { return testColor; }";

            vsCode = ShaderBytecode.Compile(code, "VS", "vs_5_0");
            vs = new VertexShader(dev, vsCode);
            psCode = ShaderBytecode.Compile(code, "PS", "ps_5_0");
            ps = new PixelShader(dev, psCode);

            dc.VertexShader.Set(vs);
            dc.PixelShader.Set(ps);

            il = new InputLayout(dev, ShaderSignature.GetInputSignature(vsCode),
              new InputElement[] {new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0),
              new InputElement("TEXCOORD", 0, Format.R32G32_Float, 16, 0)});

            dc.InputAssembler.InputLayout = il;
            dc.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;

            updateBuffer();

            RenderLoop.Run(form, () =>
            {
                dc.ClearDepthStencilView(dsv, DepthStencilClearFlags.Depth, 1.0f, 0);
                dc.ClearRenderTargetView(rtv, Color4.Black);
                float dist = 10.0f;
                draw(new Vector3(-dist, -dist, dist), Vector2.Zero, new Vector3(-dist, dist, dist), Vector2.UnitY,
                  new Vector3(dist, dist, dist), Vector2.One);
            });
        }

        void init()
        {
            form = new RenderForm();
            form.ClientSize = new System.Drawing.Size(width, height);
            form.BackColor = System.Drawing.Color.Black;
            form.FormClosed += form_FormClosed;
            pic = new PictureBox();
            pic.Location = new System.Drawing.Point(0, 0);
            pic.Size = new Size(width, height);
            pic.Show();
            form.Controls.Add(pic);

            scd = new SwapChainDescription();
            scd.BufferCount = 1;
            scd.Flags = SwapChainFlags.AllowModeSwitch;
            scd.IsWindowed = true;
            scd.ModeDescription = new ModeDescription(width, height, new Rational(60, 1), Format.R8G8B8A8_UNorm);
            scd.OutputHandle = pic.Handle;
            scd.SampleDescription = new SampleDescription(1, 0);
            scd.SwapEffect = SwapEffect.Discard;
            scd.Usage = Usage.RenderTargetOutput;

            rsd = new RasterizerStateDescription();
            rsd.CullMode = CullMode.None;
            rsd.DepthBias = 0;
            rsd.DepthBiasClamp = 0;
            rsd.FillMode = FillMode.Solid;
            rsd.IsAntialiasedLineEnabled = true;
            rsd.IsDepthClipEnabled = true;
            rsd.IsFrontCounterClockwise = false;
            rsd.IsMultisampleEnabled = true;
            rsd.IsScissorEnabled = false;
            rsd.SlopeScaledDepthBias = 0;

            SharpDX.Direct3D11.Device.CreateWithSwapChain(DriverType.Hardware, DeviceCreationFlags.Debug, scd, out dev, out sc);
            rs = new RasterizerState(dev, rsd);
            vp = new Viewport(0, 0, width, height, 0.0f, 1.0f);
            dc = dev.ImmediateContext;
            dc.Rasterizer.State = rs;
            dc.Rasterizer.SetViewports(vp);

            depthDesc = new Texture2DDescription();
            depthDesc.ArraySize = 1;
            depthDesc.BindFlags = BindFlags.DepthStencil;
            depthDesc.CpuAccessFlags = CpuAccessFlags.None;
            depthDesc.Format = Format.D32_Float_S8X24_UInt;
            depthDesc.Height = height;
            depthDesc.MipLevels = 1;
            depthDesc.OptionFlags = ResourceOptionFlags.None;
            depthDesc.SampleDescription = new SampleDescription(1, 0);
            depthDesc.Usage = ResourceUsage.Default;
            depthDesc.Width = width;

            dsv = new DepthStencilView(dev, new Texture2D(dev, depthDesc));
            rtv = new RenderTargetView(dev, (SharpDX.Direct3D11.Resource)SharpDX.Direct3D11.Resource.FromSwapChain<Texture2D>(sc, 0));
            dc.OutputMerger.SetTargets(dsv, rtv);

            buffer = new SharpDX.Direct3D11.Buffer(dev, Marshal.SizeOf(typeof(Data)),
              ResourceUsage.Default, BindFlags.ConstantBuffer, CpuAccessFlags.None, ResourceOptionFlags.None, 0);
            dc.VertexShader.SetConstantBuffer(0, buffer);
        }

        void initMat()
        {
            view = Matrix.LookAtLH(Vector3.Zero, Vector3.UnitZ, Vector3.UnitY);
            proj = Matrix.PerspectiveFovLH((float)Math.PI / 4.0f, (float)width / (float)height, 0.001f, 10000.0f);
            mat = view * proj;
            mat.Transpose();
            data.mat = mat;
        }

        void updateBuffer()
        {
            dc.UpdateSubresource<Data>(ref data, buffer);
        }

        public void draw(Vector3 p1, Vector2 t1, Vector3 p2, Vector2 t2, Vector3 p3, Vector2 t3)
        {
            Vector3[] p = new Vector3[3] {p1, p2, p3};
            Vector2[] t = new Vector2[3] {t1, t2, t3};
            Point[] points = new Point[3];
            for(int i = 0; i < 3; i++)
            {
                points[i] = new Point();
                points[i].pos = new Vector4(p[i].X, p[i].Y, p[i].Z, 1.0f);
                points[i].tex = new Vector2(t[i].X, t[i].Y);
            }
            using(pointStream = new DataStream(vertSize * 3, true, true))
            {
                pointStream.WriteRange<Point>(points);
                using(pointBuffer = new SharpDX.Direct3D11.Buffer(dev, pointStream, vertSize * 3,
                  ResourceUsage.Default, BindFlags.VertexBuffer, CpuAccessFlags.None, ResourceOptionFlags.None, 0))
                {
                    dc.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
                    dc.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(pointBuffer, vertSize, 0));
                    dc.Draw(3, 0);
                }
            }
        }

        void form_FormClosed(object sender, FormClosedEventArgs e)
        {
            buffer.Dispose();
            il.Dispose();
            ps.Dispose();
            psCode.Dispose();
            vs.Dispose();
            vsCode.Dispose();
            rtv.Dispose();
            dsv.Dispose();
            dc.ClearState();
            dc.Flush();
            dc.Dispose();
            dev.Dispose();
            sc.Dispose();
        }
    }
}

Also, here is the shader code formatted in a more readable way:

struct vert
{
    float4 pos : POSITION;
    float2 tex : TEXCOORD;
};

struct pix
{
    float4 pos : SV_POSITION;
    float2 tex : TEXCOORD;
};

cbuffer buf1 : register(b0)
{
    float4x4 mat;
    float4 testColor;
}

pix VS(vert vertIn)
{
    pix pixOut = (pix)0;
    pixOut.pos = mul(vertIn.pos, mat);
    pixOut.tex = vertIn.tex;
    return out;
}

float4 PS(pix pixIn) : SV_Target
{
    return testColor;
}

Upvotes: 0

Views: 530

Answers (1)

Goodies
Goodies

Reputation: 2069

I'm not sure if this is of any help here, but why go UpdateSubresource in your updateBuffer()? In the SharpDXTutorial/Tutorial16 (the cubemap example) the buffer is initialized with the "device" object,

device.UpdateData<Data>(dataConstantBuffer, sceneInformation);

This is a very handy object. It is contained in SharpHelper, part of SharpDXTutorial,

https://github.com/RobyDX/SharpDX_Demo/blob/master/SharpDXTutorial/SharpHelper/SharpHelper.csproj

.. maybe it takes care of stuff missed, to update the constant buffer?

Upvotes: 0

Related Questions