Пример #1
0
 private void InitializeDevice()
 {
     device = new Dx11.Device(Dx11.DriverType.Hardware, Dx11.DeviceCreationFlags.None);
     for (int i = 0; i < 8; i++)
     {
         qual = device.CheckMultisampleQualityLevels(Dxgi.Format.R8G8B8A8_UNorm, i);
         if (qual > 0)
         {
             count = i;
         }
     }
     factor    = new Dxgi.Factory();
     swapChain = new Dxgi.SwapChain(factor, device,
                                    new Dxgi.SwapChainDescription()
     {
         BufferCount       = 1, OutputHandle = this.Handle,
         IsWindowed        = true,
         SampleDescription = new Dxgi.SampleDescription()
         {
             Count = count, Quality = qual - 1,
         }, ModeDescription = new Dxgi.ModeDescription()
         {
             Width       = ClientSize.Width, Height = ClientSize.Height,
             RefreshRate = new Rational(60, 1),
             Format      = Dxgi.Format.R8G8B8A8_UNorm,
         }, Usage = Dxgi.Usage.RenderTargetOutput
     });
     InitializeRenderTarget();
     InitializeDepthStencil();
     InitializeViewport();
     LoadContent();
     InitializeInputDevice();
 }
Пример #2
0
    static void CreateDeviceAndSwapChain(
        System.Windows.Forms.Form form,
        out SlimDX.Direct3D11.Device device,
        out SlimDX.DXGI.SwapChain swapChain
        )
    {
        SlimDX.Direct3D11.Device.CreateWithSwapChain(

            SlimDX.Direct3D11.DriverType.Hardware,
            SlimDX.Direct3D11.DeviceCreationFlags.None,
            new SlimDX.DXGI.SwapChainDescription
        {
            BufferCount       = 1,
            OutputHandle      = form.Handle,
            IsWindowed        = true,
            SampleDescription = new SlimDX.DXGI.SampleDescription
            {
                Count   = 1,
                Quality = 0
            },
            ModeDescription = new SlimDX.DXGI.ModeDescription
            {
                Width       = form.ClientSize.Width,
                Height      = form.ClientSize.Height,
                RefreshRate = new SlimDX.Rational(60, 1),
                Format      = SlimDX.DXGI.Format.R8G8B8A8_UNorm
            },
            Usage = SlimDX.DXGI.Usage.RenderTargetOutput
        },
            out device,
            out swapChain
            );
    }
Пример #3
0
        /// <summary>
        /// Hooked to allow resizing a texture/surface that is reused. Currently not in use as we create the texture for each request
        /// to support different sizes each time (as we use DirectX to copy only the region we are after rather than the entire backbuffer)
        /// </summary>
        /// <param name="swapChainPtr"></param>
        /// <param name="newTargetParameters"></param>
        /// <returns></returns>
        int ResizeTargetHook(IntPtr swapChainPtr, ref DXGI.DXGI_MODE_DESC newTargetParameters)
        {
            using (SlimDX.DXGI.SwapChain swapChain = SlimDX.DXGI.SwapChain.FromPointer(swapChainPtr))
            {
                // This version creates a new texture for each request so there is nothing to resize.
                // IF the size of the texture is known each time, we could create it once, and then possibly need to resize it here

                if (bitmap != null)
                {
                    bitmap.Dispose();
                    bitmap = null;
                }
                return(swapChain.ResizeTarget(
                           new SlimDX.DXGI.ModeDescription()
                {
                    Format = newTargetParameters.Format,
                    Height = newTargetParameters.Height,
                    RefreshRate = newTargetParameters.RefreshRate,
                    Scaling = newTargetParameters.Scaling,
                    ScanlineOrdering = newTargetParameters.ScanlineOrdering,
                    Width = newTargetParameters.Width
                }
                           ).Code);
            }
        }
