diff --git a/Dotnet/Cef/CefService.cs b/Dotnet/Cef/CefService.cs index a6848a59..1fa097ee 100644 --- a/Dotnet/Cef/CefService.cs +++ b/Dotnet/Cef/CefService.cs @@ -51,7 +51,6 @@ namespace VRCX cefSettings.CefCommandLineArgs.Add("disable-pdf-extension"); cefSettings.CefCommandLineArgs["autoplay-policy"] = "no-user-gesture-required"; cefSettings.CefCommandLineArgs.Add("disable-web-security"); - cefSettings.SetOffScreenRenderingBestPerformanceArgs(); // causes white screen sometimes? if (WebApi.ProxySet) { diff --git a/Dotnet/Overlay/OffScreenBrowser.cs b/Dotnet/Overlay/OffScreenBrowser.cs index 822dc8c3..48b5723f 100644 --- a/Dotnet/Overlay/OffScreenBrowser.cs +++ b/Dotnet/Overlay/OffScreenBrowser.cs @@ -10,116 +10,76 @@ using CefSharp.OffScreen; using CefSharp.Structs; using SharpDX.Direct3D11; using System; -using System.Runtime.InteropServices; using System.Threading; +using SharpDX.Direct3D; +using SharpDX.Mathematics.Interop; using Range = CefSharp.Structs.Range; namespace VRCX { public class OffScreenBrowser : ChromiumWebBrowser, IRenderHandler { - private readonly ReaderWriterLockSlim _paintBufferLock; - private GCHandle _paintBuffer; - private int _width; - private int _height; + private Device _device; + private Device1 _device1; + private DeviceMultithread _deviceMultithread; + private Query _query; + private Texture2D _renderTarget; public OffScreenBrowser(string address, int width, int height) - : base( - address, - new BrowserSettings() - { - DefaultEncoding = "UTF-8" - } - ) + : base(address, automaticallyCreateBrowser: false) { - _paintBufferLock = new ReaderWriterLockSlim(); + var windowInfo = new WindowInfo(); + windowInfo.SetAsWindowless(IntPtr.Zero); + windowInfo.WindowlessRenderingEnabled = true; + windowInfo.SharedTextureEnabled = true; + windowInfo.Width = width; + windowInfo.Height = height; + + var browserSettings = new BrowserSettings() + { + DefaultEncoding = "UTF-8", + WindowlessFrameRate = 60 + }; + + CreateBrowser(windowInfo, browserSettings); Size = new System.Drawing.Size(width, height); RenderHandler = this; - + JavascriptBindings.ApplyVrJavascriptBindings(JavascriptObjectRepository); } + public void UpdateRender(Device device, Texture2D renderTarget) + { + _device = device; + _device1 = _device.QueryInterface(); + + _deviceMultithread?.Dispose(); + _deviceMultithread = _device.QueryInterfaceOrNull(); + _deviceMultithread?.SetMultithreadProtected(true); + + _renderTarget = renderTarget; + + _query?.Dispose(); + _query = new Query(_device, new QueryDescription + { + Type = QueryType.Event, + Flags = QueryFlags.None + }); + } + public new void Dispose() { RenderHandler = null; base.Dispose(); - - _paintBufferLock.EnterWriteLock(); - try - { - if (_paintBuffer.IsAllocated == true) - { - _paintBuffer.Free(); - } - } - finally - { - _paintBufferLock.ExitWriteLock(); - } - - _paintBufferLock.Dispose(); - } - - public void RenderToTexture(Texture2D texture) - { - // Safeguard against uninitialized texture - if (texture == null) - return; - - _paintBufferLock.EnterReadLock(); - try - { - if (_width > 0 && - _height > 0) - { - var context = texture.Device.ImmediateContext; - var dataBox = context.MapSubresource( - texture, - 0, - MapMode.WriteDiscard, - MapFlags.None - ); - if (dataBox.IsEmpty == false) - { - var sourcePtr = _paintBuffer.AddrOfPinnedObject(); - var destinationPtr = dataBox.DataPointer; - var pitch = _width * 4; - var rowPitch = dataBox.RowPitch; - if (pitch == rowPitch) - { - WinApi.RtlCopyMemory( - destinationPtr, - sourcePtr, - (uint)(_width * _height * 4) - ); - } - else - { - for (var y = _height; y > 0; --y) - { - WinApi.RtlCopyMemory( - destinationPtr, - sourcePtr, - (uint)pitch - ); - sourcePtr += pitch; - destinationPtr += rowPitch; - } - } - } - context.UnmapSubresource(texture, 0); - } - } - finally - { - _paintBufferLock.ExitReadLock(); - } } ScreenInfo? IRenderHandler.GetScreenInfo() { - return null; + return new ScreenInfo + { + DeviceScaleFactor = 1.0F + }; } bool IRenderHandler.GetScreenPoint(int viewX, int viewY, out int screenX, out int screenY) @@ -136,7 +96,24 @@ namespace VRCX void IRenderHandler.OnAcceleratedPaint(PaintElementType type, Rect dirtyRect, AcceleratedPaintInfo paintInfo) { - // NOT USED + if (type != PaintElementType.View) + return; + + if (_device == null) + return; + + using Texture2D cefTexture = _device1.OpenSharedResource1(paintInfo.SharedTextureHandle); + _device.ImmediateContext.CopyResource(cefTexture, _renderTarget); + _device.ImmediateContext.End(_query); + _device.ImmediateContext.Flush(); + + RawBool q = _device.ImmediateContext.GetData(_query, AsynchronousFlags.DoNotFlush); + + while (!q) + { + Thread.Yield(); + q = _device.ImmediateContext.GetData(_query, AsynchronousFlags.DoNotFlush); + } } void IRenderHandler.OnCursorChange(IntPtr cursor, CursorType type, CursorInfo customCursorInfo) @@ -149,37 +126,6 @@ namespace VRCX void IRenderHandler.OnPaint(PaintElementType type, Rect dirtyRect, IntPtr buffer, int width, int height) { - if (type == PaintElementType.View) - { - _paintBufferLock.EnterWriteLock(); - try - { - if (_width != width || - _height != height) - { - _width = width; - _height = height; - if (_paintBuffer.IsAllocated == true) - { - _paintBuffer.Free(); - } - _paintBuffer = GCHandle.Alloc( - new byte[_width * _height * 4], - GCHandleType.Pinned - ); - } - - WinApi.RtlCopyMemory( - _paintBuffer.AddrOfPinnedObject(), - buffer, - (uint)(width * height * 4) - ); - } - finally - { - _paintBufferLock.ExitWriteLock(); - } - } } void IRenderHandler.OnPopupShow(bool show) diff --git a/Dotnet/Overlay/VRCXVR.cs b/Dotnet/Overlay/VRCXVR.cs index 6c4521e5..fae8021f 100644 --- a/Dotnet/Overlay/VRCXVR.cs +++ b/Dotnet/Overlay/VRCXVR.cs @@ -16,6 +16,10 @@ using SharpDX.Direct3D11; using SharpDX.DXGI; using Valve.VR; using Device = SharpDX.Direct3D11.Device; +using Device1 = SharpDX.Direct3D11.Device1; +using Device2 = SharpDX.Direct3D11.Device2; +using Device3 = SharpDX.Direct3D11.Device3; +using Device4 = SharpDX.Direct3D11.Device4; namespace VRCX { @@ -87,7 +91,8 @@ namespace VRCX { Factory f = new Factory1(); _device = new Device(f.GetAdapter(OpenVR.System.GetD3D9AdapterIndex()), - DeviceCreationFlags.SingleThreaded | DeviceCreationFlags.BgraSupport); + DeviceCreationFlags.BgraSupport); + UpgradeDevice(); _texture1?.Dispose(); _texture1 = new Texture2D( @@ -100,12 +105,11 @@ namespace VRCX ArraySize = 1, Format = Format.B8G8R8A8_UNorm, SampleDescription = new SampleDescription(1, 0), - Usage = ResourceUsage.Dynamic, - BindFlags = BindFlags.ShaderResource, - CpuAccessFlags = CpuAccessFlags.Write + BindFlags = BindFlags.ShaderResource } ); - + _browser1?.UpdateRender(_device, _texture1); + _texture2?.Dispose(); _texture2 = new Texture2D( _device, @@ -117,11 +121,48 @@ namespace VRCX ArraySize = 1, Format = Format.B8G8R8A8_UNorm, SampleDescription = new SampleDescription(1, 0), - Usage = ResourceUsage.Dynamic, - BindFlags = BindFlags.ShaderResource, - CpuAccessFlags = CpuAccessFlags.Write + BindFlags = BindFlags.ShaderResource } ); + _browser2?.UpdateRender(_device, _texture2); + } + + private void UpgradeDevice() + { + Device5 device5 = _device.QueryInterfaceOrNull(); + if (device5 != null) + { + _device.Dispose(); + _device = device5; + return; + } + Device4 device4 = _device.QueryInterfaceOrNull(); + if (device4 != null) + { + _device.Dispose(); + _device = device4; + return; + } + Device3 device3 = _device.QueryInterfaceOrNull(); + if (device3 != null) + { + _device.Dispose(); + _device = device3; + return; + } + Device2 device2 = _device.QueryInterfaceOrNull(); + if (device2 != null) + { + _device.Dispose(); + _device = device2; + return; + } + Device1 device1 = _device.QueryInterfaceOrNull(); + if (device1 != null) + { + _device.Dispose(); + _device = device1; + } } private void ThreadLoop() @@ -152,10 +193,6 @@ namespace VRCX while (_thread != null) { - if (_wristOverlayActive) - _browser1.RenderToTexture(_texture1); - if (_hmdOverlayActive) - _browser2.RenderToTexture(_texture2); try { Thread.Sleep(32);