Bunch of Refresh API changes, plus more validation (#31)

Co-authored-by: TheSpydog <thespydog@noreply.example.org>
Co-committed-by: TheSpydog <thespydog@noreply.example.org>
pull/33/head
TheSpydog 2022-11-09 18:49:53 +00:00 committed by cosmonaut
parent 1b38f8606b
commit 02b0c12ad8
7 changed files with 48 additions and 115 deletions

View File

@ -16,6 +16,7 @@ namespace MoonWorks.Graphics
GraphicsPipeline currentGraphicsPipeline;
ComputePipeline currentComputePipeline;
bool renderPassActive;
SampleCount currentSampleCount;
// called from RefreshDevice
internal CommandBuffer(GraphicsDevice device, IntPtr handle)
@ -25,6 +26,7 @@ namespace MoonWorks.Graphics
currentGraphicsPipeline = null;
currentComputePipeline = null;
renderPassActive = false;
currentSampleCount = SampleCount.One;
}
// FIXME: we can probably use the NativeMemory functions to not have to generate arrays here
@ -55,7 +57,6 @@ namespace MoonWorks.Graphics
Refresh.Refresh_BeginRenderPass(
Device.Handle,
Handle,
IntPtr.Zero,
(IntPtr) pColorAttachmentInfos,
(uint) colorAttachmentInfos.Length,
IntPtr.Zero
@ -78,7 +79,7 @@ namespace MoonWorks.Graphics
)
{
#if DEBUG
AssertValidDepthAttachments(depthStencilAttachmentInfo);
AssertValidDepthAttachment(depthStencilAttachmentInfo);
AssertValidColorAttachments(colorAttachmentInfos, false);
#endif
@ -96,88 +97,6 @@ namespace MoonWorks.Graphics
Refresh.Refresh_BeginRenderPass(
Device.Handle,
Handle,
IntPtr.Zero,
pColorAttachmentInfos,
(uint) colorAttachmentInfos.Length,
&refreshDepthStencilAttachmentInfo
);
}
renderPassActive = true;
}
/// <summary>
/// Begins a render pass.
/// All render state, resource binding, and draw commands must be made within a render pass.
/// It is an error to call this after calling BeginRenderPass but before calling EndRenderPass.
/// </summary>
/// <param name="renderArea">The rectangle that should be drawn to on the attachments.</param>
/// <param name="colorAttachmentInfos">The color attachments to use in the render pass.</param>
public unsafe void BeginRenderPass(
in Rect renderArea,
params ColorAttachmentInfo[] colorAttachmentInfos
)
{
#if DEBUG
AssertValidColorAttachments(colorAttachmentInfos, true);
#endif
var refreshColorAttachmentInfos = new Refresh.ColorAttachmentInfo[colorAttachmentInfos.Length];
for (var i = 0; i < colorAttachmentInfos.Length; i += 1)
{
refreshColorAttachmentInfos[i] = colorAttachmentInfos[i].ToRefresh();
}
fixed (Refresh.ColorAttachmentInfo* pColorAttachmentInfos = refreshColorAttachmentInfos)
{
Refresh.Refresh_BeginRenderPass(
Device.Handle,
Handle,
renderArea.ToRefresh(),
(IntPtr) pColorAttachmentInfos,
(uint) colorAttachmentInfos.Length,
IntPtr.Zero
);
}
renderPassActive = true;
}
/// <summary>
/// Begins a render pass.
/// All render state, resource binding, and draw commands must be made within a render pass.
/// It is an error to call this after calling BeginRenderPass but before calling EndRenderPass.
/// </summary>
/// <param name="renderArea">The rectangle that should be drawn to on the attachments.</param>
/// <param name="depthStencilAttachmentInfo">The depth stencil attachment to use in the render pass.</param>
/// <param name="colorAttachmentInfos">The color attachments to use in the render pass.</param>
public unsafe void BeginRenderPass(
in Rect renderArea,
DepthStencilAttachmentInfo depthStencilAttachmentInfo,
params ColorAttachmentInfo[] colorAttachmentInfos
)
{
#if DEBUG
AssertValidDepthAttachments(depthStencilAttachmentInfo);
AssertValidColorAttachments(colorAttachmentInfos, false);
#endif
var refreshColorAttachmentInfos = new Refresh.ColorAttachmentInfo[colorAttachmentInfos.Length];
for (var i = 0; i < colorAttachmentInfos.Length; i += 1)
{
refreshColorAttachmentInfos[i] = colorAttachmentInfos[i].ToRefresh();
}
var refreshDepthStencilAttachmentInfo = depthStencilAttachmentInfo.ToRefresh();
fixed (Refresh.ColorAttachmentInfo* pColorAttachmentInfos = refreshColorAttachmentInfos)
{
Refresh.Refresh_BeginRenderPass(
Device.Handle,
Handle,
renderArea.ToRefresh(),
pColorAttachmentInfos,
(uint) colorAttachmentInfos.Length,
&refreshDepthStencilAttachmentInfo
@ -312,6 +231,15 @@ namespace MoonWorks.Graphics
GraphicsPipeline graphicsPipeline
)
{
#if DEBUG
AssertRenderPassActive();
if (graphicsPipeline.SampleCount != currentSampleCount)
{
throw new System.ArgumentException("The sample count of the bound GraphicsPipeline must match the sample count of the current render pass!");
}
#endif
Refresh.Refresh_BindGraphicsPipeline(
Device.Handle,
Handle,
@ -1073,6 +1001,8 @@ namespace MoonWorks.Graphics
throw new System.ArgumentException("Render pass must contain at least one attachment!");
}
currentSampleCount = (colorAttachmentInfos.Length > 0) ? colorAttachmentInfos[0].SampleCount : SampleCount.One;
if (colorAttachmentInfos.Length > 4)
{
throw new System.ArgumentException("Render pass cannot have more than 4 color attachments!");
@ -1090,10 +1020,15 @@ namespace MoonWorks.Graphics
{
throw new System.ArgumentException("Render pass color attachment UsageFlags must include TextureUsageFlags.ColorTarget!");
}
if (colorAttachmentInfos[i].SampleCount != currentSampleCount)
{
throw new System.ArgumentException("All color attachments in a render pass must have the same SampleCount!");
}
}
}
private void AssertValidDepthAttachments(DepthStencilAttachmentInfo depthStencilAttachmentInfo)
private void AssertValidDepthAttachment(DepthStencilAttachmentInfo depthStencilAttachmentInfo)
{
if (depthStencilAttachmentInfo.Texture == null ||
depthStencilAttachmentInfo.Texture.Handle == IntPtr.Zero)

View File

@ -110,10 +110,7 @@ namespace MoonWorks.Graphics
One,
Two,
Four,
Eight,
Sixteen,
ThirtyTwo,
SixtyFour
Eight
}
public enum CubeMapFace : uint

View File

@ -209,25 +209,35 @@ namespace MoonWorks.Graphics
public LoadOp LoadOp;
public StoreOp StoreOp;
public ColorAttachmentInfo(Texture texture, Color clearColor, StoreOp storeOp = StoreOp.Store)
public ColorAttachmentInfo(
Texture texture,
Color clearColor,
SampleCount sampleCount = SampleCount.One,
StoreOp storeOp = StoreOp.Store
)
{
Texture = texture;
Depth = 0;
Layer = 0;
Level = 0;
SampleCount = SampleCount.One;
SampleCount = sampleCount;
ClearColor = clearColor;
LoadOp = LoadOp.Clear;
StoreOp = storeOp;
}
public ColorAttachmentInfo(Texture texture, LoadOp loadOp = LoadOp.DontCare, StoreOp storeOp = StoreOp.Store)
public ColorAttachmentInfo(
Texture texture,
LoadOp loadOp = LoadOp.DontCare,
SampleCount sampleCount = SampleCount.One,
StoreOp storeOp = StoreOp.Store
)
{
Texture = texture;
Depth = 0;
Layer = 0;
Level = 0;
SampleCount = SampleCount.One;
SampleCount = sampleCount;
ClearColor = Color.White;
LoadOp = loadOp;
StoreOp = storeOp;
@ -344,16 +354,13 @@ namespace MoonWorks.Graphics
public struct ColorAttachmentDescription
{
public TextureFormat Format;
public SampleCount SampleCount;
public ColorAttachmentBlendState BlendState;
public ColorAttachmentDescription(
TextureFormat format,
ColorAttachmentBlendState blendState,
SampleCount sampleCount = SampleCount.One
ColorAttachmentBlendState blendState
) {
Format = format;
SampleCount = sampleCount;
BlendState = blendState;
}
}

View File

@ -14,6 +14,7 @@ namespace MoonWorks.Graphics
public GraphicsShaderInfo VertexShaderInfo { get; }
public GraphicsShaderInfo FragmentShaderInfo { get; }
internal SampleCount SampleCount { get; }
public unsafe GraphicsPipeline(
GraphicsDevice device,
@ -46,7 +47,6 @@ namespace MoonWorks.Graphics
for (var i = 0; i < attachmentInfo.ColorAttachmentDescriptions.Length; i += 1)
{
colorAttachmentDescriptions[i].format = (Refresh.TextureFormat) attachmentInfo.ColorAttachmentDescriptions[i].Format;
colorAttachmentDescriptions[i].sampleCount = (Refresh.SampleCount) attachmentInfo.ColorAttachmentDescriptions[i].SampleCount;
colorAttachmentDescriptions[i].blendState = attachmentInfo.ColorAttachmentDescriptions[i].BlendState.ToRefresh();
}
@ -112,6 +112,7 @@ namespace MoonWorks.Graphics
VertexShaderInfo = vertexShaderInfo;
FragmentShaderInfo = fragmentShaderInfo;
SampleCount = multisampleState.MultisampleCount;
}
}
}

View File

@ -15,7 +15,6 @@ namespace MoonWorks.Graphics
public TextureFormat Format { get; }
public bool IsCube { get; }
public uint LevelCount { get; }
public SampleCount SampleCount { get; }
public TextureUsageFlags UsageFlags { get; }
protected override Action<IntPtr, IntPtr> QueueDestroyFunction => Refresh.Refresh_QueueDestroyTexture;
@ -46,7 +45,6 @@ namespace MoonWorks.Graphics
textureCreateInfo.Format = TextureFormat.R8G8B8A8;
textureCreateInfo.IsCube = false;
textureCreateInfo.LevelCount = 1;
textureCreateInfo.SampleCount = SampleCount.One;
textureCreateInfo.UsageFlags = TextureUsageFlags.Sampler;
var texture = new Texture(device, textureCreateInfo);
@ -83,12 +81,12 @@ namespace MoonWorks.Graphics
if (isCube)
{
texture = CreateTextureCube(graphicsDevice, (uint) width, format, TextureUsageFlags.Sampler, SampleCount.One, (uint) levels);
texture = CreateTextureCube(graphicsDevice, (uint) width, format, TextureUsageFlags.Sampler, (uint) levels);
faces = 6;
}
else
{
texture = CreateTexture2D(graphicsDevice, (uint) width, (uint) height, format, TextureUsageFlags.Sampler, SampleCount.One, (uint) levels);
texture = CreateTexture2D(graphicsDevice, (uint) width, (uint) height, format, TextureUsageFlags.Sampler, (uint) levels);
faces = 1;
}
@ -124,7 +122,6 @@ namespace MoonWorks.Graphics
/// <param name="height">The height of the texture.</param>
/// <param name="format">The format of the texture.</param>
/// <param name="usageFlags">Specifies how the texture will be used.</param>
/// <param name="sampleCount">Specifies the multisample count.</param>
/// <param name="levelCount">Specifies the number of mip levels.</param>
public static Texture CreateTexture2D(
GraphicsDevice device,
@ -132,7 +129,6 @@ namespace MoonWorks.Graphics
uint height,
TextureFormat format,
TextureUsageFlags usageFlags,
SampleCount sampleCount = SampleCount.One,
uint levelCount = 1
)
{
@ -142,7 +138,6 @@ namespace MoonWorks.Graphics
Height = height,
Depth = 1,
IsCube = false,
SampleCount = sampleCount,
LevelCount = levelCount,
Format = format,
UsageFlags = usageFlags
@ -160,7 +155,6 @@ namespace MoonWorks.Graphics
/// <param name="depth">The depth of the texture.</param>
/// <param name="format">The format of the texture.</param>
/// <param name="usageFlags">Specifies how the texture will be used.</param>
/// <param name="sampleCount">Specifies the multisample count.</param>
/// <param name="levelCount">Specifies the number of mip levels.</param>
public static Texture CreateTexture3D(
GraphicsDevice device,
@ -169,7 +163,6 @@ namespace MoonWorks.Graphics
uint depth,
TextureFormat format,
TextureUsageFlags usageFlags,
SampleCount sampleCount = SampleCount.One,
uint levelCount = 1
)
{
@ -179,7 +172,6 @@ namespace MoonWorks.Graphics
Height = height,
Depth = depth,
IsCube = false,
SampleCount = sampleCount,
LevelCount = levelCount,
Format = format,
UsageFlags = usageFlags
@ -195,14 +187,12 @@ namespace MoonWorks.Graphics
/// <param name="size">The length of one side of the cube.</param>
/// <param name="format">The format of the texture.</param>
/// <param name="usageFlags">Specifies how the texture will be used.</param>
/// <param name="sampleCount">Specifies the multisample count.</param>
/// <param name="levelCount">Specifies the number of mip levels.</param>
public static Texture CreateTextureCube(
GraphicsDevice device,
uint size,
TextureFormat format,
TextureUsageFlags usageFlags,
SampleCount sampleCount = SampleCount.One,
uint levelCount = 1
)
{
@ -212,7 +202,6 @@ namespace MoonWorks.Graphics
Height = size,
Depth = 1,
IsCube = true,
SampleCount = sampleCount,
LevelCount = levelCount,
Format = format,
UsageFlags = usageFlags
@ -241,7 +230,6 @@ namespace MoonWorks.Graphics
Height = textureCreateInfo.Height;
Depth = textureCreateInfo.Depth;
IsCube = textureCreateInfo.IsCube;
SampleCount = textureCreateInfo.SampleCount;
LevelCount = textureCreateInfo.LevelCount;
UsageFlags = textureCreateInfo.UsageFlags;
}
@ -265,7 +253,6 @@ namespace MoonWorks.Graphics
Height = height;
Depth = 1;
IsCube = false;
SampleCount = SampleCount.One;
LevelCount = 1;
UsageFlags = TextureUsageFlags.ColorTarget;
}

View File

@ -13,5 +13,13 @@
MultisampleCount = SampleCount.One,
SampleMask = uint.MaxValue
};
public MultisampleState(
SampleCount sampleCount,
uint sampleMask = uint.MaxValue
) {
MultisampleCount = sampleCount;
SampleMask = sampleMask;
}
}
}

View File

@ -8,7 +8,6 @@ namespace MoonWorks.Graphics
public uint Height;
public uint Depth;
public bool IsCube;
public SampleCount SampleCount;
public uint LevelCount;
public TextureFormat Format;
public TextureUsageFlags UsageFlags;
@ -21,7 +20,6 @@ namespace MoonWorks.Graphics
height = Height,
depth = Depth,
isCube = Conversions.BoolToByte(IsCube),
sampleCount = (Refresh.SampleCount) SampleCount,
levelCount = LevelCount,
format = (Refresh.TextureFormat) Format,
usageFlags = (Refresh.TextureUsageFlags) UsageFlags