Search code examples
c#directx-11sharpdx

Can't create staging Texture3D


I want to create staging Texture3D and bind it to unordered access view to perform some calculations using DirectCompute and then read them with CPU. Unfortunately I got error when creating Texture3D using following description:

Texture3DDescription desc = new Texture3DDescription()
{
    BindFlags = BindFlags.UnorderedAccess,
    CpuAccessFlags = CpuAccessFlags.Read | CpuAccessFlags.Write,
    Depth = sunAngleIterations,
    Format = SharpDX.DXGI.Format.R32G32B32_Float,
    Height = viewAngleIterations,
    MipLevels = 1,
    OptionFlags = ResourceOptionFlags.None,
    Usage = ResourceUsage.Staging,
    Width = heightIterations
};

texture = new Texture3D(device, desc);

The exception thrown is:

{HRESULT: [0x80070057], Module: [General], ApiCode: [E_INVALIDARG/Invalid Arguments], Message: Parameter jest niepoprawny.}

Any ideas what's wrong here?


Solution

  • Staging textures can't be bound to the shader pipeline, so you need to create first a default texture (also not all cards support 3 channels, so I also changed the format, trying to sample 3 channels texture might not work or crash your driver)

    Texture3DDescription desc = new Texture3DDescription()
    {
        BindFlags = BindFlags.UnorderedAccess,
        CpuAccessFlags = CpuAccessFlags.None,
        Depth = sunAngleIterations,
        Format = SharpDX.DXGI.Format.R32G32B32A32_Float,
        Height = viewAngleIterations,
        MipLevels = 1,
        OptionFlags = ResourceOptionFlags.None,
        Usage = ResourceUsage.Default,
        Width = heightIterations
    };
    
    texture = new Texture3D(device, desc);
    

    Then perform your calculations and use a staging texture to retrieve the data:

    Texture3DDescription stagingdesc = new Texture3DDescription()
    {
        BindFlags = BindFlags.None,
        CpuAccessFlags = CpuAccessFlags.Read,
        Depth = sunAngleIterations,
        Format = SharpDX.DXGI.Format.R32G32B32A32_Float,
        Height = viewAngleIterations,
        MipLevels = 1,
        OptionFlags = ResourceOptionFlags.None,
        Usage = ResourceUsage.Staging,
        Width = heightIterations
    };
    
    stagingtexture = new Texture3D(device, stagingdesc);
    

    Your need to then use deviceContext.CopyResource to copy the content of your default rexture to your staging texture.

    Once done, you can use deviceContext.MapSubresource (with read flag) to access your texture data.