I'm using Directx11 (SlimDx C#) to write an editor type thing (like Maya). As there will be a lot of complex objects on screen, I figured I would do the picking in the following manner.
- Have all shaders write to two render targets, the first being the normal colour target, and the second being a R32_UInt texture to store pixel IDs (object ids)
- Then have this second texture read by the CPU and copied to a map for easy picking via cursor coords
The problem I am having is that it is rather slow.
At the end of each frame, I use CopyResource to copy the picking texture (BindFlags.RenderTarget) to a 'ResourceUsage.Staging' texture
Then I call MapSubresource, and copy it all to a simple array of uints (which are used for the actual picking detection).
It takes about 10ms though :( .... is there a faster way? .... The Copy call appears to be ok, it is the mapping/Unmapping calls that take the time.
My code looks something like this :
void EndOfRenderFrame()
{
// copy the picking rendertarget to the staging texture (as we cant read from a rendertarget)
D3DDevice.ImmediateContext.CopyResource(m_pickTexture, m_pickStagingTexture);
// now copy the staging texture to our local copy of the picking buffer
DataBox map = D3DDevice.ImmediateContext.MapSubresource(m_pickStagingTexture, 0, MapMode.Read, MapFlags.None);
int destinationPitch = m_pickStagingTexture.Description.Width;
for (int i = 0; i < m_pickStagingTexture.Description.Height; ++i)
{
Copy(map.Data.DataPointer, i * (map.RowPitch / 4), m_pickMap.Data, i * destinationPitch, destinationPitch);
}
D3DDevice.ImmediateContext.UnmapSubresource(m_pickStagingTexture, 0);
}
//--------------------------------------------------------------------------
public static void Copy(IntPtr source, int sourceOffset, uint[] destination, int destinationOffset, int length)
{
unsafe
{
uint* sourcePtr = ((uint*)source) + sourceOffset;
for (int i = destinationOffset; i < destinationOffset + length; ++i)
{
destination[i] = *sourcePtr++;
}
}
}