Example #1
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>
        private int PresentHook(IntPtr swapChainPtr, int syncInterval, PresentFlags flags)
        {
            Frame();
            var swapChain = (SwapChain)swapChainPtr;


            try
            {
                #region Screenshot Request

                if (Request != null)
                {
                    try
                    {
                        DebugMessage("PresentHook: Request Start");
                        var startTime = DateTime.Now;
                        using (var texture = Resource.FromSwapChain <Texture2D>(swapChain, 0))
                        {
                            #region Determine region to capture

                            var regionToCapture = new Rectangle(0, 0, texture.Description.Width,
                                                                texture.Description.Height);

                            if (Request.RegionToCapture.Width > 0)
                            {
                                regionToCapture = 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)
                            {
                                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 SampleDescription(1, 0), // Ensure single sample
                                    BindFlags         = BindFlags.None,
                                    MipLevels         = 1,
                                    OptionFlags       = texture.Description.OptionFlags
                                });
                                // Resolve into textureResolved
                                texture.Device.ResolveSubresource(texture, 0, textureResolved, 0,
                                                                  texture.Description.Format);

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

                            // Create destination texture
                            var textureDest = new Texture2D(texture.Device, new Texture2DDescription
                            {
                                CpuAccessFlags    = CpuAccessFlags.None,   // CpuAccessFlags.Write | CpuAccessFlags.Read,
                                Format            = Format.R8G8B8A8_UNorm, // Supports BMP/PNG
                                Height            = regionToCapture.Height,
                                Usage             = ResourceUsage.Default, // ResourceUsage.Staging,
                                Width             = regionToCapture.Width,
                                ArraySize         = 1,                     //texture.Description.ArraySize,
                                SampleDescription = new 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.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
                            var request = Request.Clone();
                            // this.Request gets set to null, so copy the Request for use in the thread
                            ThreadPool.QueueUserWorkItem(delegate
                            {
                                //FileStream fs = new FileStream(@"c:\temp\temp.bmp", FileMode.Create);
                                //Texture2D.ToStream(testSubResourceCopy, ImageFileFormat.Bmp, fs);

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

                                    var startSendResponse = DateTime.Now;
                                    ProcessCapture(ms, request);
                                    this.DebugMessage("PresentHook: Send response time: " +
                                                      (DateTime.Now - startSendResponse));
                                }

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

                            // Make sure we free up the resolved texture if it was created
                            if (textureResolved != null)
                            {
                                textureResolved.Dispose();
                                textureResolved = null;
                            }
                        }

                        DebugMessage("PresentHook: Copy BackBuffer time: " + (DateTime.Now - startTime));
                        DebugMessage("PresentHook: Request End");
                    }
                    finally
                    {
                        // Prevent the request from being processed a second time
                        Request = null;
                    }
                }

                #endregion

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

                if (Config.ShowOverlay)
                {
                    using (var texture = Resource.FromSwapChain <Texture2D>(swapChain, 0))
                    {
                        if (FPS.GetFPS() >= 1)
                        {
                            var fd = new FontDescription
                            {
                                Height          = 16,
                                FaceName        = "Arial",
                                Italic          = false,
                                Width           = 0,
                                MipLevels       = 1,
                                CharacterSet    = FontCharacterSet.Default,
                                OutputPrecision = FontPrecision.Default,
                                Quality         = FontQuality.Antialiased,
                                PitchAndFamily  = FontPitchAndFamily.Default | FontPitchAndFamily.DontCare,
                                Weight          = FontWeight.Bold
                            };

                            // TODO: Font should not be created every frame!
                            using (var font = new Font(texture.Device, fd))
                            {
                                DrawText(font, new Vector2(5, 5), string.Format("{0:N0} fps", FPS.GetFPS()),
                                         new Color4(Color.Red.ToColor3()));

                                if (TextDisplay != null && TextDisplay.Display)
                                {
                                    DrawText(font, new Vector2(5, 25), TextDisplay.Text,
                                             new Color4(Color.Red.ToColor3(), (Math.Abs(1.0f - TextDisplay.Remaining))));
                                }
                            }
                        }
                    }
                }

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

            // 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
            swapChain.Present(syncInterval, flags);
            return(Result.Ok.Code);
        }
Example #2
0
 /// <summary>
 /// Copies data from the CPU to to a non-mappable subresource region.
 /// </summary>
 /// <param name="source">The source data.</param>
 /// <param name="resource">The destination resource.</param>
 /// <param name="subresource">The destination subresource.</param>
 public void UpdateSubresource(DataBox source, Resource resource, int subresource)
 {
     UpdateSubresource(resource, subresource, null, source.DataPointer, source.RowPitch, source.SlicePitch);
 }
Example #3
0
 /// <summary>
 /// Copies data from the CPU to to a non-mappable subresource region.
 /// </summary>
 /// <param name="source">The source data.</param>
 /// <param name="resource">The destination resource.</param>
 /// <param name="subresource">The destination subresource.</param>
 /// <param name="region">The destination region within the resource.</param>
 public void UpdateSubresource(DataBox source, Resource resource, int subresource, ResourceRegion region)
 {
     UpdateSubresource(resource, subresource, region, source.DataPointer, source.RowPitch, source.SlicePitch);
 }
Example #4
0
 /// <summary>
 /// Copy the entire contents of the source resource to the destination resource using the GPU.
 /// </summary>
 /// <remarks>
 /// This method is unusual in that it causes the GPU to perform the copy operation (similar to a memcpy by the CPU). As a result, it has a few restrictions designed for improving performance. For instance, the source and destination resources:  Must be different resources. Must be the same {{type}}. Must have identical dimensions (including width, height, depth, and size as appropriate). Will only be copied. CopyResource does not support any stretch, color key, blend, or format conversions. Must have compatible {{formats}}, which means the formats must be identical or at least from the same type group. For example, a DXGI_FORMAT_R32G32B32_FLOAT texture can be copied to an DXGI_FORMAT_R32G32B32_UINT texture since both of these formats are in the DXGI_FORMAT_R32G32B32_TYPELESS group. May not be currently {{mapped}}.   {{Immutable}}, and {{depth-stencil}} resources cannot be used as a destination.  Resources created with {{multisampling capability}} cannot be used as either a source or destination. The method is an asynchronous call which may be added to the command-buffer queue. This attempts to remove pipeline stalls that may occur when copying data. See {{performance considerations}} for more details. An application that only needs to copy a portion of the data in a resource should use <see cref="SharpDX.Direct3D10.Device.CopySubresourceRegion_"/> instead.   Differences between Direct3D 10 and Direct3D 10.1: Direct3D 10.1 enables depth-stencil resources to be used as either a source or destination. Direct3D 10.1 enables multisampled resources to be used as source and destination only if both source and destination have identical multisampled count and quality. If source and destination differ in multisampled count and quality or if the source is multisampled and the destination is not multisampled (or vice versa), the call to ID3D10Device::CopyResource fails. It is possible to copy between prestructured+typed resources and block-compressed textures. See {{Format Conversion using Direct3D 10.1}}.   ?
 /// </remarks>
 /// <param name="source">A reference to the source resource (see <see cref="SharpDX.Direct3D10.Resource"/>). </param>
 /// <param name="destination">A reference to the destination resource (see <see cref="SharpDX.Direct3D10.Resource"/>). </param>
 /// <unmanaged>void ID3D10Device::CopyResource([In] ID3D10Resource* pDstResource,[In] ID3D10Resource* pSrcResource)</unmanaged>
 public void CopyResource(Resource source, Resource destination)
 {
     CopyResource_(destination, source);
 }