/// <inveritdoc/> public override void RenderAll() { SurfaceViewData viewData = null; var regionToDraw = new SharpDX.Mathematics.Rectangle(0, 0, pixelWidth, pixelHeight); SharpDX.Mathematics.Interop.RawPoint rawPosition; // Unlike other targets, we can only get the DXGI surface to render to // just before rendering. using (var surface = surfaceImageSourceNative.BeginDraw(regionToDraw, out rawPosition)) { position = rawPosition; // Cache DXGI surface in order to avoid recreate all render target view, depth stencil...etc. // Is it the right way to do it? // It seems that ISurfaceImageSourceNative.BeginDraw is returning 2 different DXGI surfaces (when the application is in foreground) // or different DXGI surfaces (when the application is in background). foreach (var surfaceViewData in viewDatas) { if (surfaceViewData.SurfacePointer == surface.NativePointer) { viewData = surfaceViewData; break; } } if (viewData == null) { viewData = viewDatas[nextViewDataIndex]; nextViewDataIndex = (nextViewDataIndex + 1) % viewDatas.Length; // Make sure that previous was disposed. viewData.Dispose(); viewData.SurfacePointer = surface.NativePointer; // Allocate a new renderTargetView if size is different // Cache the rendertarget dimensions in our helper class for convenient use. viewData.BackBuffer = surface.QueryInterface<SharpDX.Direct3D11.Texture2D>(); { var desc = viewData.BackBuffer.Description; viewData.RenderTargetSize = new Size(desc.Width, desc.Height); viewData.RenderTargetView = new SharpDX.Direct3D11.RenderTargetView(DeviceManager.DeviceDirect3D, viewData.BackBuffer); } // Create a descriptor for the depth/stencil buffer. // Allocate a 2-D surface as the depth/stencil buffer. // Create a DepthStencil view on this surface to use on bind. // TODO: Recreate a DepthStencilBuffer is inefficient. We should only have one depth buffer. Shared depth buffer? using (var depthBuffer = new SharpDX.Direct3D11.Texture2D(DeviceManager.DeviceDirect3D, new SharpDX.Direct3D11.Texture2DDescription() { Format = SharpDX.DXGI.Format.D24_UNorm_S8_UInt, ArraySize = 1, MipLevels = 1, Width = (int)viewData.RenderTargetSize.Width, Height = (int)viewData.RenderTargetSize.Height, SampleDescription = new SharpDX.DXGI.SampleDescription(1, 0), BindFlags = SharpDX.Direct3D11.BindFlags.DepthStencil, })) viewData.DepthStencilView = new SharpDX.Direct3D11.DepthStencilView(DeviceManager.DeviceDirect3D, depthBuffer, new SharpDX.Direct3D11.DepthStencilViewDescription() { Dimension = SharpDX.Direct3D11.DepthStencilViewDimension.Texture2D }); // Now we set up the Direct2D render target bitmap linked to the swapchain. // Whenever we render to this bitmap, it will be directly rendered to the // swapchain associated with the window. var bitmapProperties = new SharpDX.Direct2D1.BitmapProperties1( new SharpDX.Direct2D1.PixelFormat(SharpDX.DXGI.Format.B8G8R8A8_UNorm, SharpDX.Direct2D1.AlphaMode.Premultiplied), DeviceManager.Dpi, DeviceManager.Dpi, SharpDX.Direct2D1.BitmapOptions.Target | SharpDX.Direct2D1.BitmapOptions.CannotDraw); // Direct2D needs the dxgi version of the backbuffer surface pointer. // Get a D2D surface from the DXGI back buffer to use as the D2D render target. viewData.BitmapTarget = new SharpDX.Direct2D1.Bitmap1(DeviceManager.ContextDirect2D, surface, bitmapProperties); // Create a viewport descriptor of the full window size. viewData.Viewport = new SharpDX.Mathematics.ViewportF(position.X, position.Y, (float)viewData.RenderTargetSize.Width - position.X, (float)viewData.RenderTargetSize.Height - position.Y, 0.0f, 1.0f); } backBuffer = viewData.BackBuffer; renderTargetView = viewData.RenderTargetView; depthStencilView = viewData.DepthStencilView; RenderTargetBounds = new Rect(viewData.Viewport.X, viewData.Viewport.Y, viewData.Viewport.Width, viewData.Viewport.Height); bitmapTarget = viewData.BitmapTarget; DeviceManager.ContextDirect2D.Target = viewData.BitmapTarget; // Set the current viewport using the descriptor. DeviceManager.ContextDirect3D.Rasterizer.SetViewport(viewData.Viewport); // Perform the actual rendering of this target base.RenderAll(); } surfaceImageSourceNative.EndDraw(); }
/// <inveritdoc/> public override void RenderAll() { SurfaceViewData viewData = null; var regionToDraw = new SharpDX.Mathematics.Rectangle(0, 0, pixelWidth, pixelHeight); SharpDX.Mathematics.Interop.RawPoint rawPosition; // Unlike other targets, we can only get the DXGI surface to render to // just before rendering. using (var surface = surfaceImageSourceNative.BeginDraw(regionToDraw, out rawPosition)) { position = rawPosition; // Cache DXGI surface in order to avoid recreate all render target view, depth stencil...etc. // Is it the right way to do it? // It seems that ISurfaceImageSourceNative.BeginDraw is returning 2 different DXGI surfaces (when the application is in foreground) // or different DXGI surfaces (when the application is in background). foreach (var surfaceViewData in viewDatas) { if (surfaceViewData.SurfacePointer == surface.NativePointer) { viewData = surfaceViewData; break; } } if (viewData == null) { viewData = viewDatas[nextViewDataIndex]; nextViewDataIndex = (nextViewDataIndex + 1) % viewDatas.Length; // Make sure that previous was disposed. viewData.Dispose(); viewData.SurfacePointer = surface.NativePointer; // Allocate a new renderTargetView if size is different // Cache the rendertarget dimensions in our helper class for convenient use. viewData.BackBuffer = surface.QueryInterface <SharpDX.Direct3D11.Texture2D>(); { var desc = viewData.BackBuffer.Description; viewData.RenderTargetSize = new Size(desc.Width, desc.Height); viewData.RenderTargetView = new SharpDX.Direct3D11.RenderTargetView(DeviceManager.DeviceDirect3D, viewData.BackBuffer); } // Create a descriptor for the depth/stencil buffer. // Allocate a 2-D surface as the depth/stencil buffer. // Create a DepthStencil view on this surface to use on bind. // TODO: Recreate a DepthStencilBuffer is inefficient. We should only have one depth buffer. Shared depth buffer? using (var depthBuffer = new SharpDX.Direct3D11.Texture2D(DeviceManager.DeviceDirect3D, new SharpDX.Direct3D11.Texture2DDescription() { Format = SharpDX.DXGI.Format.D24_UNorm_S8_UInt, ArraySize = 1, MipLevels = 1, Width = (int)viewData.RenderTargetSize.Width, Height = (int)viewData.RenderTargetSize.Height, SampleDescription = new SharpDX.DXGI.SampleDescription(1, 0), BindFlags = SharpDX.Direct3D11.BindFlags.DepthStencil, })) viewData.DepthStencilView = new SharpDX.Direct3D11.DepthStencilView(DeviceManager.DeviceDirect3D, depthBuffer, new SharpDX.Direct3D11.DepthStencilViewDescription() { Dimension = SharpDX.Direct3D11.DepthStencilViewDimension.Texture2D }); // Now we set up the Direct2D render target bitmap linked to the swapchain. // Whenever we render to this bitmap, it will be directly rendered to the // swapchain associated with the window. var bitmapProperties = new SharpDX.Direct2D1.BitmapProperties1( new SharpDX.Direct2D1.PixelFormat(SharpDX.DXGI.Format.B8G8R8A8_UNorm, SharpDX.Direct2D1.AlphaMode.Premultiplied), DeviceManager.Dpi, DeviceManager.Dpi, SharpDX.Direct2D1.BitmapOptions.Target | SharpDX.Direct2D1.BitmapOptions.CannotDraw); // Direct2D needs the dxgi version of the backbuffer surface pointer. // Get a D2D surface from the DXGI back buffer to use as the D2D render target. viewData.BitmapTarget = new SharpDX.Direct2D1.Bitmap1(DeviceManager.ContextDirect2D, surface, bitmapProperties); // Create a viewport descriptor of the full window size. viewData.Viewport = new SharpDX.Mathematics.ViewportF(position.X, position.Y, (float)viewData.RenderTargetSize.Width - position.X, (float)viewData.RenderTargetSize.Height - position.Y, 0.0f, 1.0f); } backBuffer = viewData.BackBuffer; renderTargetView = viewData.RenderTargetView; depthStencilView = viewData.DepthStencilView; RenderTargetBounds = new Rect(viewData.Viewport.X, viewData.Viewport.Y, viewData.Viewport.Width, viewData.Viewport.Height); bitmapTarget = viewData.BitmapTarget; DeviceManager.ContextDirect2D.Target = viewData.BitmapTarget; // Set the current viewport using the descriptor. DeviceManager.ContextDirect3D.Rasterizer.SetViewport(viewData.Viewport); // Perform the actual rendering of this target base.RenderAll(); } surfaceImageSourceNative.EndDraw(); }