Пример #4
0
        public override void Hook()
        {
            this.DebugMessage("Hook: Begin");

            // Determine method addresses in Direct3D10.Device, and DXGI.SwapChain
            if (_d3d10VTblAddresses == null)
            {
                _d3d10VTblAddresses         = new List <IntPtr>();
                _dxgiSwapChainVTblAddresses = new List <IntPtr>();
                this.DebugMessage("Hook: Before device creation");
                using (SlimDX.DXGI.Factory factory = new SlimDX.DXGI.Factory())
                {
                    using (SlimDX.Direct3D10.Device device = new Device(factory.GetAdapter(0), DriverType.Hardware, DeviceCreationFlags.None))
                    {
                        this.DebugMessage("Hook: Device created");
                        _d3d10VTblAddresses.AddRange(GetVTblAddresses(device.ComPointer, D3D10_DEVICE_METHOD_COUNT));

                        using (SlimDX.Windows.RenderForm renderForm = new SlimDX.Windows.RenderForm())
                        {
                            using (SlimDX.DXGI.SwapChain sc = new SlimDX.DXGI.SwapChain(factory, device, DXGI.CreateSwapChainDescription(renderForm.Handle)))
                            {
                                _dxgiSwapChainVTblAddresses.AddRange(GetVTblAddresses(sc.ComPointer, DXGI.DXGI_SWAPCHAIN_METHOD_COUNT));
                            }
                        }
                    }
                }
            }

            // We will capture the backbuffer here
            DXGISwapChain_PresentHook = LocalHook.Create(
                _dxgiSwapChainVTblAddresses[(int)DXGI.DXGISwapChainVTbl.Present],
                new DXGISwapChain_PresentDelegate(PresentHook),
                this);

            // We will capture target/window resizes here
            DXGISwapChain_ResizeTargetHook = LocalHook.Create(
                _dxgiSwapChainVTblAddresses[(int)DXGI.DXGISwapChainVTbl.ResizeTarget],
                new DXGISwapChain_ResizeTargetDelegate(ResizeTargetHook),
                this);

            /*
             * Don't forget that all hooks will start deactivated...
             * The following ensures that all threads are intercepted:
             * Note: you must do this for each hook.
             */
            DXGISwapChain_PresentHook.ThreadACL.SetExclusiveACL(new Int32[1]);

            DXGISwapChain_ResizeTargetHook.ThreadACL.SetExclusiveACL(new Int32[1]);
        }
 private void DestroySwapChain()
 {
     if (_swapChain != null)
     {
         if (_isFullScreen)
         {
             _swapChain.SetFullScreenState(false, null);
         }
         if (_renderer != null)
         {
             _renderer.Resources.RemoveTrackedObject(_swapChain.ComPointer);
         }
         _swapChain.Dispose();
         _swapChain = null;
     }
 }
Пример #6
0
        private void Destroy()
        {
            mOffScreenWindow?.Close();
            mSwapChain?.Dispose();
            mPixelShader?.Dispose();
            mVertexShader?.Dispose();
            mVertexBuffer?.Dispose();
            mVertices?.Dispose();
            mRenderTarget?.Dispose();

            mOffScreenWindow = null;
            mSwapChain       = null;
            mPixelShader     = null;
            mVertexShader    = null;
            mVertexBuffer    = null;
            mVertices        = null;
            mRenderTarget    = null;
        }
