public void grab(IRenderDevice device, IDeviceContext context, ITexture texture, ConsumeTextureDelegate consume) { TextureDesc desc = texture.GetDesc(); // Create staging texture if needed if (null == stagingTexture || stagingDesc.Size != desc.Size || stagingDesc.Format != desc.Format) { ComUtils.clear(ref stagingTexture); desc.Type = ResourceDimension.Tex2d; desc.BindFlags = BindFlags.None; desc.CPUAccessFlags = CpuAccessFlags.Read; desc.Usage = Usage.Staging; stagingTexture = device.CreateTexture(ref desc, "ScreenGrabber staging"); stagingDesc = desc; } // In D3D12, Diligent engine fails instead of waiting for GPU. Need to wait manually, need a fence for that. if (RuntimeEnvironment.runningWindows && null == fence) { var fd = new FenceDesc(false); fence = device.CreateFence(ref fd); } // Finish the rendering, if any waitForGpu(context); // Unset the targets context.SetRenderTargets(0, null, null); waitForGpu(context); // Copy source texture to staging context.copyTexture(stagingTexture, texture); waitForGpu(context); // Map the texture Box box = new Box(false) { MaxX = desc.Size.cx, MaxY = desc.Size.cy }; MappedTextureSubresource mapped = context.MapTextureSubresource(stagingTexture, 0, 0, MapType.Read, MapFlags.DoNotWait, ref box); try { consume(desc.Format, desc.Size, mapped); } finally { context.UnmapTextureSubresource(stagingTexture, 0, 0); } }