presentation ABI break

main
cosmonaut 2022-03-01 22:57:10 -08:00
parent 7328cbc13d
commit 81c882bd48
7 changed files with 65 additions and 222 deletions

@ -1 +1 @@
Subproject commit 61ec63b71f9fc3163ef5a8d985fbb53e3f02dbf9
Subproject commit d844fe56ee16e7e0e0ae4f4ff1814292e499dff7

View File

@ -52,12 +52,14 @@ namespace MoonWorks.Graphics
refreshColorAttachmentInfos[i] = colorAttachmentInfos[i].ToRefresh();
}
Rect renderArea = new Rect((int) colorAttachmentInfos[0].Texture.Width, (int) colorAttachmentInfos[0].Texture.Height);
fixed (Refresh.ColorAttachmentInfo* pColorAttachmentInfos = refreshColorAttachmentInfos)
{
Refresh.Refresh_BeginRenderPass(
Device.Handle,
Handle,
colorAttachmentInfos[0].RenderTarget.TextureSlice.Rectangle.ToRefresh(),
renderArea.ToRefresh(),
(IntPtr) pColorAttachmentInfos,
(uint) colorAttachmentInfos.Length,
IntPtr.Zero
@ -100,12 +102,14 @@ namespace MoonWorks.Graphics
var refreshDepthStencilAttachmentInfo = depthStencilAttachmentInfo.ToRefresh();
Rect renderArea = new Rect((int) colorAttachmentInfos[0].Texture.Width, (int) colorAttachmentInfos[0].Texture.Height);
fixed (Refresh.ColorAttachmentInfo* pColorAttachmentInfos = refreshColorAttachmentInfos)
{
Refresh.Refresh_BeginRenderPass(
Device.Handle,
Handle,
colorAttachmentInfos[0].RenderTarget.TextureSlice.Rectangle.ToRefresh(),
renderArea.ToRefresh(),
pColorAttachmentInfos,
(uint) colorAttachmentInfos.Length,
&refreshDepthStencilAttachmentInfo
@ -650,126 +654,19 @@ namespace MoonWorks.Graphics
}
/// <summary>
/// Prepares a texture to be presented to a window.
/// This particular variant of this method will present to the entire window area.
/// Acquires a swapchain texture.
/// This texture will be presented to the given window when the command buffer is submitted.
/// </summary>
/// <param name="texture">The texture to present.</param>
/// <param name="filter">The filter to use when the texture size differs from the window size.</param>
public void QueuePresent(
Texture texture,
Filter filter,
public Texture AcquireSwapchainTexture(
Window window
)
{
var refreshTextureSlice = new Refresh.TextureSlice
{
texture = texture.Handle,
rectangle = new Refresh.Rect
{
x = 0,
y = 0,
w = (int) texture.Width,
h = (int) texture.Height
},
layer = 0,
level = 0,
depth = 0
};
Refresh.Refresh_QueuePresent(
Device.Handle,
Handle,
refreshTextureSlice,
IntPtr.Zero,
(Refresh.Filter) filter,
window.Handle
);
}
/// <summary>
/// Prepares a texture slice to be presented to a window.
/// This particular variant of this method will present to the entire window area.
/// </summary>
/// <param name="textureSlice">The texture slice to present.</param>
/// <param name="filter">The filter to use when the texture size differs from the window size.</param>
public void QueuePresent(
in TextureSlice textureSlice,
Filter filter,
Window window
)
{
Refresh.Refresh_QueuePresent(
Device.Handle,
Handle,
textureSlice.ToRefreshTextureSlice(),
IntPtr.Zero,
(Refresh.Filter) filter,
window.Handle
);
}
/// <summary>
/// Prepares a texture to be presented to a window.
/// </summary>
/// <param name="texture">The texture to present.</param>
/// <param name="destinationRectangle">The area of the window to present to.</param>
/// <param name="filter">The filter to use when the texture size differs from the destination rectangle.</param>
public void QueuePresent(
in Texture texture,
in Rect destinationRectangle,
Filter filter,
Window window
)
{
var refreshRect = destinationRectangle.ToRefresh();
var refreshTextureSlice = new Refresh.TextureSlice
{
texture = texture.Handle,
rectangle = new Refresh.Rect
{
x = 0,
y = 0,
w = (int) texture.Width,
h = (int) texture.Height
},
layer = 0,
level = 0,
depth = 0
};
Refresh.Refresh_QueuePresent(
Device.Handle,
Handle,
refreshTextureSlice,
refreshRect,
(Refresh.Filter) filter,
window.Handle
);
}
/// <summary>
/// Prepares a texture slice to be presented to a window.
/// </summary>
/// <param name="textureSlice">The texture slice to present.</param>
/// <param name="destinationRectangle">The area of the window to present to.</param>
/// <param name="filter">The filter to use when the texture size differs from the destination rectangle.</param>
public void QueuePresent(
in TextureSlice textureSlice,
in Rect destinationRectangle,
Filter filter,
Window window
)
{
var refreshTextureSlice = textureSlice.ToRefreshTextureSlice();
var refreshRect = destinationRectangle.ToRefresh();
Refresh.Refresh_QueuePresent(
Device.Handle,
Handle,
refreshTextureSlice,
refreshRect,
(Refresh.Filter) filter,
window.Handle
return new Texture(
Device,
Refresh.Refresh_AcquireSwapchainTexture(Device.Handle, Handle, window.Handle),
(TextureFormat) Refresh.Refresh_GetSwapchainFormat(Device.Handle, window.Handle),
window.Width,
window.Height
);
}

View File

@ -60,6 +60,7 @@ namespace MoonWorks.Graphics
public enum TextureFormat
{
R8G8B8A8,
B8G8R8A8,
R5G6B5,
A1R5G5B5,
B4G4R4A4,

View File

@ -148,7 +148,11 @@ namespace MoonWorks.Graphics
[StructLayout(LayoutKind.Sequential)]
public struct ColorAttachmentInfo
{
public RenderTarget RenderTarget;
public Texture Texture;
public uint Depth;
public uint Layer;
public uint Level;
public SampleCount SampleCount;
public Color ClearColor;
public LoadOp LoadOp;
public StoreOp StoreOp;
@ -157,7 +161,11 @@ namespace MoonWorks.Graphics
{
return new Refresh.ColorAttachmentInfo
{
renderTarget = RenderTarget.Handle,
texture = Texture.Handle,
depth = Depth,
layer = Layer,
level = Level,
sampleCount = (Refresh.SampleCount) SampleCount,
clearColor = new Refresh.Vec4
{
x = ClearColor.R / 255f,
@ -174,8 +182,11 @@ namespace MoonWorks.Graphics
[StructLayout(LayoutKind.Sequential)]
public struct DepthStencilAttachmentInfo
{
public RenderTarget DepthStencilTarget;
public DepthStencilValue DepthStencilValue;
public Texture Texture;
public uint Depth;
public uint Layer;
public uint Level;
public DepthStencilValue DepthStencilClearValue;
public LoadOp LoadOp;
public StoreOp StoreOp;
public LoadOp StencilLoadOp;
@ -185,8 +196,11 @@ namespace MoonWorks.Graphics
{
return new Refresh.DepthStencilAttachmentInfo
{
depthStencilTarget = DepthStencilTarget.Handle,
depthStencilValue = DepthStencilValue.ToRefresh(),
texture = Texture.Handle,
depth = Depth,
layer = Layer,
level = Level,
depthStencilClearValue = DepthStencilClearValue.ToRefresh(),
loadOp = (Refresh.LoadOp) LoadOp,
storeOp = (Refresh.StoreOp) StoreOp,
stencilLoadOp = (Refresh.LoadOp) StencilLoadOp,

View File

@ -1,94 +0,0 @@
using System;
using RefreshCS;
namespace MoonWorks.Graphics
{
/// <summary>
/// A render target is a structure that wraps a texture so that it can be rendered to.
/// </summary>
public class RenderTarget : GraphicsResource
{
public TextureSlice TextureSlice { get; }
public TextureFormat Format => TextureSlice.Texture.Format;
public uint Width => (uint) TextureSlice.Rectangle.W;
public uint Height => (uint) TextureSlice.Rectangle.H;
protected override Action<IntPtr, IntPtr, IntPtr> QueueDestroyFunction => Refresh.Refresh_QueueDestroyRenderTarget;
/// <summary>
/// Creates a render target backed by a texture.
/// </summary>
/// <param name="device">An initialized GraphicsDevice.</param>
/// <param name="width">The width of the render target.</param>
/// <param name="height">The height of the render target.</param>
/// <param name="format">The format of the render target.</param>
/// <param name="canBeSampled">Whether the render target can be used by a sampler.</param>
/// <param name="sampleCount">The multisample count of the render target.</param>
/// <param name="levelCount">The mip level of the render target.</param>
/// <returns></returns>
public static RenderTarget CreateBackedRenderTarget(
GraphicsDevice device,
uint width,
uint height,
TextureFormat format,
bool canBeSampled,
SampleCount sampleCount = SampleCount.One,
uint levelCount = 1
)
{
TextureUsageFlags flags = 0;
if (
format == TextureFormat.D16 ||
format == TextureFormat.D32 ||
format == TextureFormat.D16S8 ||
format == TextureFormat.D32S8
)
{
flags |= TextureUsageFlags.DepthStencilTarget;
}
else
{
flags |= TextureUsageFlags.ColorTarget;
}
if (canBeSampled)
{
flags |= TextureUsageFlags.Sampler;
}
var texture = Texture.CreateTexture2D(
device,
width,
height,
format,
flags,
sampleCount,
levelCount
);
return new RenderTarget(device, new TextureSlice(texture), sampleCount);
}
/// <summary>
/// Creates a render target using a texture slice and an optional sample count.
/// </summary>
/// <param name="device">An initialized GraphicsDevice.</param>
/// <param name="textureSlice">The texture slice that will be rendered to.</param>
/// <param name="sampleCount">The desired multisample count of the render target.</param>
public RenderTarget(
GraphicsDevice device,
in TextureSlice textureSlice,
SampleCount sampleCount = SampleCount.One
) : base(device)
{
Handle = Refresh.Refresh_CreateRenderTarget(
device.Handle,
textureSlice.ToRefreshTextureSlice(),
(Refresh.SampleCount) sampleCount
);
TextureSlice = textureSlice;
}
}
}

View File

@ -56,11 +56,16 @@ namespace MoonWorks.Graphics
return texture;
}
public unsafe static void SavePNG(string path, int width, int height, byte[] pixels)
public unsafe static void SavePNG(string path, int width, int height, TextureFormat format, byte[] pixels)
{
if (format != TextureFormat.R8G8B8A8 && format != TextureFormat.B8G8R8A8)
{
throw new ArgumentException("Texture format must be RGBA8 or BGRA8!", "format");
}
fixed (byte* ptr = &pixels[0])
{
Refresh.Refresh_Image_SavePNG(path, width, height, (IntPtr) ptr);
Refresh.Refresh_Image_SavePNG(path, width, height, Conversions.BoolToByte(format == TextureFormat.B8G8R8A8), (IntPtr) ptr);
}
}
@ -191,8 +196,28 @@ namespace MoonWorks.Graphics
IsCube = textureCreateInfo.IsCube;
SampleCount = textureCreateInfo.SampleCount;
LevelCount = textureCreateInfo.LevelCount;
SampleCount = textureCreateInfo.SampleCount;
UsageFlags = textureCreateInfo.UsageFlags;
}
// Used by AcquireSwapchainTexture.
internal Texture(
GraphicsDevice device,
IntPtr handle,
TextureFormat format,
uint width,
uint height
) : base(device)
{
Handle = handle;
Format = format;
Width = width;
Height = height;
Depth = 1;
IsCube = false;
SampleCount = SampleCount.One;
LevelCount = 1;
UsageFlags = TextureUsageFlags.ColorTarget;
}
}
}