Jump to content
  • Advertisement
Sign in to follow this  
belfegor

DX11 GPU write - CPU read

Recommended Posts

For example, in deferred renderer, in pixel shader  i would like to write distance from camera to pixel (read from g-buffer R32F texture) at current cursor position.

What kind of buffers i could use (if any, except render targets) and how to setup those to be able to access that value on CPU side? 

With google i couldn't find any example code, and i don't know with what keywords to search properly.

I tried to write some code, but i am stuck as don't know what is correct "semantic" for shader code side:

c++

struct MyStruct
	{
		vec4 myData;
	};

...

std::memset(&buffDesc, 0, sizeof(buffDesc));
	buffDesc.Usage = D3D11_USAGE_DEFAULT;
	buffDesc.ByteWidth = sizeof(MyStruct);
	buffDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
	buffDesc.CPUAccessFlags = 0;

	hr = dev->CreateBuffer(&buffDesc, nullptr, &m_writeBuffer);
	if (FAILED(hr))
	{
		...
	}

	std::memset(&buffDesc, 0, sizeof(buffDesc));
	buffDesc.Usage = D3D11_USAGE_STAGING;
	buffDesc.ByteWidth = sizeof(MyStruct);
	buffDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
	buffDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;

	hr = dev->CreateBuffer(&buffDesc, nullptr, &m_readBuffer);
	if (FAILED(hr))
	{
		...
	}

...

//after drawing
Context->CopyResource(m_readBuffer, m_writeBuffer);
	MyStruct s;
	D3D11_MAPPED_SUBRESOURCE ms;
	Context->Map(m_readBuffer, 0, D3D11_MAP_READ, 0, &ms);
	s.myData = *(vec4*)ms.pData;
	Context->Unmap(m_readBuffer, 0);
... // use myData

hlsl

??? MyStruct : register(???)
{
    float4 myData;
};

void PixelShader(...)
{
    ...
    myData = something;
    ...
}

 

Share this post


Link to post
Share on other sites
Advertisement

You are better off using a compute shader for that. Once you have render all your gbuffer, you can run the compute with a Dispatch(1,1,1);, using a RWStructuredBuffer<MyData> type in it, read from your GBuffer texture ( The depth buffer is enough to rebuild the position from depth btw ). To write a general purpose buffer on the GPU, it has to have a binding of D3D11_BIND_UNORDERED_ACCESS.

 

I also recommend you to use a ID3D11Query to monitor the GPU execution of the Copy, and only do the Map once you know the GPU is done, or you would get bad CPU/GPU serialization.

Share this post


Link to post
Share on other sites

If you want an example of what galop1n is suggesting, you can check out this shader code. It also pulls out the tangent frame from the G-Buffer since that code was used for placing decals, so you can ignore that bit and just look at the part that computes and stores the position.

On the C++ side of things, you'll want to create a 1-element structured buffer with stride == sizeof(float3), with UAV access. You'll also need a nearly-identical buffer with D3D11_USAGE_STAGING that you'll use as your readback buffer. The basic process goes like this:

  1. Render your G-Buffer
  2. Dispatch your compute shader to grab depth and write position to your UAV buffer
  3. Use CopyResource to copy the data from your UAV buffer to your staging buffer
  4. Wait until at least the next frame (this part is important if you don't want to stall the CPU and GPU like galop1n mentioned, but you can skip the wait when you're just testing if it works, or if you're okay with having a big stall). Like galop1n explained you can use a query if you want to know for sure that calling Map won't stall.
  5. Map your staging buffer and get the data that you need

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
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!