| publicBitmapGetMirrorImage(EVREyeeye=EVREye.Eye_Left) |
| { |
| varsrvPtr=IntPtr.Zero; |
| |
| varresult=OpenVR.Compositor.GetMirrorTextureD3D11(eye,device.NativePointer,refsrvPtr); |
| if(result!=EVRCompositorError.None) |
| thrownewOpenVRSystemException<EVRCompositorError>("Failed to get mirror texture from OpenVR",result); |
| |
| varsrv=newShaderResourceView(srvPtr); |
| vartex=srv.Resource.QueryInterface<Texture2D>(); |
| vartexDesc=tex.Description; |
| |
| varbitmap=newBitmap(texDesc.Width,texDesc.Height); |
| varboundsRect=newRectangle(0,0,texDesc.Width,texDesc.Height); |
| |
| using(varcpuTex=newTexture2D(device,newTexture2DDescription |
| { |
| CpuAccessFlags=CpuAccessFlags.Read, |
| BindFlags=BindFlags.None, |
| Format=texDesc.Format, |
| Width=texDesc.Width, |
| Height=texDesc.Height, |
| OptionFlags=ResourceOptionFlags.None, |
| MipLevels=1, |
| ArraySize=1, |
| SampleDescription={Count=1,Quality=0}, |
| Usage=ResourceUsage.Staging |
| })) |
| { |
| // Copy texture to RAM so CPU can read from it |
| device.ImmediateContext.CopyResource(tex,cpuTex); |
| OpenVR.Compositor.ReleaseMirrorTextureD3D11(srvPtr); |
| |
| varmapSource=device.ImmediateContext.MapSubresource(cpuTex,0,MapMode.Read,MapFlags.None); |
| varmapDest=bitmap.LockBits(boundsRect,ImageLockMode.WriteOnly,bitmap.PixelFormat); |
| varsourcePtr=mapSource.DataPointer; |
| vardestPtr=mapDest.Scan0; |
| |
| for(inty=0;y<texDesc.Height;y++) |
| { |
| Utilities.CopyMemory(destPtr,sourcePtr,texDesc.Width*4); |
| sourcePtr=IntPtr.Add(sourcePtr,mapSource.RowPitch); |
| destPtr=IntPtr.Add(destPtr,mapDest.Stride); |
| } |
| |
| bitmap.UnlockBits(mapDest); |
| device.ImmediateContext.UnmapSubresource(cpuTex,0); |
| } |
| |
| FlipChannels(refbitmap); |
| returnbitmap; |
| } |
DirectXCompositor.GetMirrorImageis really slow right now (~15ms per call on average), mostly because there's lots of copying and manipulation going on. We should explore different ways of improving performance, such as:async(would OpenVR be happy with that? If not, we could call the OpenVR API on the main thread, then do the rest of the work on a different thread)FlipChannelsafter the image is copied over, can we do this while copying the memory initially?Texture2D->Bitmapcopying more efficient?I don't work with DirectX much (or graphics APIs in general) so there could be something I'm missing. Any input is appreciated :)
For reference, here's the method:
OVRSharp/OVRSharp.Graphics.DirectX/DirectXCompositor.cs
Lines 52 to 103 in f75f356