如何在dx11中获取计算着色器的正确输出,我使用SharpDx

How to get correct output of compute shader in dx11,I use SharpDx

提问人:ThraceShah 提问时间:8/16/2023 更新时间:8/16/2023 访问量:28

问:

            float[] buffer = new float[]{1,2,3,4,5,6,7,8,9};
            var vertexArray = MemoryMarshal.Cast<float, Vector3>(buffer).ToArray();
            var device = new Device(DriverType.Hardware, DeviceCreationFlags.Debug);
            var context = device.ImmediateContext;
            // 编译计算着色器
            var faceCsFile = Path.Combine(AppContext.BaseDirectory, "HLSL/Face_CS.hlsl");
            var shaderBytecode = ShaderBytecode.CompileFromFile(faceCsFile, "CS", "cs_5_0");
            var computeShader = new ComputeShader(device, shaderBytecode);
            shaderBytecode.Dispose();
            var inputDesc = new BufferDescription()
            {SizeInBytes = SharpDX.Utilities.SizeOf<Vector3>() * vertexArray.Length,
                Usage = ResourceUsage.Default,
                BindFlags = BindFlags.ShaderResource | BindFlags.UnorderedAccess,
                OptionFlags = ResourceOptionFlags.BufferStructured,
                StructureByteStride = SharpDX.Utilities.SizeOf<Vector3>(),};
            var verticeBuffer = Buffer.Create(device, vertexArray, inputDesc);
            device.ImmediateContext.UnmapSubresource(verticeBuffer, 0);
            var srvDesc = new ShaderResourceViewDescription()
            {Format = SharpDX.DXGI.Format.Unknown,
                Dimension = ShaderResourceViewDimension.Buffer,
                BufferEx = new ShaderResourceViewDescription.ExtendedBufferResource()
                {
                    FirstElement = 0,
                    ElementCount = vertexArray.Length,
                    Flags = ShaderResourceViewExtendedBufferFlags.None
                } };
            var vertexBufferView = new ShaderResourceView(device, verticeBuffer, srvDesc);
            context.ComputeShader.SetShaderResource(0, vertexBufferView);
            // 将输入和输出缓冲区绑定到计算着色器上
            context.ComputeShader.Set(computeShader);
            var dataOut = new Vector3[vertexArray.Length];
            var outDes = new BufferDescription()
            {SizeInBytes = SharpDX.Utilities.SizeOf<Vector3>() * vertexArray.Length,
                Usage = ResourceUsage.Default,
                BindFlags = BindFlags.UnorderedAccess,
                OptionFlags = ResourceOptionFlags.BufferStructured,
                StructureByteStride = SharpDX.Utilities.SizeOf<Vector3>(),};
            var bufferOut = Buffer.Create(device, dataOut, outDes);
            // 创建用于指定着色器输出的UAV
            var uavDesc = new UnorderedAccessViewDescription()
            {Format = SharpDX.DXGI.Format.Unknown,
                Dimension = UnorderedAccessViewDimension.Buffer,
                Buffer = new UnorderedAccessViewDescription.BufferResource()
                {ElementCount = vertexArray.Length,}};
            var bufferOutView = new UnorderedAccessView(device, bufferOut, uavDesc);
            context.ComputeShader.SetUnorderedAccessView(0, bufferOutView);
            int count = (vertexArray.Length + 1023) / 1024;
            context.Dispatch(count, 1, 1);// 启动计算着色器
            var stagingBuffer = new Buffer(device, new BufferDescription
            {BindFlags = BindFlags.None,
                CpuAccessFlags = CpuAccessFlags.Read,
                OptionFlags = ResourceOptionFlags.None,
                SizeInBytes = dataOut.Length * SharpDX.Utilities.SizeOf<Vector3>(),
                Usage = ResourceUsage.Staging});// 创建一个暂存缓冲区
            context.CopyResource(bufferOut, stagingBuffer);// 将输出缓冲区的内容复制到暂存缓冲区中
            // 将暂存缓冲区映射到内存中
            var dataBox = context.MapSubresource(stagingBuffer, 0, MapMode.Read, SharpDX.Direct3D11.MapFlags.None);
            Span<Vector3> result;
            unsafe{result = new Span<Vector3>((void*)dataBox.DataPointer, dataOut.Length);}// 读取数据
            context.UnmapSubresource(stagingBuffer, 0);// 取消映射
            foreach (var vec in result.ToArray())
                Console.WriteLine(vec);

StructuredBuffer<float3> Vertex : register(t0);
RWBuffer<float3> Out : register(u0);

[numthreads(1024, 1, 1)]
void CS(uint3 DTid : SV_DispatchThreadID)
{
    uint id = DTid.x;
    Out[id]=Vertex[id].yyy;
}

我相信正确的输出应该是“{2,2,2},{5,5,5},{8,8,8}”,但我得到的结果是“{2,5,8},{0,0,0},{0,0,0}”。你能帮我指出错误发生的位置吗? 当我将 hlsl 输出从 yyy 修改为 xyz 时,我获得了结果 {1,4,7}, {0,0,0}, {0,0,0}。因此,我认为计算着色器的输入和计算结果是正确的,但是在从GPU获取结果时遇到了错误,但是找不到错误。

C# DirectX-11 SharpDX 计算着色器 DirectCompute

评论

1赞 PMF 8/16/2023
您提供的代码中有很多不必要的噪音。你能把代码简化为实际进行计算的部分吗?
0赞 JonasH 8/16/2023
您知道 SharpDX 自 2019 年以来一直没有维护吗?围绕未维护的库构建新代码似乎不是一个好主意。

答: 暂无答案