-
Notifications
You must be signed in to change notification settings - Fork 6
Open
Labels
enhancementNew feature or requestNew feature or request
Description
DirectXCompositor.GetMirrorImage is 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:
- Minimize copying from GPU to RAM (at least once is necessary, though)
- See if we can execute this on a different thread and make the method
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) - Instead of using
FlipChannelsafter the image is copied over, can we do this while copying the memory initially? - Can we make the
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
| public Bitmap GetMirrorImage(EVREye eye = EVREye.Eye_Left) | |
| { | |
| var srvPtr = IntPtr.Zero; | |
| var result = OpenVR.Compositor.GetMirrorTextureD3D11(eye, device.NativePointer, ref srvPtr); | |
| if (result != EVRCompositorError.None) | |
| throw new OpenVRSystemException<EVRCompositorError>("Failed to get mirror texture from OpenVR", result); | |
| var srv = new ShaderResourceView(srvPtr); | |
| var tex = srv.Resource.QueryInterface<Texture2D>(); | |
| var texDesc = tex.Description; | |
| var bitmap = new Bitmap(texDesc.Width, texDesc.Height); | |
| var boundsRect = new Rectangle(0, 0, texDesc.Width, texDesc.Height); | |
| using(var cpuTex = new Texture2D(device, new Texture2DDescription | |
| { | |
| 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); | |
| var mapSource = device.ImmediateContext.MapSubresource(cpuTex, 0, MapMode.Read, MapFlags.None); | |
| var mapDest = bitmap.LockBits(boundsRect, ImageLockMode.WriteOnly, bitmap.PixelFormat); | |
| var sourcePtr = mapSource.DataPointer; | |
| var destPtr = mapDest.Scan0; | |
| for (int y = 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(ref bitmap); | |
| return bitmap; | |
| } |
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or request