Directx 使用SharpDX运行DX11计算着色器-无法获得结果

Directx 使用SharpDX运行DX11计算着色器-无法获得结果,directx,shader,sharpdx,Directx,Shader,Sharpdx,我正在尝试运行一个计算着色器,并使用SharpDX获得结果纹理 根据我的理解,我需要: 1.创建要设置为着色器输出的纹理。 2.将上面的纹理设置为无序访问视图,以便我可以对其进行写入。 3.运行着色器 4.将UAV纹理复制到暂存纹理,以便CPU可以访问该纹理 5.将暂存纹理读取到位图 问题是,无论我做什么,结果都是黑色位图。我认为错误不在Texture2D->位图转换代码中,因为直接从暂存纹理打印第一个像素也会给我0 这是我的着色器代码: RWTexture2D<float4> Ou

我正在尝试运行一个计算着色器,并使用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);
}
rwd输出:寄存器(u0);
[numthreads(32,32,1)]
空干管(uint3 id:SV_DispatchThreadID){
输出[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);
        }
    }
}
公共类GPUScreenColor{
专用int适配器索引=0;
专用适配器1 gpu;
专用设备;
私有计算hader ComputeShader;
私有纹理2D纹理;
私有纹理2D阶段性纹理;
私有无序访问视图;
公共GPUScreenColor(){
initializeDirectX();
}
private void initializeDirectX(){
使用(var factory=new Factory1()){
gpu=factory.GetAdapter1(adapterIndex);
}
设备=新设备(gpu、DeviceCreationFlags.Debug、FeatureLevel.Level_11_1);
var compilationResult=ShaderBytecode.CompileFromFile(“test.hlsl”、“main”、“cs_5_0”、ShaderFlags.Debug);
computeShader=新的computeShader(设备、编译结果、字节码);
纹理=新纹理2d(设备,新纹理2ddescription(){
BindFlags=BindFlags.UnorderedAccess | BindFlags.ShaderResource,
Format=Format.R8G8B8A8_UNorm,
宽度=1024,
高度=1024,
OptionFlags=ResourceOptionFlags.None,
MIP级别=1,
ArraySize=1,
SampleDescription={Count=1,Quality=0}
});
UnorderedAccessView视图=新建UnorderedAccessView(设备、纹理、新建UnorderedAccessViewDescription(){
Format=Format.R8G8B8A8_UNorm,
维度=无序访问视图维度.Texture2D,
Texture2D={MipSlice=0}
});
stagingTexture=新纹理2D(设备,新纹理2D说明{
CpuAccessFlags=CpuAccessFlags.Read,
BindFlags=BindFlags.None,
Format=Format.R8G8B8A8_UNorm,
宽度=1024,
高度=1024,
OptionFlags=ResourceOptionFlags.None,
MIP级别=1,
ArraySize=1,
SampleDescription={Count=1,Quality=0},
用法=ResourceUsage.Staging
});
}
公共位图getBitmap(){
device.ImmediateContext.ComputeShader.Set(ComputeShader);
device.ImmediateContext.ComputeShader.SetUnorderedAccessView(0,视图);
设备.ImmediateContext.Dispatch(32,32,1);
device.ImmediateContext.CopyResource(纹理,StaginTexture);
var mapSource=device.ImmediateContext.MapSubresource(staginTexture,0,MapMode.Read,MapFlags.None);
Console.WriteLine(Marshal.ReadInt32(IntPtr.Add(mapSource.DataPointer,0));
试一试{
//将屏幕捕获纹理中的像素复制到GDI位图
位图位图=新位图(1024,1024,System.Drawing.Imaging.PixelFormat.Format32bppRgb);
BitmapData mapDest=位图.LockBits(新矩形(0,0,1024,1024),ImageLockMode.ReadWrite,bitmap.PixelFormat);
试一试{
var sourcePtr=mapSource.DataPointer;
var destPtr=mapDest.Scan0;
对于(int y=0;y<1024;y++){
//复制一行
CopyMemory(destPtr,sourcePtr,1024*4);
//前进指针
sourcePtr=IntPtr.Add(sourcePtr,mapSource.RowPitch);
destPtr=IntPtr.Add(destPtr,mapDest.Stride);
}
返回位图;
}最后{
位图.解锁位(mapDest);
}
}最后{
device.ImmediateContext.UnmassubreSource(StaginTexture,0);
}
}
}

我对着色器非常陌生,所以这可能是显而易见的…

首先,您将UAV创建为本地:

UnorderedAccessView view = new UnorderedAccessView(....
因此,该字段为null,替换为

view = new UnorderedAccessView(....
将解决第一个问题

其次,运行时很可能会抱怨类型(debug会给您一些类似于:

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

有些卡可能会做些什么(悄悄地修复它),有些卡可能什么也不做,有些卡可能会崩溃:)

问题是RWTexture2D与UNORM格式不匹配(正如您在此处指定的展平点格式)

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

rwd输出:寄存器(u0);

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

您是否在D3D11调试(启用不安全调试,并检查调试与输出窗口)的情况下运行,以检查流中是否没有错误?你试过图形调试器吗?(像Renderdoc)我确信我错过了一些愚蠢的事情。非常感谢。当我回家(周末)时,我会再次检查这是否解决了问题,并标记答案。与此同时,我让它在一个新项目中工作,却没有发现问题所在。
RWTexture2D<unorm float4> Output : register(u0);