Пример #7
0
        /// <summary>
        /// Our present hook that will grab a copy of the backbuffer when requested. Note: this supports multi-sampling (anti-aliasing)
        /// </summary>
        /// <param name="swapChainPtr"></param>
        /// <param name="syncInterval"></param>
        /// <param name="flags"></param>
        /// <returns>The HRESULT of the original method</returns>
        int PresentHook(IntPtr swapChainPtr, int syncInterval, SlimDX.DXGI.PresentFlags flags)
        {
            using (SlimDX.DXGI.SwapChain swapChain = SlimDX.DXGI.SwapChain.FromPointer(swapChainPtr))
            {
                try
                {
                    #region Screenshot Request
                    if (this.Request != null)
                    {
                        this.DebugMessage("PresentHook: Request Start");
                        DateTime startTime = DateTime.Now;
                        using (Texture2D texture = Texture2D.FromSwapChain <Texture2D>(swapChain, 0))
                        {
                            #region Determine region to capture
                            System.Drawing.Rectangle regionToCapture = new System.Drawing.Rectangle(0, 0, texture.Description.Width, texture.Description.Height);

                            if (this.Request.RegionToCapture.Width > 0)
                            {
                                regionToCapture = this.Request.RegionToCapture;
                            }
                            #endregion

                            var theTexture = texture;

                            // If texture is multisampled, then we can use ResolveSubresource to copy it into a non-multisampled texture
                            Texture2D textureResolved = null;
                            if (texture.Description.SampleDescription.Count > 1)
                            {
                                this.DebugMessage("PresentHook: resolving multi-sampled texture");
                                // texture is multi-sampled, lets resolve it down to single sample
                                textureResolved = new Texture2D(texture.Device, new Texture2DDescription()
                                {
                                    CpuAccessFlags    = CpuAccessFlags.None,
                                    Format            = texture.Description.Format,
                                    Height            = texture.Description.Height,
                                    Usage             = ResourceUsage.Default,
                                    Width             = texture.Description.Width,
                                    ArraySize         = 1,
                                    SampleDescription = new SlimDX.DXGI.SampleDescription(1, 0), // Ensure single sample
                                    BindFlags         = BindFlags.None,
                                    MipLevels         = 1,
                                    OptionFlags       = texture.Description.OptionFlags
                                });
                                // Resolve into textureResolved
                                texture.Device.ImmediateContext.ResolveSubresource(texture, 0, textureResolved, 0, texture.Description.Format);

                                // Make "theTexture" be the resolved texture
                                theTexture = textureResolved;
                            }

                            // Create destination texture
                            Texture2D textureDest = new Texture2D(texture.Device, new Texture2DDescription()
                            {
                                CpuAccessFlags    = CpuAccessFlags.None,                     // CpuAccessFlags.Write | CpuAccessFlags.Read,
                                Format            = SlimDX.DXGI.Format.R8G8B8A8_UNorm,       // Supports BMP/PNG
                                Height            = regionToCapture.Height,
                                Usage             = ResourceUsage.Default,                   // ResourceUsage.Staging,
                                Width             = regionToCapture.Width,
                                ArraySize         = 1,                                       //texture.Description.ArraySize,
                                SampleDescription = new SlimDX.DXGI.SampleDescription(1, 0), // texture.Description.SampleDescription,
                                BindFlags         = BindFlags.None,
                                MipLevels         = 1,                                       //texture.Description.MipLevels,
                                OptionFlags       = texture.Description.OptionFlags
                            });

                            // Copy the subresource region, we are dealing with a flat 2D texture with no MipMapping, so 0 is the subresource index
                            theTexture.Device.ImmediateContext.CopySubresourceRegion(theTexture, 0, new ResourceRegion()
                            {
                                Top    = regionToCapture.Top,
                                Bottom = regionToCapture.Bottom,
                                Left   = regionToCapture.Left,
                                Right  = regionToCapture.Right,
                                Front  = 0,
                                Back   = 1 // Must be 1 or only black will be copied
                            }, textureDest, 0, 0, 0, 0);

                            // Note: it would be possible to capture multiple frames and process them in a background thread

                            // Copy to memory and send back to host process on a background thread so that we do not cause any delay in the rendering pipeline
                            Guid requestId = this.Request.RequestId; // this.Request gets set to null, so copy the RequestId for use in the thread
                            ThreadPool.QueueUserWorkItem(delegate
                            {
                                //FileStream fs = new FileStream(@"c:\temp\temp.bmp", FileMode.Create);
                                //Texture2D.ToStream(testSubResourceCopy, ImageFileFormat.Bmp, fs);

                                DateTime startCopyToSystemMemory = DateTime.Now;
                                using (MemoryStream ms = new MemoryStream())
                                {
                                    Texture2D.ToStream(textureDest.Device.ImmediateContext, textureDest, ImageFileFormat.Bmp, ms);
                                    ms.Position = 0;
                                    this.DebugMessage("PresentHook: Copy to System Memory time: " + (DateTime.Now - startCopyToSystemMemory).ToString());

                                    DateTime startSendResponse = DateTime.Now;
                                    SendResponse(ms, requestId);
                                    this.DebugMessage("PresentHook: Send response time: " + (DateTime.Now - startSendResponse).ToString());
                                }

                                // Free the textureDest as we no longer need it.
                                textureDest.Dispose();
                                textureDest = null;
                                this.DebugMessage("PresentHook: Full Capture time: " + (DateTime.Now - startTime).ToString());
                            });

                            // Prevent the request from being processed a second time
                            this.Request = null;

                            // Make sure we free up the resolved texture if it was created
                            if (textureResolved != null)
                            {
                                textureResolved.Dispose();
                                textureResolved = null;
                            }
                        }
                        this.DebugMessage("PresentHook: Copy BackBuffer time: " + (DateTime.Now - startTime).ToString());
                        this.DebugMessage("PresentHook: Request End");
                    }
                    #endregion

                    #region TODO: Draw overlay (after screenshot so we don't capture overlay as well)

                    // Note: Direct3D 11 doesn't have font support, so I believe the approach is to use
                    //       a Direct3D 10.1 device with Direct2d, render to a texture, and then blend
                    //       this into the Direct3D 11 backbuffer - hmm sounds like fun.
                    // http://forums.create.msdn.com/forums/t/38961.aspx
                    // http://www.gamedev.net/topic/547920-how-to-use-d2d-with-d3d11/

                    #endregion
                }
                catch (Exception e)
                {
                    // If there is an error we do not want to crash the hooked application, so swallow the exception
                    this.DebugMessage("PresentHook: Exeception: " + e.GetType().FullName + ": " + e.Message);
                    //return unchecked((int)0x8000FFFF); //E_UNEXPECTED
                }

                // As always we need to call the original method, note that EasyHook has already repatched the original method
                // so calling it here will not cause an endless recursion to this function
                return(swapChain.Present(syncInterval, flags).Code);
            }
        }
        private void CreateSwapChain(IntPtr windowHandle, PresentationParameters presentParams)
        {
            DXGI.Format surfaceFormat = D3D10Helper.ToD3DSurfaceFormat(presentParams.BackBufferFormat);

            switch (presentParams.PresentInterval)
            {
            case PresentInterval.Immediate:
                _interval = 0;
                break;

            case PresentInterval.One:
                _interval = 1;
                break;

            case PresentInterval.Two:
                _interval = 2;
                break;
            }

            DXGI.SampleDescription sampleDesc = new DXGI.SampleDescription(1, 0);
            bool msEnabled = false;

            if (presentParams.MultiSampleCount > 1)
            {
                sampleDesc.Count = presentParams.MultiSampleCount;
                int q = _graphicsDevice.CheckMultisampleQualityLevels(surfaceFormat, presentParams.MultiSampleCount);
                if (presentParams.MultiSampleQuality < q)
                {
                    sampleDesc.Quality = presentParams.MultiSampleQuality;
                }
                else
                {
                    sampleDesc.Quality = q - 1;
                }
                msEnabled = true;
            }

            DXGI.SwapEffect swap;
            if (presentParams.RenderTargetUsage == RenderTargetUsage.PlatformDefault)
            {
                if (msEnabled)
                {
                    swap = DXGI.SwapEffect.Discard;
                }
                else
                {
                    swap = DXGI.SwapEffect.Sequential;
                }
            }
            else if (presentParams.RenderTargetUsage == RenderTargetUsage.DiscardContents)
            {
                swap = DXGI.SwapEffect.Discard;
            }
            else
            {
                swap = DXGI.SwapEffect.Sequential;
            }
            DXGI.ModeDescription modeDesc = new DXGI.ModeDescription(presentParams.BackBufferWidth, presentParams.BackBufferHeight, new SDX.Rational(60, 1), surfaceFormat);
            modeDesc.Scaling = DXGI.DisplayModeScaling.Stretched;
            _swapChain       = new DXGI.SwapChain(_factory, _graphicsDevice, new DXGI.SwapChainDescription {
                BufferCount       = 1,
                Flags             = DXGI.SwapChainFlags.AllowModeSwitch,
                IsWindowed        = true,
                ModeDescription   = modeDesc,
                OutputHandle      = windowHandle,
                SampleDescription = sampleDesc,
                SwapEffect        = swap,
                Usage             = DXGI.Usage.RenderTargetOutput
            });

            //Add to tracker
            _renderer.Resources.AddTrackedObject(_swapChain.ComPointer, this);

            _factory.SetWindowAssociation(windowHandle, DXGI.WindowAssociationFlags.IgnoreAll | DXGI.WindowAssociationFlags.IgnoreAltEnter);
        }
