1

I'd like to implement color picking in DirectX 12. So basically what I am trying to do is render to two render targets simultaneously. The first render target should contain the normal rendering, while the second should contain the objectID.

To render to two render targets, I think all you need to do is set them with OMSetRenderTargets.

Question 1: How do you specify which shader or pipeline state object should be used for a specific render target? Like how do you say render_target_0 should be rendered with shader_0, render_target_1 should be rendered with shader_1?

Question 2: How do you read a pixel from the frame buffer after it has been rendered? Is it like in DirectX 11 by using CopySubresourceRegion then Map? Do you need to use a readback heap? Do you need to use a resource barrier or fence or some sort synchronisation primitive to avoid the CPU and GPU using the frame buffer resource at the same time?

I tried googling for the answers but didn't get very far because DirectX 12 is pretty new and there aren't a lot of examples, tutorials, or open source projects for DirectX 12 yet.

Thanks for your help in advance.

Extra special bonus points for code examples.

0xfeedbacc
  • 301
  • 2
  • 9

1 Answers1

4

Since I didn't get any response on Stack Overflow, I cross-posted on gamedev.net and got a good response there: http://www.gamedev.net/topic/674529-d3d12-color-picking-questions/

For anyone finding this in the future, I'll just copy red75prime's answer from the GameDev forums here.

red75prime's answer:

Question 1 is not specific to D3D12. Use one pixel shader with multiple outputs. Rendering to multiple textures with one pass in directx 11

Questions 2. Yes to all.

Pseudocode:

ID3D12GraphicsCommandList *gl = ...;
ID3D12CommandQueue *gqueue = ...;
ID3D12Resource *render_target, *read_back_texture;

...
// Draw scene
gl->DrawInstanced(...); 
// Make ready for copy
gl->ResourceBarrier(render_target, RENDER_TARGET, COPY_SOURCE);
//gl->ResourceBarrier(read_back_texture, GENERIC_READ, COPY_DEST);
// Copy
gl->CopyTextureRegion(...);
// Make render_target ready for Present(), read_back_texture for Map()
gl->ResourceBarrier(render_target, COPY_SOURCE, PRESENT);
//gl->ResourceBarrier(read_back_texture, COPY_DEST, GENERIC_READ);
gl->Close(); // It's easy to forget

gqueue->ExecuteCommandLists(gl);
// Instruct GPU to signal when command list is done.
gqueue->Signal(fence, ...); 
// Wait until GPU completes drawing
// It's inefficient. It doesn't allow GPU and CPU work in parallel.
// It's here just to make example simple.
wait_for_fence(fence, ...);

// Also, you can map texture once and store pointer to mapped data.
read_back_texture->Map(...);
// Read texture data
...
read_back_texture->Unmap();

EDIT: I added "gl->Close()" to the code.

EDIT2: State transitions for read_back_texture are unnecessary. Resources in read-back heap must always have state COPY_DEST.

Community
  • 1
  • 1
0xfeedbacc
  • 301
  • 2
  • 9