private void InitializeResources(GraphicsDevice graphicsDevice, int width, int height) { try { Debug.Assert(_renderTarget == null, "Dispose previous back buffer before creating a new back buffer."); // MonoGame var format = _enableAlpha ? SurfaceFormat.Bgra32 : SurfaceFormat.Bgr32; _renderTarget = new RenderTarget2D(graphicsDevice, width, height, false, format, DepthFormat.Depth24Stencil8, 0, RenderTargetUsage.DiscardContents); // Direct3D 11 var device11 = (SharpDX.Direct3D11.Device)graphicsDevice.Handle; var formatDXGI = D3D11Helper.ToD3D11(format); _texture11 = D3D11Helper.CreateSharedResource(device11, width, height, formatDXGI); _stagingResource11 = D3D11Helper.CreateStagingResource(device11, _texture11); // Direct3D 9 _texture9 = _d3D9.CreateSharedTexture(_texture11); _surface9 = _texture9.GetSurfaceLevel(0); _stagingResource9 = _d3D9.CreateStagingResource(_texture11); // Direct3D 11 event query. Debug.Assert(_isFrameReady, "_isFrameReady should be true when uninitialized."); var queryDescription = new SharpDX.Direct3D11.QueryDescription { Flags = SharpDX.Direct3D11.QueryFlags.None, Type = SharpDX.Direct3D11.QueryType.Event }; _query = new SharpDX.Direct3D11.Query(device11, queryDescription); // Assign back buffer to D3DImage. // The back buffer is still empty, however we need to set a valid back buffer // for the layout logic. Otherwise, the size of the D3D11Image is (0, 0). Lock(); SetBackBuffer(D3DResourceType.IDirect3DSurface9, _surface9.NativePointer, true); #else SetBackBuffer(D3DResourceType.IDirect3DSurface9, _surface9.NativePointer); Unlock(); if (IsSynchronized) { // Issue a copy of the surface into the staging resource to see when the // resource is no longer used by Direct3D 9. _d3D9.Copy(_surface9, _stagingResource9); _isAvailable9 = _d3D9.TryAccess(_stagingResource9); } } catch { // GPU may run out of memory. UninitializeResources(); throw; } }
/// <summary> /// Unlocks the back buffer and disables render operations. /// </summary> /// <param name="graphicsDevice">The graphics device.</param> public void EndRender(GraphicsDevice graphicsDevice) { if (!_isLocked) // May appear due to WPF bug (see above). return; ThrowIfDisposed(); var device11 = (SharpDX.Direct3D11.Device)graphicsDevice.Handle; try { if (_renderTarget == null) { // BeginRender was unsuccessful. (GPU out-of-memory exception.) return; } // Double-buffering: Copy MonoGame render target into shared resource. D3D11Helper.Copy(device11, (SharpDX.Direct3D11.Texture2D)_renderTarget.Handle, _texture11); // Place Direct3D 11 event query. device11.ImmediateContext.End(_query); SharpDX.Bool result; _isFrameReady = device11.ImmediateContext.GetData(_query, out result) && result; if (IsSynchronized) { // Issue a copy of the surface into the staging resource to see when the // resource is no longer used by Direct3D 11. D3D11Helper.Copy(device11, _texture11, _stagingResource11); // Block until the surface is no longer used by Direct3D 11. D3D11Helper.Access(device11, _stagingResource11); } else { // For optimal performance, explicitly flush command buffers. graphicsDevice.Flush(); } // Note: Redundant calls to SetBackBuffer() are a no-op. SetBackBuffer(D3DResourceType.IDirect3DSurface9, _surface9.NativePointer, true); #else SetBackBuffer(D3DResourceType.IDirect3DSurface9, _surface9.NativePointer); if (IsSynchronized) { // Issue a copy of the surface into the staging resource to see when the // resource is no longer used by Direct3D 9. _d3D9.Copy(_surface9, _stagingResource9); _isAvailable9 = _d3D9.TryAccess(_stagingResource9); } AddDirtyRect(new Int32Rect(0, 0, PixelWidth, PixelHeight)); } finally { Unlock(); _isLocked = false; } }