Пример #9
0
        public override void Hook()
        {
            this.DebugMessage("Hook: Begin");

            // Determine method addresses in Direct3D10.Device, and DXGI.SwapChain
            if (_d3d10VTblAddresses == null)
            {
                _d3d10VTblAddresses = new List<IntPtr>();
                _dxgiSwapChainVTblAddresses = new List<IntPtr>();
                this.DebugMessage("Hook: Before device creation");
                using (SlimDX.DXGI.Factory factory = new SlimDX.DXGI.Factory())
                {
                    using (SlimDX.Direct3D10.Device device = new Device(factory.GetAdapter(0), DriverType.Hardware, DeviceCreationFlags.None))
                    {
                        this.DebugMessage("Hook: Device created");
                        _d3d10VTblAddresses.AddRange(GetVTblAddresses(device.ComPointer, D3D10_DEVICE_METHOD_COUNT));
                        
                        using (SlimDX.Windows.RenderForm renderForm = new SlimDX.Windows.RenderForm())
                        {
                            using (SlimDX.DXGI.SwapChain sc = new SlimDX.DXGI.SwapChain(factory, device, DXGI.CreateSwapChainDescription(renderForm.Handle)))
                            {
                                _dxgiSwapChainVTblAddresses.AddRange(GetVTblAddresses(sc.ComPointer, DXGI.DXGI_SWAPCHAIN_METHOD_COUNT));
                            }
                        }
                    }
                }
            }

            // We will capture the backbuffer here
            DXGISwapChain_PresentHook = LocalHook.Create(
                _dxgiSwapChainVTblAddresses[(int)DXGI.DXGISwapChainVTbl.Present],
                new DXGISwapChain_PresentDelegate(PresentHook),
                this);

            // We will capture target/window resizes here
            DXGISwapChain_ResizeTargetHook = LocalHook.Create(
                _dxgiSwapChainVTblAddresses[(int)DXGI.DXGISwapChainVTbl.ResizeTarget],
                new DXGISwapChain_ResizeTargetDelegate(ResizeTargetHook),
                this);

            /*
             * Don't forget that all hooks will start deactivated...
             * The following ensures that all threads are intercepted:
             * Note: you must do this for each hook.
             */
            DXGISwapChain_PresentHook.ThreadACL.SetExclusiveACL(new Int32[1]);

            DXGISwapChain_ResizeTargetHook.ThreadACL.SetExclusiveACL(new Int32[1]);
        }
