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;
}
}
}