[D3D12] Color Picking Questions

Started by
3 comments, last by Fresa 7 years, 9 months ago

I posted these questions questions on Stack Overflow, but I didn't get any response yet and not many views, so I figured I would cross-post here, hoping to have better luck.

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.

Advertisement

Question 1 is not specific to D3D12. Use one pixel shader with multiple outputs. http://stackoverflow.com/questions/12730309/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.

Thanks a lot red75prime, your answers are very helpful. I will try this out.

Thanks again red75prime, I tried out your procedure and it worked very nicely.

How did you create read_back_texture? It's a texture in a readback heap, yes?

This topic is closed to new replies.

Advertisement