Пример #10
0
        private void CreateView(int width, int height)
        {
            if (width <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(width));
            }

            if (height <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(height));
            }

            Destroy();

            mWidth  = width;
            mHeight = height;

            Execution.ExecuteOnUiThread(() =>
            {
                mOffScreenWindow                 = new Form();
                mOffScreenWindow.Left            = -65535;
                mOffScreenWindow.Top             = -65535;
                mOffScreenWindow.FormBorderStyle = FormBorderStyle.None;
                mOffScreenWindow.Width           = 1;
                mOffScreenWindow.Height          = 1;
                mOffScreenWindow.ShowInTaskbar   = false;
                mOffScreenWindow.Show();
                mOffScreenWindow.Hide();
            });

            var description = new SwapChainDescription
            {
                BufferCount       = 1,
                IsWindowed        = true,
                ModeDescription   = new ModeDescription(0, 0, new Rational(60, 1), Format.B8G8R8A8_UNorm),
                SampleDescription = new SampleDescription(1, 0),
                Usage             = Usage.RenderTargetOutput | Usage.Shared,
                OutputHandle      = mOffScreenWindow.Handle
            };

            mSwapChain    = mDevice.CreateSwapChain(description);
            mPixelShader  = new PixelShader(Device, Bytecode);
            mVertexShader = new VertexShader(Device, mVertexShaderBytecode);
            mVertexBuffer = CreateVertexBuffer(out mVertices);

            Execution.ExecuteOnUiThread(() =>
            {
                mOffScreenWindow.Width  = mWidth;
                mOffScreenWindow.Height = mHeight;
            });

            mSwapChain.ResizeBuffers(1, mWidth, mHeight, Format.B8G8R8A8_UNorm, SwapChainFlags.None);
            Device.ImmediateContext.Rasterizer.SetViewports(new Viewport(0.0f, 0.0f, mWidth, mHeight));

            Device.ImmediateContext.Rasterizer.State =
                RasterizerState.FromDescription(Device,
                                                new RasterizerStateDescription
            {
                CullMode = CullMode.None,
                FillMode = FillMode.Solid
            });

            mRenderTarget = new HardwareRenderTarget(mDevice, mSwapChain);
        }