using System; using System.IO; using System.Reflection; using System.Windows.Forms; using Blacklight.Core; using Blacklight.Core.Cameras; using SharpDX.Direct3D9; namespace Blacklight.SharpDX9.PerformanceTests { /// /// Draws the comparison scenes and writes what the GPU produced for each to a file, so two builds of the shader can /// be checked for drawing the same picture. /// public static class ImageDump { public const string Argument = "--dump-images"; public const int Width = 640; public const int Height = 480; private const int BytesPerPixel = 8; /// /// Gets the scene target the last frame was drawn into, which the window handle keeps to itself. /// public static SharpDX9SceneTarget SceneTargetOf(SharpDX9WindowHandle handle) { FieldInfo field = typeof(SharpDX9WindowHandle).GetField( "_sceneTarget", BindingFlags.Instance | BindingFlags.NonPublic); return (SharpDX9SceneTarget)field.GetValue(handle); } /// /// Writes the scene target's linear half float RGBA pixels, row by row, to `path`. /// public static void Capture(SharpDX9WindowHandle handle, string path) { Device device = handle.Backend.GraphicsDevice; Surface target = SceneTargetOf(handle).Surface; SurfaceDescription description = target.Description; using (Surface readable = Surface.CreateOffscreenPlain( device, description.Width, description.Height, description.Format, Pool.SystemMemory)) { device.GetRenderTargetData(target, readable); SharpDX.DataRectangle rectangle = readable.LockRectangle(LockFlags.ReadOnly); try { var row = new byte[description.Width * BytesPerPixel]; using (var file = new FileStream(path, FileMode.Create)) { for (int y = 0; y < description.Height; ++y) { System.Runtime.InteropServices.Marshal.Copy( rectangle.DataPointer + y * rectangle.Pitch, row, 0, row.Length); file.Write(row, 0, row.Length); } } } finally { readable.UnlockRectangle(); } } } public static int Run(string directory) { Directory.CreateDirectory(directory); using (var window = new Form()) using (var module = new Module { VerticalSync = VerticalSyncMode.Off }) { window.ClientSize = new System.Drawing.Size(Width, Height); var handle = (SharpDX9WindowHandle)module.CreateDrawableSurfaceOnWindow(window.Handle); try { var context = new SceneContext { Handle = handle, Sheet = SpriteSheet.Create(handle, ImageScene.BuildFrames(premultiplied: false), new System.Drawing.Size(ImageScene.FrameSide, ImageScene.FrameSide), borderSize: 0), PremultipliedSheet = SpriteSheet.Create(handle, ImageScene.BuildFrames(premultiplied: true), new System.Drawing.Size(ImageScene.FrameSide, ImageScene.FrameSide), borderSize: 0), FillTexture = handle.CreateTexture(ImageScene.BuildChecker()), }; var camera = new ScreenSpaceCamera(handle); Console.WriteLine($"{handle.Width}x{handle.Height}"); foreach (ImageScene imageScene in ImageScene.All()) { Scene scene = imageScene.Build(context); handle.FrameReset(); handle.DrawScene(scene, camera); handle.SubmitDrawCalls(); Capture(handle, Path.Combine(directory, imageScene.Name + ".f16")); } } finally { handle.Dispose(); } } return 0; } } }