Jump to content
  • Advertisement
Sign in to follow this  
MysteryX

ComputeShader: How to Read Output

This topic is 890 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm trying to figure out how DirectCompute works, with Texture2D as input and output. Setting the input textures is pretty straightforward.

 

But how do I get the output Texture2D from the DeviceContext?

 

 

I found this in a DirectCompute sample, and I'm not sure what makes it read the output, or how to do it with a Texture2D.

ID3D11Buffer* CreateAndCopyToDebugBuf( ID3D11Device* pDevice, ID3D11DeviceContext* pd3dImmediateContext, ID3D11Buffer* pBuffer )
{
    ID3D11Buffer* debugbuf = nullptr;

    D3D11_BUFFER_DESC desc;
    ZeroMemory( &desc, sizeof(desc) );
    pBuffer->GetDesc( &desc );
    desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
    desc.Usage = D3D11_USAGE_STAGING;
    desc.BindFlags = 0;
    desc.MiscFlags = 0;
    if ( SUCCEEDED(pDevice->CreateBuffer(&desc, nullptr, &debugbuf)) )
    {
        pd3dImmediateContext->CopyResource( debugbuf, pBuffer );
    }

    return debugbuf;
}

Share this post


Link to post
Share on other sites
Advertisement

Textures (and Buffers) created with the D3D11_USAGE_STAGING flag can be read/written by the CPU whereas D3D11_USAGE_DEFAULT resources cannot.

 

The first step (as shown in the code snippet above) is to get the GPU to copy the data from the Texture2D it used as output for your Compute Shader operation into another Texture2D of matching size and format with the D3D11_USAGE_STAGING flag as well as D3D11_CPU_ACCESS_READ for the CPUAccessFlags.

 

You're then able to call 'Map' on the immediate context to obtain a pointer to the data in the STAGING texture, which you just read like you would any other piece of memory pointed to by a pointer.

 

eg:

D3D11_MAPPED_SUBRESOURCE mappedData;
HRESULT hr = context->Map(pStagingTexture, 0, D3D11_MAP_READ, 0, &mappedData);

// Read from mappedData.pData 

context->Unmap(pStagingTexture, 0)

If this is purely for debug purposes or non-realtime applications (eg, Games) then there's no problem. However, if you intend to do this sort of thing every few milliseconds then you need to be aware that you will be causing the GPU to flush all its commands before you can map the STAGING texture and start reading the output; this is not a good thing to do in a game.

Edited by Adam Miles

Share this post


Link to post
Share on other sites

The first step (as shown in the code snippet above) is to get the GPU to copy the data from the Texture2D it used as output

 

This is the part I'm trying to figure out. How do I define an output texture?

Share this post


Link to post
Share on other sites

It depends what you mean by "output texture". Compute Shaders have Unordered Access Views bound to them, which can act as input, output or both at the same time. Have you actually written a Compute Shader that does useful work and writes its output?

Share this post


Link to post
Share on other sites

I don't write the shaders; I want to run them. Here's one.

https://github.com/zachsaw/MPDN_Extensions/blob/master/Extensions/RenderScripts/Super-xBR/super-xbr.hlsl

 

I already have implemented the solution with DX9 but that doesn't support PS_5_0. I thought this was PS_5_0 because of the STRUCT inputs, but after looking back with the author, it is PS_3_0. Just to be sure, can I run PS_3_0 shaders like this one with DX11?

Share this post


Link to post
Share on other sites

I'm not sure how we've gone from talking about DirectCompute to pixel shaders.

 

You can run old-style shaders, yes, you just need to pass /Gec to the shader compiler to enable backwards compatibility mode.

Share this post


Link to post
Share on other sites

With DX9, I have to use PixelShaders and rasterize against a rendertarget before reading the data from the GPU back into memory. With DX11, DirectCompute allow running the same and "should" be more straightforward. Unless I'm missing something? Except that I have to replace the RenderTarget with "something else"

Edited by MysteryX

Share this post


Link to post
Share on other sites

Yes, Compute Shaders write to "Unordered Access Views" rather than "Render Target Views". Create a texture for output as you would normally but instead of creating a Render Target View, create an Unordered Access View instead and set it with CSSetUnorderedAccessViews.

 

The following is an example of a simple Compute Shader that writes red to a Texture2D via an Unordered Access View:

RWTexture2D<float4> outputTex : register(u0);

[numthreads(8,8,1)]
void main(uint3 DTid : SV_DispatchThreadID)
{
	outputTex[DTid.xy] = float4(1, 0, 0, 1); // Red
}

Share this post


Link to post
Share on other sites

Oh. Does the HLSL code have to be written differently for this to work?

 

I don't have "register(u0)" in the PS_3_0 code

Share this post


Link to post
Share on other sites

There's no such thing as Shader Model 3 Compute Shaders. You will need the shaders to be written using CS_5_0.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!