【问题标题】:SharpDX Constant/Texture Buffers Don't WorkSharpDX 常量/纹理缓冲区不起作用
【发布时间】:2016-02-03 21:13:43
【问题描述】:

我一直试图让常量/纹理缓冲区在 SharpDX 中工作(它就像 SlimDX),但我放入其中的数据似乎没有进入着色器。

我已经查看了如何做到这一点并遵循了示例,但我无法让它发挥作用。

最终我需要能够将多个不同数据类型的大型数组输入到我的着色器中,所以如果有人能给我一个可以做到这一点的工作示例,那就太好了!

但是现在我已经编写了一个简单的示例,我已经尝试过测试,但我无法让它工作。通常,当我绘制三角形时,我至少可以显示一些东西,但现在它甚至不会这样做。

这可能是我忽略的一个愚蠢的错误,但无论如何,如果有人可以看看它并指出哪里出了问题,或者更好的是,修复它并发布更新的代码(它是完整的并且应该编译)。

如果代码很长,我很抱歉,但我尽量使它尽可能简单。无论如何,这里是:

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();
        }
    }
}

另外,这里的着色器代码以更易读的方式格式化:

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;
}

【问题讨论】:

  • 使用像renderdoc.org这样的图形调试器或集成在VS2013+中的调试器来调试这个
  • 我会看看我是否可以,但我对此一无所知,也不知道如何设置它。有人不能看看代码有什么问题吗?或者更好的是,如果有人有一个工作源代码示例指向我可以下载或复制文本并使用,它将数组数据输入到常量/纹理缓冲区中,那将是非常出色的!理想情况下,我希望在星期六之前完成,否则我要到下周末才能完成,我很着急。谢谢。
  • 另外,如果我错了,请纠正我,但如果我调试,那是在着色器内部对吧?所以它不会只是告诉我数据一旦存在就在做什么,而不是告诉我为什么当它应该是其他数字时它全部初始化为 0?看来 C# 一定有问题。
  • Point 结构还需要一个Size

标签: arrays shader sharpdx


【解决方案1】:

我不确定这在这里是否有任何帮助,但为什么要在您的updateBuffer() 中使用UpdateSubresource?在 SharpDXTutorial/Tutorial16(立方体贴图示例)中,缓冲区使用“设备”对象进行初始化,

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

这是一个非常方便的对象。它包含在 SharpHelper 中,是 SharpDXTutorial 的一部分,

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

.. 也许它会处理遗漏的东西,更新常量缓冲区?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-06
    • 1970-01-01
    • 2014-12-05
    • 1970-01-01
    • 1970-01-01
    • 2023-01-28
    相关资源
    最近更新 更多