【问题标题】:Running a DX11 compute shader with SharpDX - cannot get results使用 SharpDX 运行 DX11 计算着色器 - 无法获得结果
【发布时间】:2017-06-03 14:57:36
【问题描述】:

我正在尝试运行计算着色器并使用 SharpDX 获取生成的纹理。

据我了解,我需要: 1. 创建一个纹理以设置为着色器的输出。 2. 将上述纹理设置为无序访问视图,以便我可以对其进行写入。 3.运行着色器 4. 将 UAV 纹理复制到暂存纹理,以便 CPU 可以访问它 5. 将暂存纹理读取到位图

问题是,无论我做什么,结果都是黑色位图。我不认为错误出在 Texture2D -> 位图转换代码中,因为直接从暂存区打印第一个像素纹理也给了我 0。

这是我的着色器代码:

RWTexture2D<float4> Output : register(u0);

[numthreads(32, 32, 1)]
void main(uint3 id : SV_DispatchThreadID) {
    Output[id.xy] = float4(0, 1.0, 0, 1.0);
}

使用 MS DX11 文档和博客,我拼凑了这段代码来运行纹理:

public class GPUScreenColor {
    private int adapterIndex = 0;

    private Adapter1 gpu;
    private Device device;
    private ComputeShader computeShader;

    private Texture2D texture;
    private Texture2D stagingTexture;
    private UnorderedAccessView view;

    public GPUScreenColor() {
        initializeDirectX();
    }

    private void initializeDirectX() {
        using (var factory = new Factory1()) {
            gpu = factory.GetAdapter1(adapterIndex);
        }

        device = new Device(gpu, DeviceCreationFlags.Debug, FeatureLevel.Level_11_1);

        var compilationResult = ShaderBytecode.CompileFromFile("test.hlsl", "main", "cs_5_0", ShaderFlags.Debug);
        computeShader = new ComputeShader(device, compilationResult.Bytecode);

        texture = new Texture2D(device, new Texture2DDescription() {
            BindFlags = BindFlags.UnorderedAccess | BindFlags.ShaderResource,
            Format = Format.R8G8B8A8_UNorm,
            Width = 1024,
            Height = 1024,
            OptionFlags = ResourceOptionFlags.None,
            MipLevels = 1,
            ArraySize = 1,
            SampleDescription = { Count = 1, Quality = 0 }
        });

        UnorderedAccessView view = new UnorderedAccessView(device, texture, new UnorderedAccessViewDescription() {
            Format = Format.R8G8B8A8_UNorm,
            Dimension = UnorderedAccessViewDimension.Texture2D,
            Texture2D = { MipSlice = 0 }
        });

        stagingTexture = new Texture2D(device, new Texture2DDescription {
            CpuAccessFlags = CpuAccessFlags.Read,
            BindFlags = BindFlags.None,
            Format = Format.R8G8B8A8_UNorm,
            Width = 1024,
            Height = 1024,
            OptionFlags = ResourceOptionFlags.None,
            MipLevels = 1,
            ArraySize = 1,
            SampleDescription = { Count = 1, Quality = 0 },
            Usage = ResourceUsage.Staging
        });
    }

    public Bitmap getBitmap() {
        device.ImmediateContext.ComputeShader.Set(computeShader);
        device.ImmediateContext.ComputeShader.SetUnorderedAccessView(0, view);

        device.ImmediateContext.Dispatch(32, 32, 1);
        device.ImmediateContext.CopyResource(texture, stagingTexture);
        var mapSource = device.ImmediateContext.MapSubresource(stagingTexture, 0, MapMode.Read, MapFlags.None);

        Console.WriteLine(Marshal.ReadInt32(IntPtr.Add(mapSource.DataPointer, 0)));

        try {
            // Copy pixels from screen capture Texture to GDI bitmap
            Bitmap bitmap = new Bitmap(1024, 1024, System.Drawing.Imaging.PixelFormat.Format32bppRgb);
            BitmapData mapDest = bitmap.LockBits(new Rectangle(0, 0, 1024, 1024), ImageLockMode.ReadWrite, bitmap.PixelFormat);

            try {
                var sourcePtr = mapSource.DataPointer;
                var destPtr = mapDest.Scan0;
                for (int y = 0; y < 1024; y++) {
                    // Copy a single line
                    Utilities.CopyMemory(destPtr, sourcePtr, 1024 * 4);

                    // Advance pointers
                    sourcePtr = IntPtr.Add(sourcePtr, mapSource.RowPitch);
                    destPtr = IntPtr.Add(destPtr, mapDest.Stride);
                }

                return bitmap;
            } finally {
                bitmap.UnlockBits(mapDest);
            }
        } finally {
            device.ImmediateContext.UnmapSubresource(stagingTexture, 0);
        }
    }
}

我对着色器很陌生,所以这可能很明显......

【问题讨论】:

  • 您是否使用 D3D11 调试(并启用了不安全调试,并检查调试 VS 输出窗口)来检查您的流程中是否有任何问题?您是否尝试过图形调试器? (如 Renderdoc)

标签: directx shader sharpdx


【解决方案1】:

首先,您将无人机创建为本地:

UnorderedAccessView view = new UnorderedAccessView(....

所以该字段为空,替换为

view = new UnorderedAccessView(....

将解决第一个问题。

其次,运行时很可能会抱怨类型(调试会给你类似的东西:

在着色器代码 (FLOAT) 中声明的组件 0 的资源返回类型与绑定到计算着色器单元 (UNORM) 的无序访问视图插槽 0 的资源类型不兼容。

有些卡可能会做某事(静默修复),有些可能什么都不做,有些可能会崩溃:)

问题是 RWTexture2D 与 UNORM 格式不匹配(因为您在此处指定扁平点格式)。

你需要强制你的 RWTexture 使用 unorm 格式,例如(是的,运行时可能很挑剔):

RWTexture2D<unorm float4> Output : register(u0);

然后你的整个设置应该可以工作(PS:我没有检查位图代码,但我加倍检查着色器运行没有错误并且第一个像素匹配)

【讨论】:

  • 我确信我错过了一些愚蠢的事情。谢谢!当我回到家(周末)时,将仔细检查这是否解决了问题,并将标记答案。与此同时,我让它在一个新项目中工作,却没有发现问题出在哪里。
猜你喜欢
  • 2022-11-16
  • 1970-01-01
  • 1970-01-01
  • 2017-03-11
  • 2011-04-24
  • 1970-01-01
  • 1970-01-01
  • 2016-09-29
  • 2014-09-13
相关资源
最近更新 更多