starting graphics layer restructuring
parent
cc7cae9d6b
commit
8b35b6b0b7
|
@ -4,12 +4,12 @@
|
||||||
[submodule "lib/FAudio"]
|
[submodule "lib/FAudio"]
|
||||||
path = lib/FAudio
|
path = lib/FAudio
|
||||||
url = https://github.com/FNA-XNA/FAudio.git
|
url = https://github.com/FNA-XNA/FAudio.git
|
||||||
[submodule "lib/RefreshCS"]
|
|
||||||
path = lib/RefreshCS
|
|
||||||
url = https://gitea.moonside.games/MoonsideGames/RefreshCS.git
|
|
||||||
[submodule "lib/WellspringCS"]
|
[submodule "lib/WellspringCS"]
|
||||||
path = lib/WellspringCS
|
path = lib/WellspringCS
|
||||||
url = https://gitea.moonside.games/MoonsideGames/WellspringCS.git
|
url = https://gitea.moonside.games/MoonsideGames/WellspringCS.git
|
||||||
[submodule "lib/dav1dfile"]
|
[submodule "lib/dav1dfile"]
|
||||||
path = lib/dav1dfile
|
path = lib/dav1dfile
|
||||||
url = https://github.com/MoonsideGames/dav1dfile.git
|
url = https://github.com/MoonsideGames/dav1dfile.git
|
||||||
|
[submodule "SDL2_gpuCS"]
|
||||||
|
path = lib/SDL2_gpuCS
|
||||||
|
url = https://github.com/MoonsideGames/SDL2_gpuCS.git
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="lib\FAudio\csharp\FAudio.cs" />
|
<Compile Include="lib\FAudio\csharp\FAudio.cs" />
|
||||||
<Compile Include="lib\RefreshCS\src\Refresh.cs" />
|
<Compile Include="lib\SDL2_gpuCS\SDL2_gpuCS.cs" />
|
||||||
<Compile Include="lib\SDL2-CS\src\SDL2.cs" />
|
<Compile Include="lib\SDL2-CS\src\SDL2.cs" />
|
||||||
<Compile Include="lib\WellspringCS\WellspringCS.cs" />
|
<Compile Include="lib\WellspringCS\WellspringCS.cs" />
|
||||||
<Compile Include="lib\dav1dfile\csharp\dav1dfile.cs" />
|
<Compile Include="lib\dav1dfile\csharp\dav1dfile.cs" />
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
Subproject commit b92ecb60e3f60c3cce694477cbde381449759c58
|
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit b3cf918f900a24d131b4eb130a87dd12b4e4ca8c
|
|
@ -1,21 +1,19 @@
|
||||||
using RefreshCS;
|
using SDL2_gpuCS;
|
||||||
|
namespace MoonWorks.Graphics;
|
||||||
|
|
||||||
namespace MoonWorks.Graphics
|
/// <summary>
|
||||||
{
|
/// A buffer-offset pair to be used when binding buffers.
|
||||||
/// <summary>
|
/// </summary>
|
||||||
/// A buffer-offset pair to be used when binding vertex or index buffers.
|
public readonly record struct BufferBinding(
|
||||||
/// </summary>
|
|
||||||
public readonly record struct BufferBinding(
|
|
||||||
GpuBuffer Buffer,
|
GpuBuffer Buffer,
|
||||||
uint Offset
|
uint Offset
|
||||||
) {
|
) {
|
||||||
public Refresh.BufferBinding ToRefresh()
|
public SDL_Gpu.BufferBinding ToRefresh()
|
||||||
{
|
{
|
||||||
return new Refresh.BufferBinding
|
return new SDL_Gpu.BufferBinding
|
||||||
{
|
{
|
||||||
gpuBuffer = Buffer.Handle,
|
Buffer = Buffer.Handle,
|
||||||
offset = Offset
|
Offset = Offset
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,29 +1,29 @@
|
||||||
using RefreshCS;
|
using SDL2_gpuCS;
|
||||||
|
|
||||||
namespace MoonWorks.Graphics
|
namespace MoonWorks.Graphics;
|
||||||
{
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Binding specification to be used when binding buffers for compute shaders.
|
/// Binding specification to be used when binding buffers for compute shaders.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="GpuBuffer">The GpuBuffer to bind.</param>
|
/// <param name="GpuBuffer">The GpuBuffer to bind.</param>
|
||||||
/// <param name="WriteOption">
|
/// <param name="WriteOption">
|
||||||
/// Specifies data dependency behavior when this buffer is written to in the shader. <br/>
|
/// Specifies data dependency behavior when this buffer is written to in the shader. <br/>
|
||||||
///
|
///
|
||||||
/// Cycle:
|
/// Cycle:
|
||||||
/// If this buffer has been used in commands that have not finished,
|
/// If this buffer has been used in commands that have not finished,
|
||||||
/// the implementation may choose to prevent a dependency on those commands
|
/// the implementation may choose to prevent a dependency on those commands
|
||||||
/// at the cost of increased memory usage.
|
/// at the cost of increased memory usage.
|
||||||
/// You may NOT assume that any of the previous data is retained.
|
/// You may NOT assume that any of the previous data is retained.
|
||||||
/// This may prevent stalls when frequently updating a resource. <br />
|
/// This may prevent stalls when frequently updating a resource. <br />
|
||||||
///
|
///
|
||||||
/// SafeOverwrite:
|
/// SafeOverwrite:
|
||||||
/// Overwrites the data safely using a GPU memory barrier.
|
/// Overwrites the data safely using a GPU memory barrier.
|
||||||
/// </param>
|
/// </param>
|
||||||
public readonly record struct ComputeBufferBinding(
|
public readonly record struct ComputeBufferBinding(
|
||||||
GpuBuffer GpuBuffer,
|
GpuBuffer GpuBuffer,
|
||||||
WriteOptions WriteOption
|
WriteOptions WriteOption
|
||||||
) {
|
) {
|
||||||
public Refresh.ComputeBufferBinding ToRefresh()
|
public SDL_Gpu.BufferBinding ToRefresh()
|
||||||
{
|
{
|
||||||
return new Refresh.ComputeBufferBinding
|
return new Refresh.ComputeBufferBinding
|
||||||
{
|
{
|
||||||
|
@ -31,5 +31,4 @@ namespace MoonWorks.Graphics
|
||||||
writeOption = (Refresh.WriteOptions) WriteOption
|
writeOption = (Refresh.WriteOptions) WriteOption
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using RefreshCS;
|
using SDL2_gpuCS;
|
||||||
|
|
||||||
namespace MoonWorks.Graphics
|
namespace MoonWorks.Graphics
|
||||||
{
|
{
|
||||||
|
@ -9,12 +9,12 @@ namespace MoonWorks.Graphics
|
||||||
Texture Texture,
|
Texture Texture,
|
||||||
Sampler Sampler
|
Sampler Sampler
|
||||||
) {
|
) {
|
||||||
public Refresh.TextureSamplerBinding ToRefresh()
|
public SDL_Gpu.TextureSamplerBinding ToSDL()
|
||||||
{
|
{
|
||||||
return new Refresh.TextureSamplerBinding
|
return new SDL_Gpu.TextureSamplerBinding
|
||||||
{
|
{
|
||||||
texture = Texture.Handle,
|
Texture = Texture.Handle,
|
||||||
sampler = Sampler.Handle
|
Sampler = Sampler.Handle
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using RefreshCS;
|
using SDL2_gpuCS;
|
||||||
|
|
||||||
namespace MoonWorks.Graphics
|
namespace MoonWorks.Graphics;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Command buffers are used to apply render state and issue draw calls.
|
||||||
|
/// NOTE: it is not recommended to hold references to command buffers long term.
|
||||||
|
/// </summary>
|
||||||
|
public class CommandBuffer
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Command buffers are used to apply render state and issue draw calls.
|
|
||||||
/// NOTE: it is not recommended to hold references to command buffers long term.
|
|
||||||
/// </summary>
|
|
||||||
public class CommandBuffer
|
|
||||||
{
|
|
||||||
public GraphicsDevice Device { get; }
|
public GraphicsDevice Device { get; }
|
||||||
public IntPtr Handle { get; internal set; }
|
public IntPtr Handle { get; internal set; }
|
||||||
|
|
||||||
|
@ -101,8 +101,7 @@ namespace MoonWorks.Graphics
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
var texturePtr = Refresh.Refresh_AcquireSwapchainTexture(
|
var texturePtr = SDL_Gpu.SDL_GpuAcquireSwapchainTexture(
|
||||||
Device.Handle,
|
|
||||||
Handle,
|
Handle,
|
||||||
window.Handle,
|
window.Handle,
|
||||||
out var width,
|
out var width,
|
||||||
|
@ -143,11 +142,10 @@ namespace MoonWorks.Graphics
|
||||||
AssertColorTarget(colorAttachmentInfo);
|
AssertColorTarget(colorAttachmentInfo);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
var refreshColorAttachmentInfos = stackalloc Refresh.ColorAttachmentInfo[1];
|
var refreshColorAttachmentInfos = stackalloc SDL_Gpu.ColorAttachmentInfo[1];
|
||||||
refreshColorAttachmentInfos[0] = colorAttachmentInfo.ToRefresh();
|
refreshColorAttachmentInfos[0] = colorAttachmentInfo.ToRefresh();
|
||||||
|
|
||||||
Refresh.Refresh_BeginRenderPass(
|
SDL_Gpu.SDL_GpuBeginRenderPass(
|
||||||
Device.Handle,
|
|
||||||
Handle,
|
Handle,
|
||||||
(IntPtr) refreshColorAttachmentInfos,
|
(IntPtr) refreshColorAttachmentInfos,
|
||||||
1,
|
1,
|
||||||
|
@ -577,426 +575,6 @@ namespace MoonWorks.Graphics
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Binds a graphics pipeline so that rendering work may be performed.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="graphicsPipeline">The graphics pipeline to bind.</param>
|
|
||||||
public void BindGraphicsPipeline(
|
|
||||||
GraphicsPipeline graphicsPipeline
|
|
||||||
) {
|
|
||||||
#if DEBUG
|
|
||||||
AssertNotSubmitted();
|
|
||||||
AssertRenderPassActive();
|
|
||||||
AssertRenderPassPipelineFormatMatch(graphicsPipeline);
|
|
||||||
|
|
||||||
if (colorAttachmentCount > 0)
|
|
||||||
{
|
|
||||||
if (graphicsPipeline.SampleCount != colorAttachmentSampleCount)
|
|
||||||
{
|
|
||||||
throw new System.InvalidOperationException($"Sample count mismatch! Graphics pipeline sample count: {graphicsPipeline.SampleCount}, Color attachment sample count: {colorAttachmentSampleCount}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasDepthStencilAttachment)
|
|
||||||
{
|
|
||||||
if (graphicsPipeline.SampleCount != depthStencilAttachmentSampleCount)
|
|
||||||
{
|
|
||||||
throw new System.InvalidOperationException($"Sample count mismatch! Graphics pipeline sample count: {graphicsPipeline.SampleCount}, Depth stencil attachment sample count: {depthStencilAttachmentSampleCount}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Refresh.Refresh_BindGraphicsPipeline(
|
|
||||||
Device.Handle,
|
|
||||||
Handle,
|
|
||||||
graphicsPipeline.Handle
|
|
||||||
);
|
|
||||||
|
|
||||||
#if DEBUG
|
|
||||||
currentGraphicsPipeline = graphicsPipeline;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets the viewport. Only valid during a render pass.
|
|
||||||
/// </summary>
|
|
||||||
public void SetViewport(in Viewport viewport)
|
|
||||||
{
|
|
||||||
#if DEBUG
|
|
||||||
AssertNotSubmitted();
|
|
||||||
AssertRenderPassActive();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Refresh.Refresh_SetViewport(
|
|
||||||
Device.Handle,
|
|
||||||
Handle,
|
|
||||||
viewport.ToRefresh()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets the scissor area. Only valid during a render pass.
|
|
||||||
/// </summary>
|
|
||||||
public void SetScissor(in Rect scissor)
|
|
||||||
{
|
|
||||||
#if DEBUG
|
|
||||||
AssertNotSubmitted();
|
|
||||||
AssertRenderPassActive();
|
|
||||||
|
|
||||||
if (scissor.X < 0 || scissor.Y < 0 || scissor.W <= 0 || scissor.H <= 0)
|
|
||||||
{
|
|
||||||
throw new System.ArgumentOutOfRangeException("Scissor position cannot be negative and dimensions must be positive!");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Refresh.Refresh_SetScissor(
|
|
||||||
Device.Handle,
|
|
||||||
Handle,
|
|
||||||
scissor.ToRefresh()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Binds vertex buffers to be used by subsequent draw calls.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="bufferBinding">Buffer to bind and associated offset.</param>
|
|
||||||
/// <param name="firstBinding">The index of the first vertex input binding whose state is updated by the command.</param>
|
|
||||||
public unsafe void BindVertexBuffers(
|
|
||||||
in BufferBinding bufferBinding,
|
|
||||||
uint firstBinding = 0
|
|
||||||
) {
|
|
||||||
#if DEBUG
|
|
||||||
AssertNotSubmitted();
|
|
||||||
AssertGraphicsPipelineBound();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
var bindingArray = stackalloc Refresh.BufferBinding[1];
|
|
||||||
bindingArray[0] = bufferBinding.ToRefresh();
|
|
||||||
|
|
||||||
Refresh.Refresh_BindVertexBuffers(
|
|
||||||
Device.Handle,
|
|
||||||
Handle,
|
|
||||||
firstBinding,
|
|
||||||
1,
|
|
||||||
bindingArray
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Binds vertex buffers to be used by subsequent draw calls.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="bufferBindingOne">Buffer to bind and associated offset.</param>
|
|
||||||
/// <param name="bufferBindingTwo">Buffer to bind and associated offset.</param>
|
|
||||||
/// <param name="firstBinding">The index of the first vertex input binding whose state is updated by the command.</param>
|
|
||||||
public unsafe void BindVertexBuffers(
|
|
||||||
in BufferBinding bufferBindingOne,
|
|
||||||
in BufferBinding bufferBindingTwo,
|
|
||||||
uint firstBinding = 0
|
|
||||||
) {
|
|
||||||
#if DEBUG
|
|
||||||
AssertNotSubmitted();
|
|
||||||
AssertGraphicsPipelineBound();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
var bindingArray = stackalloc Refresh.BufferBinding[2];
|
|
||||||
bindingArray[0] = bufferBindingOne.ToRefresh();
|
|
||||||
bindingArray[1] = bufferBindingTwo.ToRefresh();
|
|
||||||
|
|
||||||
Refresh.Refresh_BindVertexBuffers(
|
|
||||||
Device.Handle,
|
|
||||||
Handle,
|
|
||||||
firstBinding,
|
|
||||||
2,
|
|
||||||
bindingArray
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Binds vertex buffers to be used by subsequent draw calls.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="bufferBindingOne">Buffer to bind and associated offset.</param>
|
|
||||||
/// <param name="bufferBindingTwo">Buffer to bind and associated offset.</param>
|
|
||||||
/// <param name="bufferBindingThree">Buffer to bind and associated offset.</param>
|
|
||||||
/// <param name="firstBinding">The index of the first vertex input binding whose state is updated by the command.</param>
|
|
||||||
public unsafe void BindVertexBuffers(
|
|
||||||
in BufferBinding bufferBindingOne,
|
|
||||||
in BufferBinding bufferBindingTwo,
|
|
||||||
in BufferBinding bufferBindingThree,
|
|
||||||
uint firstBinding = 0
|
|
||||||
) {
|
|
||||||
#if DEBUG
|
|
||||||
AssertNotSubmitted();
|
|
||||||
AssertGraphicsPipelineBound();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
var bindingArray = stackalloc Refresh.BufferBinding[3];
|
|
||||||
bindingArray[0] = bufferBindingOne.ToRefresh();
|
|
||||||
bindingArray[1] = bufferBindingTwo.ToRefresh();
|
|
||||||
bindingArray[2] = bufferBindingThree.ToRefresh();
|
|
||||||
|
|
||||||
Refresh.Refresh_BindVertexBuffers(
|
|
||||||
Device.Handle,
|
|
||||||
Handle,
|
|
||||||
firstBinding,
|
|
||||||
3,
|
|
||||||
bindingArray
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Binds vertex buffers to be used by subsequent draw calls.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="bufferBindingOne">Buffer to bind and associated offset.</param>
|
|
||||||
/// <param name="bufferBindingTwo">Buffer to bind and associated offset.</param>
|
|
||||||
/// <param name="bufferBindingThree">Buffer to bind and associated offset.</param>
|
|
||||||
/// <param name="bufferBindingFour">Buffer to bind and associated offset.</param>
|
|
||||||
/// <param name="firstBinding">The index of the first vertex input binding whose state is updated by the command.</param>
|
|
||||||
public unsafe void BindVertexBuffers(
|
|
||||||
in BufferBinding bufferBindingOne,
|
|
||||||
in BufferBinding bufferBindingTwo,
|
|
||||||
in BufferBinding bufferBindingThree,
|
|
||||||
in BufferBinding bufferBindingFour,
|
|
||||||
uint firstBinding = 0
|
|
||||||
) {
|
|
||||||
#if DEBUG
|
|
||||||
AssertNotSubmitted();
|
|
||||||
AssertGraphicsPipelineBound();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
var bindingArray = stackalloc Refresh.BufferBinding[4];
|
|
||||||
bindingArray[0] = bufferBindingOne.ToRefresh();
|
|
||||||
bindingArray[1] = bufferBindingTwo.ToRefresh();
|
|
||||||
bindingArray[2] = bufferBindingThree.ToRefresh();
|
|
||||||
bindingArray[3] = bufferBindingFour.ToRefresh();
|
|
||||||
|
|
||||||
Refresh.Refresh_BindVertexBuffers(
|
|
||||||
Device.Handle,
|
|
||||||
Handle,
|
|
||||||
firstBinding,
|
|
||||||
4,
|
|
||||||
bindingArray
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Binds vertex buffers to be used by subsequent draw calls.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="bufferBindings">Spawn of buffers to bind and their associated offsets.</param>
|
|
||||||
/// <param name="firstBinding">The index of the first vertex input binding whose state is updated by the command.</param>
|
|
||||||
public unsafe void BindVertexBuffers(
|
|
||||||
in Span<BufferBinding> bufferBindings,
|
|
||||||
uint firstBinding = 0
|
|
||||||
) {
|
|
||||||
#if DEBUG
|
|
||||||
AssertNotSubmitted();
|
|
||||||
AssertGraphicsPipelineBound();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Refresh.BufferBinding* bufferBindingsArray = (Refresh.BufferBinding*) NativeMemory.Alloc((nuint) (Marshal.SizeOf<Refresh.BufferBinding>() * bufferBindings.Length));
|
|
||||||
|
|
||||||
for (var i = 0; i < bufferBindings.Length; i += 1)
|
|
||||||
{
|
|
||||||
bufferBindingsArray[i] = bufferBindings[i].ToRefresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
Refresh.Refresh_BindVertexBuffers(
|
|
||||||
Device.Handle,
|
|
||||||
Handle,
|
|
||||||
firstBinding,
|
|
||||||
(uint) bufferBindings.Length,
|
|
||||||
bufferBindingsArray
|
|
||||||
);
|
|
||||||
|
|
||||||
NativeMemory.Free(bufferBindingsArray);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Binds an index buffer to be used by subsequent draw calls.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="indexBuffer">The index buffer to bind.</param>
|
|
||||||
/// <param name="indexElementSize">The size in bytes of the index buffer elements.</param>
|
|
||||||
/// <param name="offset">The offset index for the buffer.</param>
|
|
||||||
public void BindIndexBuffer(
|
|
||||||
BufferBinding bufferBinding,
|
|
||||||
IndexElementSize indexElementSize
|
|
||||||
)
|
|
||||||
{
|
|
||||||
#if DEBUG
|
|
||||||
AssertNotSubmitted();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Refresh.Refresh_BindIndexBuffer(
|
|
||||||
Device.Handle,
|
|
||||||
Handle,
|
|
||||||
bufferBinding.ToRefresh(),
|
|
||||||
(Refresh.IndexElementSize) indexElementSize
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Binds samplers to be used by the vertex shader.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="textureSamplerBindings">The texture-sampler to bind.</param>
|
|
||||||
public unsafe void BindVertexSamplers(
|
|
||||||
in TextureSamplerBinding textureSamplerBinding
|
|
||||||
) {
|
|
||||||
#if DEBUG
|
|
||||||
AssertNotSubmitted();
|
|
||||||
AssertGraphicsPipelineBound();
|
|
||||||
AssertVertexSamplerCount(1);
|
|
||||||
AssertTextureSamplerBindingNonNull(textureSamplerBinding);
|
|
||||||
AssertTextureBindingUsageFlags(textureSamplerBinding.Texture);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
var bindingArray = stackalloc Refresh.TextureSamplerBinding[1];
|
|
||||||
bindingArray[0] = textureSamplerBinding.ToRefresh();
|
|
||||||
|
|
||||||
Refresh.Refresh_BindVertexSamplers(
|
|
||||||
Device.Handle,
|
|
||||||
Handle,
|
|
||||||
bindingArray
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Binds samplers to be used by the vertex shader.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="textureSamplerBindingOne">The first texture-sampler to bind.</param>
|
|
||||||
/// <param name="textureSamplerBindingTwo">The second texture-sampler to bind.</param>
|
|
||||||
public unsafe void BindVertexSamplers(
|
|
||||||
in TextureSamplerBinding textureSamplerBindingOne,
|
|
||||||
in TextureSamplerBinding textureSamplerBindingTwo
|
|
||||||
) {
|
|
||||||
#if DEBUG
|
|
||||||
AssertNotSubmitted();
|
|
||||||
AssertGraphicsPipelineBound();
|
|
||||||
AssertVertexSamplerCount(2);
|
|
||||||
AssertTextureSamplerBindingNonNull(textureSamplerBindingOne);
|
|
||||||
AssertTextureSamplerBindingNonNull(textureSamplerBindingTwo);
|
|
||||||
AssertTextureBindingUsageFlags(textureSamplerBindingOne.Texture);
|
|
||||||
AssertTextureBindingUsageFlags(textureSamplerBindingTwo.Texture);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
var bindingArray = stackalloc Refresh.TextureSamplerBinding[2];
|
|
||||||
bindingArray[0] = textureSamplerBindingOne.ToRefresh();
|
|
||||||
bindingArray[1] = textureSamplerBindingTwo.ToRefresh();
|
|
||||||
|
|
||||||
Refresh.Refresh_BindVertexSamplers(
|
|
||||||
Device.Handle,
|
|
||||||
Handle,
|
|
||||||
bindingArray
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Binds samplers to be used by the vertex shader.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="textureSamplerBindingOne">The first texture-sampler to bind.</param>
|
|
||||||
/// <param name="textureSamplerBindingTwo">The second texture-sampler to bind.</param>
|
|
||||||
/// <param name="textureSamplerBindingThree">The third texture-sampler to bind.</param>
|
|
||||||
public unsafe void BindVertexSamplers(
|
|
||||||
in TextureSamplerBinding textureSamplerBindingOne,
|
|
||||||
in TextureSamplerBinding textureSamplerBindingTwo,
|
|
||||||
in TextureSamplerBinding textureSamplerBindingThree
|
|
||||||
) {
|
|
||||||
#if DEBUG
|
|
||||||
AssertNotSubmitted();
|
|
||||||
AssertGraphicsPipelineBound();
|
|
||||||
AssertVertexSamplerCount(3);
|
|
||||||
AssertTextureSamplerBindingNonNull(textureSamplerBindingOne);
|
|
||||||
AssertTextureSamplerBindingNonNull(textureSamplerBindingTwo);
|
|
||||||
AssertTextureSamplerBindingNonNull(textureSamplerBindingThree);
|
|
||||||
AssertTextureBindingUsageFlags(textureSamplerBindingOne.Texture);
|
|
||||||
AssertTextureBindingUsageFlags(textureSamplerBindingTwo.Texture);
|
|
||||||
AssertTextureBindingUsageFlags(textureSamplerBindingThree.Texture);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
var bindingArray = stackalloc Refresh.TextureSamplerBinding[3];
|
|
||||||
bindingArray[0] = textureSamplerBindingOne.ToRefresh();
|
|
||||||
bindingArray[1] = textureSamplerBindingTwo.ToRefresh();
|
|
||||||
bindingArray[2] = textureSamplerBindingThree.ToRefresh();
|
|
||||||
|
|
||||||
Refresh.Refresh_BindVertexSamplers(
|
|
||||||
Device.Handle,
|
|
||||||
Handle,
|
|
||||||
bindingArray
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Binds samplers to be used by the vertex shader.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="textureSamplerBindingOne">The first texture-sampler to bind.</param>
|
|
||||||
/// <param name="textureSamplerBindingTwo">The second texture-sampler to bind.</param>
|
|
||||||
/// <param name="textureSamplerBindingThree">The third texture-sampler to bind.</param>
|
|
||||||
/// <param name="textureSamplerBindingThree">The fourth texture-sampler to bind.</param>
|
|
||||||
public unsafe void BindVertexSamplers(
|
|
||||||
in TextureSamplerBinding textureSamplerBindingOne,
|
|
||||||
in TextureSamplerBinding textureSamplerBindingTwo,
|
|
||||||
in TextureSamplerBinding textureSamplerBindingThree,
|
|
||||||
in TextureSamplerBinding textureSamplerBindingFour
|
|
||||||
) {
|
|
||||||
#if DEBUG
|
|
||||||
AssertNotSubmitted();
|
|
||||||
AssertGraphicsPipelineBound();
|
|
||||||
AssertVertexSamplerCount(4);
|
|
||||||
AssertTextureSamplerBindingNonNull(textureSamplerBindingOne);
|
|
||||||
AssertTextureSamplerBindingNonNull(textureSamplerBindingTwo);
|
|
||||||
AssertTextureSamplerBindingNonNull(textureSamplerBindingThree);
|
|
||||||
AssertTextureSamplerBindingNonNull(textureSamplerBindingFour);
|
|
||||||
AssertTextureBindingUsageFlags(textureSamplerBindingOne.Texture);
|
|
||||||
AssertTextureBindingUsageFlags(textureSamplerBindingTwo.Texture);
|
|
||||||
AssertTextureBindingUsageFlags(textureSamplerBindingThree.Texture);
|
|
||||||
AssertTextureBindingUsageFlags(textureSamplerBindingFour.Texture);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
var bindingArray = stackalloc Refresh.TextureSamplerBinding[4];
|
|
||||||
bindingArray[0] = textureSamplerBindingOne.ToRefresh();
|
|
||||||
bindingArray[1] = textureSamplerBindingTwo.ToRefresh();
|
|
||||||
bindingArray[2] = textureSamplerBindingThree.ToRefresh();
|
|
||||||
bindingArray[3] = textureSamplerBindingFour.ToRefresh();
|
|
||||||
|
|
||||||
Refresh.Refresh_BindVertexSamplers(
|
|
||||||
Device.Handle,
|
|
||||||
Handle,
|
|
||||||
bindingArray
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Binds samplers to be used by the vertex shader.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="textureSamplerBindings">The texture-sampler pairs to bind.</param>
|
|
||||||
public unsafe void BindVertexSamplers(
|
|
||||||
in Span<TextureSamplerBinding> textureSamplerBindings
|
|
||||||
) {
|
|
||||||
#if DEBUG
|
|
||||||
AssertNotSubmitted();
|
|
||||||
AssertGraphicsPipelineBound();
|
|
||||||
AssertVertexSamplerCount(textureSamplerBindings.Length);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Refresh.TextureSamplerBinding* bindingsArray = (Refresh.TextureSamplerBinding*) NativeMemory.Alloc((nuint) (Marshal.SizeOf<Refresh.TextureSamplerBinding>() * textureSamplerBindings.Length));
|
|
||||||
|
|
||||||
for (var i = 0; i < textureSamplerBindings.Length; i += 1)
|
|
||||||
{
|
|
||||||
#if DEBUG
|
|
||||||
AssertTextureSamplerBindingNonNull(textureSamplerBindings[i]);
|
|
||||||
AssertTextureBindingUsageFlags(textureSamplerBindings[i].Texture);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bindingsArray[i] = textureSamplerBindings[i].ToRefresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
Refresh.Refresh_BindVertexSamplers(
|
|
||||||
Device.Handle,
|
|
||||||
Handle,
|
|
||||||
bindingsArray
|
|
||||||
);
|
|
||||||
|
|
||||||
NativeMemory.Free(bindingsArray);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Binds samplers to be used by the fragment shader.
|
/// Binds samplers to be used by the fragment shader.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -2079,51 +1657,6 @@ namespace MoonWorks.Graphics
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AssertRenderPassPipelineFormatMatch(GraphicsPipeline graphicsPipeline)
|
|
||||||
{
|
|
||||||
for (var i = 0; i < graphicsPipeline.AttachmentInfo.ColorAttachmentDescriptions.Length; i += 1)
|
|
||||||
{
|
|
||||||
TextureFormat format;
|
|
||||||
if (i == 0)
|
|
||||||
{
|
|
||||||
format = colorFormatOne;
|
|
||||||
}
|
|
||||||
else if (i == 1)
|
|
||||||
{
|
|
||||||
format = colorFormatTwo;
|
|
||||||
}
|
|
||||||
else if (i == 2)
|
|
||||||
{
|
|
||||||
format = colorFormatThree;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
format = colorFormatFour;
|
|
||||||
}
|
|
||||||
|
|
||||||
var pipelineFormat = graphicsPipeline.AttachmentInfo.ColorAttachmentDescriptions[i].Format;
|
|
||||||
if (pipelineFormat != format)
|
|
||||||
{
|
|
||||||
throw new System.InvalidOperationException($"Color texture format mismatch! Pipeline expects {pipelineFormat}, render pass attachment is {format}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (graphicsPipeline.AttachmentInfo.HasDepthStencilAttachment)
|
|
||||||
{
|
|
||||||
var pipelineDepthFormat = graphicsPipeline.AttachmentInfo.DepthStencilFormat;
|
|
||||||
|
|
||||||
if (!hasDepthStencilAttachment)
|
|
||||||
{
|
|
||||||
throw new System.InvalidOperationException("Pipeline expects depth attachment!");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pipelineDepthFormat != depthStencilFormat)
|
|
||||||
{
|
|
||||||
throw new System.InvalidOperationException($"Depth texture format mismatch! Pipeline expects {pipelineDepthFormat}, render pass attachment is {depthStencilFormat}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AssertVertexSamplerCount(int count)
|
private void AssertVertexSamplerCount(int count)
|
||||||
{
|
{
|
||||||
if (currentGraphicsPipeline.VertexShaderInfo.SamplerBindingCount != count)
|
if (currentGraphicsPipeline.VertexShaderInfo.SamplerBindingCount != count)
|
||||||
|
@ -2287,5 +1820,4 @@ namespace MoonWorks.Graphics
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,485 @@
|
||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using SDL2_gpuCS;
|
||||||
|
namespace MoonWorks.Graphics;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Render passes are begun in command buffers and are used to apply render state and issue draw calls.
|
||||||
|
/// Render passes are pooled and should not be referenced after calling EndRenderPass.
|
||||||
|
/// </summary>
|
||||||
|
public class RenderPass
|
||||||
|
{
|
||||||
|
public nint Handle { get; internal set; }
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
internal bool active;
|
||||||
|
GraphicsPipeline currentGraphicsPipeline;
|
||||||
|
uint colorAttachmentCount;
|
||||||
|
SampleCount colorAttachmentSampleCount;
|
||||||
|
TextureFormat colorFormatOne;
|
||||||
|
TextureFormat colorFormatTwo;
|
||||||
|
TextureFormat colorFormatThree;
|
||||||
|
TextureFormat colorFormatFour;
|
||||||
|
bool hasDepthStencilAttachment;
|
||||||
|
SampleCount depthStencilAttachmentSampleCount;
|
||||||
|
TextureFormat depthStencilFormat;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
internal void SetHandle(nint handle)
|
||||||
|
{
|
||||||
|
Handle = handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Binds a graphics pipeline so that rendering work may be performed.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="graphicsPipeline">The graphics pipeline to bind.</param>
|
||||||
|
public void BindGraphicsPipeline(
|
||||||
|
GraphicsPipeline graphicsPipeline
|
||||||
|
) {
|
||||||
|
#if DEBUG
|
||||||
|
AssertRenderPassActive();
|
||||||
|
AssertRenderPassPipelineFormatMatch(graphicsPipeline);
|
||||||
|
|
||||||
|
if (colorAttachmentCount > 0)
|
||||||
|
{
|
||||||
|
if (graphicsPipeline.SampleCount != colorAttachmentSampleCount)
|
||||||
|
{
|
||||||
|
throw new System.InvalidOperationException($"Sample count mismatch! Graphics pipeline sample count: {graphicsPipeline.SampleCount}, Color attachment sample count: {colorAttachmentSampleCount}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasDepthStencilAttachment)
|
||||||
|
{
|
||||||
|
if (graphicsPipeline.SampleCount != depthStencilAttachmentSampleCount)
|
||||||
|
{
|
||||||
|
throw new System.InvalidOperationException($"Sample count mismatch! Graphics pipeline sample count: {graphicsPipeline.SampleCount}, Depth stencil attachment sample count: {depthStencilAttachmentSampleCount}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SDL_Gpu.SDL_GpuBindGraphicsPipeline(
|
||||||
|
Handle,
|
||||||
|
graphicsPipeline.Handle
|
||||||
|
);
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
currentGraphicsPipeline = graphicsPipeline;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the viewport.
|
||||||
|
/// </summary>
|
||||||
|
public void SetViewport(in Viewport viewport)
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
AssertRenderPassActive();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SDL_Gpu.SDL_GpuSetViewport(
|
||||||
|
Handle,
|
||||||
|
viewport.ToRefresh()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the scissor area.
|
||||||
|
/// </summary>
|
||||||
|
public void SetScissor(in Rect scissor)
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
AssertRenderPassActive();
|
||||||
|
|
||||||
|
if (scissor.X < 0 || scissor.Y < 0 || scissor.W <= 0 || scissor.H <= 0)
|
||||||
|
{
|
||||||
|
throw new System.ArgumentOutOfRangeException("Scissor position cannot be negative and dimensions must be positive!");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SDL_Gpu.SDL_GpuSetScissor(
|
||||||
|
Handle,
|
||||||
|
scissor.ToRefresh()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Binds vertex buffers to be used by subsequent draw calls.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="bufferBinding">Buffer to bind and associated offset.</param>
|
||||||
|
/// <param name="firstBinding">The index of the first vertex input binding whose state is updated by the command.</param>
|
||||||
|
public unsafe void BindVertexBuffers(
|
||||||
|
in BufferBinding bufferBinding,
|
||||||
|
uint firstBinding = 0
|
||||||
|
) {
|
||||||
|
#if DEBUG
|
||||||
|
AssertGraphicsPipelineBound();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
var bindingArray = stackalloc SDL_Gpu.BufferBinding[1];
|
||||||
|
bindingArray[0] = bufferBinding.ToRefresh();
|
||||||
|
|
||||||
|
SDL_Gpu.SDL_GpuBindVertexBuffers(
|
||||||
|
Handle,
|
||||||
|
firstBinding,
|
||||||
|
bindingArray,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Binds vertex buffers to be used by subsequent draw calls.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="bufferBindingOne">Buffer to bind and associated offset.</param>
|
||||||
|
/// <param name="bufferBindingTwo">Buffer to bind and associated offset.</param>
|
||||||
|
/// <param name="firstBinding">The index of the first vertex input binding whose state is updated by the command.</param>
|
||||||
|
public unsafe void BindVertexBuffers(
|
||||||
|
in BufferBinding bufferBindingOne,
|
||||||
|
in BufferBinding bufferBindingTwo,
|
||||||
|
uint firstBinding = 0
|
||||||
|
) {
|
||||||
|
#if DEBUG
|
||||||
|
AssertGraphicsPipelineBound();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
var bindingArray = stackalloc SDL_Gpu.BufferBinding[2];
|
||||||
|
bindingArray[0] = bufferBindingOne.ToRefresh();
|
||||||
|
bindingArray[1] = bufferBindingTwo.ToRefresh();
|
||||||
|
|
||||||
|
SDL_Gpu.SDL_GpuBindVertexBuffers(
|
||||||
|
Handle,
|
||||||
|
firstBinding,
|
||||||
|
bindingArray,
|
||||||
|
2
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Binds vertex buffers to be used by subsequent draw calls.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="bufferBindingOne">Buffer to bind and associated offset.</param>
|
||||||
|
/// <param name="bufferBindingTwo">Buffer to bind and associated offset.</param>
|
||||||
|
/// <param name="bufferBindingThree">Buffer to bind and associated offset.</param>
|
||||||
|
/// <param name="firstBinding">The index of the first vertex input binding whose state is updated by the command.</param>
|
||||||
|
public unsafe void BindVertexBuffers(
|
||||||
|
in BufferBinding bufferBindingOne,
|
||||||
|
in BufferBinding bufferBindingTwo,
|
||||||
|
in BufferBinding bufferBindingThree,
|
||||||
|
uint firstBinding = 0
|
||||||
|
) {
|
||||||
|
#if DEBUG
|
||||||
|
AssertGraphicsPipelineBound();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
var bindingArray = stackalloc SDL_Gpu.BufferBinding[3];
|
||||||
|
bindingArray[0] = bufferBindingOne.ToRefresh();
|
||||||
|
bindingArray[1] = bufferBindingTwo.ToRefresh();
|
||||||
|
bindingArray[2] = bufferBindingThree.ToRefresh();
|
||||||
|
|
||||||
|
SDL_Gpu.SDL_GpuBindVertexBuffers(
|
||||||
|
Handle,
|
||||||
|
firstBinding,
|
||||||
|
bindingArray,
|
||||||
|
3
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Binds vertex buffers to be used by subsequent draw calls.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="bufferBindingOne">Buffer to bind and associated offset.</param>
|
||||||
|
/// <param name="bufferBindingTwo">Buffer to bind and associated offset.</param>
|
||||||
|
/// <param name="bufferBindingThree">Buffer to bind and associated offset.</param>
|
||||||
|
/// <param name="bufferBindingFour">Buffer to bind and associated offset.</param>
|
||||||
|
/// <param name="firstBinding">The index of the first vertex input binding whose state is updated by the command.</param>
|
||||||
|
public unsafe void BindVertexBuffers(
|
||||||
|
in BufferBinding bufferBindingOne,
|
||||||
|
in BufferBinding bufferBindingTwo,
|
||||||
|
in BufferBinding bufferBindingThree,
|
||||||
|
in BufferBinding bufferBindingFour,
|
||||||
|
uint firstBinding = 0
|
||||||
|
) {
|
||||||
|
#if DEBUG
|
||||||
|
AssertGraphicsPipelineBound();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
var bindingArray = stackalloc SDL_Gpu.BufferBinding[4];
|
||||||
|
bindingArray[0] = bufferBindingOne.ToRefresh();
|
||||||
|
bindingArray[1] = bufferBindingTwo.ToRefresh();
|
||||||
|
bindingArray[2] = bufferBindingThree.ToRefresh();
|
||||||
|
bindingArray[3] = bufferBindingFour.ToRefresh();
|
||||||
|
|
||||||
|
SDL_Gpu.SDL_GpuBindVertexBuffers(
|
||||||
|
Handle,
|
||||||
|
firstBinding,
|
||||||
|
bindingArray,
|
||||||
|
4
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Binds vertex buffers to be used by subsequent draw calls.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="bufferBindings">Spawn of buffers to bind and their associated offsets.</param>
|
||||||
|
/// <param name="firstBinding">The index of the first vertex input binding whose state is updated by the command.</param>
|
||||||
|
public unsafe void BindVertexBuffers(
|
||||||
|
in Span<BufferBinding> bufferBindings,
|
||||||
|
uint firstBinding = 0
|
||||||
|
) {
|
||||||
|
#if DEBUG
|
||||||
|
AssertGraphicsPipelineBound();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SDL_Gpu.BufferBinding* bufferBindingsArray = (SDL_Gpu.BufferBinding*) NativeMemory.Alloc((nuint) (Marshal.SizeOf<SDL_Gpu.BufferBinding>() * bufferBindings.Length));
|
||||||
|
|
||||||
|
for (var i = 0; i < bufferBindings.Length; i += 1)
|
||||||
|
{
|
||||||
|
bufferBindingsArray[i] = bufferBindings[i].ToRefresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Gpu.SDL_GpuBindVertexBuffers(
|
||||||
|
Handle,
|
||||||
|
firstBinding,
|
||||||
|
bufferBindingsArray,
|
||||||
|
(uint) bufferBindings.Length
|
||||||
|
);
|
||||||
|
|
||||||
|
NativeMemory.Free(bufferBindingsArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Binds an index buffer to be used by subsequent draw calls.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="indexBuffer">The index buffer to bind.</param>
|
||||||
|
/// <param name="indexElementSize">The size in bytes of the index buffer elements.</param>
|
||||||
|
/// <param name="offset">The offset index for the buffer.</param>
|
||||||
|
public void BindIndexBuffer(
|
||||||
|
BufferBinding bufferBinding,
|
||||||
|
IndexElementSize indexElementSize
|
||||||
|
)
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
AssertGraphicsPipelineBound();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SDL_Gpu.SDL_GpuBindIndexBuffer(
|
||||||
|
Handle,
|
||||||
|
bufferBinding.ToRefresh(),
|
||||||
|
(SDL_Gpu.IndexElementSize) indexElementSize
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Binds samplers to be used by the vertex shader.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="textureSamplerBindings">The texture-sampler to bind.</param>
|
||||||
|
public unsafe void BindVertexSampler(
|
||||||
|
in TextureSamplerBinding textureSamplerBinding,
|
||||||
|
uint slot = 0
|
||||||
|
) {
|
||||||
|
#if DEBUG
|
||||||
|
AssertGraphicsPipelineBound();
|
||||||
|
AssertTextureSamplerBindingNonNull(textureSamplerBinding);
|
||||||
|
AssertTextureHasSamplerFlag(textureSamplerBinding.Texture);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
var bindingArray = stackalloc SDL_Gpu.TextureSamplerBinding[1];
|
||||||
|
bindingArray[0] = textureSamplerBinding.ToSDL();
|
||||||
|
|
||||||
|
SDL_Gpu.SDL_GpuBindVertexSamplers(
|
||||||
|
Handle,
|
||||||
|
slot,
|
||||||
|
bindingArray,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public unsafe void BindVertexSamplers(
|
||||||
|
in Span<TextureSamplerBinding> textureSamplerBindings,
|
||||||
|
uint firstSlot = 0
|
||||||
|
) {
|
||||||
|
#if DEBUG
|
||||||
|
AssertGraphicsPipelineBound();
|
||||||
|
|
||||||
|
for (var i = 0; i < textureSamplerBindings.Length; i += 1)
|
||||||
|
{
|
||||||
|
AssertTextureSamplerBindingNonNull(textureSamplerBindings[i]);
|
||||||
|
AssertTextureHasSamplerFlag(textureSamplerBindings[i].Texture);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SDL_Gpu.TextureSamplerBinding* samplerBindingsArray =
|
||||||
|
(SDL_Gpu.TextureSamplerBinding*) NativeMemory.Alloc(
|
||||||
|
(nuint) (Marshal.SizeOf<SDL_Gpu.TextureSamplerBinding>() * textureSamplerBindings.Length)
|
||||||
|
);
|
||||||
|
|
||||||
|
for (var i = 0; i < textureSamplerBindings.Length; i += 1)
|
||||||
|
{
|
||||||
|
samplerBindingsArray[i] = textureSamplerBindings[i].ToSDL();
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Gpu.SDL_GpuBindVertexSamplers(
|
||||||
|
Handle,
|
||||||
|
firstSlot,
|
||||||
|
samplerBindingsArray,
|
||||||
|
(uint) textureSamplerBindings.Length
|
||||||
|
);
|
||||||
|
|
||||||
|
NativeMemory.Free(samplerBindingsArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
public unsafe void BindVertexStorageTexture(
|
||||||
|
in TextureSlice storageTextureSlice,
|
||||||
|
uint slot = 0
|
||||||
|
) {
|
||||||
|
#if DEBUG
|
||||||
|
AssertGraphicsPipelineBound();
|
||||||
|
AssertTextureNonNull(storageTextureSlice.Texture);
|
||||||
|
AssertTextureHasGraphicsStorageFlag(storageTextureSlice.Texture);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
var sliceArray = stackalloc SDL_Gpu.TextureSlice[1];
|
||||||
|
sliceArray[0] = storageTextureSlice.ToSDL();
|
||||||
|
|
||||||
|
SDL_Gpu.SDL_GpuBindVertexStorageTextures(
|
||||||
|
Handle,
|
||||||
|
slot,
|
||||||
|
sliceArray,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public unsafe void BindVertexStorageTextures(
|
||||||
|
in Span<TextureSlice> storageTextureSlices,
|
||||||
|
uint firstSlot = 0
|
||||||
|
) {
|
||||||
|
#if DEBUG
|
||||||
|
AssertGraphicsPipelineBound();
|
||||||
|
|
||||||
|
for (var i = 0; i < storageTextureSlices.Length; i += 1)
|
||||||
|
{
|
||||||
|
AssertTextureNonNull(storageTextureSlices[i].Texture);
|
||||||
|
AssertTextureHasGraphicsStorageFlag(storageTextureSlices[i].Texture);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SDL_Gpu.TextureSlice* sliceArray =
|
||||||
|
(SDL_Gpu.TextureSlice*) NativeMemory.Alloc(
|
||||||
|
(nuint) (Marshal.SizeOf<SDL_Gpu.TextureSlice>() * storageTextureSlices.Length)
|
||||||
|
);
|
||||||
|
|
||||||
|
for (var i = 0; i < storageTextureSlices.Length; i += 1)
|
||||||
|
{
|
||||||
|
sliceArray[i] = storageTextureSlices[i].ToSDL();
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Gpu.SDL_GpuBindVertexStorageTextures(
|
||||||
|
Handle,
|
||||||
|
firstSlot,
|
||||||
|
sliceArray,
|
||||||
|
(uint) storageTextureSlices.Length
|
||||||
|
);
|
||||||
|
|
||||||
|
NativeMemory.Free(sliceArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
private void AssertRenderPassActive(string message = "Render pass is not active!")
|
||||||
|
{
|
||||||
|
if (!active)
|
||||||
|
{
|
||||||
|
throw new System.InvalidOperationException(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AssertRenderPassPipelineFormatMatch(GraphicsPipeline graphicsPipeline)
|
||||||
|
{
|
||||||
|
for (var i = 0; i < graphicsPipeline.AttachmentInfo.ColorAttachmentDescriptions.Length; i += 1)
|
||||||
|
{
|
||||||
|
TextureFormat format;
|
||||||
|
if (i == 0)
|
||||||
|
{
|
||||||
|
format = colorFormatOne;
|
||||||
|
}
|
||||||
|
else if (i == 1)
|
||||||
|
{
|
||||||
|
format = colorFormatTwo;
|
||||||
|
}
|
||||||
|
else if (i == 2)
|
||||||
|
{
|
||||||
|
format = colorFormatThree;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
format = colorFormatFour;
|
||||||
|
}
|
||||||
|
|
||||||
|
var pipelineFormat = graphicsPipeline.AttachmentInfo.ColorAttachmentDescriptions[i].Format;
|
||||||
|
if (pipelineFormat != format)
|
||||||
|
{
|
||||||
|
throw new System.InvalidOperationException($"Color texture format mismatch! Pipeline expects {pipelineFormat}, render pass attachment is {format}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (graphicsPipeline.AttachmentInfo.HasDepthStencilAttachment)
|
||||||
|
{
|
||||||
|
var pipelineDepthFormat = graphicsPipeline.AttachmentInfo.DepthStencilFormat;
|
||||||
|
|
||||||
|
if (!hasDepthStencilAttachment)
|
||||||
|
{
|
||||||
|
throw new System.InvalidOperationException("Pipeline expects depth attachment!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pipelineDepthFormat != depthStencilFormat)
|
||||||
|
{
|
||||||
|
throw new System.InvalidOperationException($"Depth texture format mismatch! Pipeline expects {pipelineDepthFormat}, render pass attachment is {depthStencilFormat}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AssertGraphicsPipelineBound(string message = "No graphics pipeline is bound!")
|
||||||
|
{
|
||||||
|
if (currentGraphicsPipeline == null)
|
||||||
|
{
|
||||||
|
throw new System.InvalidOperationException(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AssertTextureNonNull(in TextureSlice textureSlice)
|
||||||
|
{
|
||||||
|
if (textureSlice.Texture == null)
|
||||||
|
{
|
||||||
|
throw new NullReferenceException("Texture must not be null!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AssertTextureSamplerBindingNonNull(in TextureSamplerBinding binding)
|
||||||
|
{
|
||||||
|
if (binding.Texture == null || binding.Texture.Handle == IntPtr.Zero)
|
||||||
|
{
|
||||||
|
throw new NullReferenceException("Texture binding must not be null!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (binding.Sampler == null || binding.Sampler.Handle == IntPtr.Zero)
|
||||||
|
{
|
||||||
|
throw new NullReferenceException("Sampler binding must not be null!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AssertTextureHasSamplerFlag(Texture texture)
|
||||||
|
{
|
||||||
|
if ((texture.UsageFlags & TextureUsageFlags.Sampler) == 0)
|
||||||
|
{
|
||||||
|
throw new System.ArgumentException("The bound Texture's UsageFlags must include TextureUsageFlags.Sampler!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AssertTextureHasGraphicsStorageFlag(Texture texture)
|
||||||
|
{
|
||||||
|
if ((texture.UsageFlags & TextureUsageFlags.GraphicsStorage) == 0)
|
||||||
|
{
|
||||||
|
throw new System.ArgumentException("The bound Texture's UsageFlags must include TextureUsageFlags.GraphicsStorage!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
|
@ -1,12 +1,11 @@
|
||||||
using RefreshCS;
|
using SDL2_gpuCS;
|
||||||
|
namespace MoonWorks.Graphics;
|
||||||
|
|
||||||
namespace MoonWorks.Graphics
|
/// <summary>
|
||||||
|
/// A texture slice specifies a subresource of a texture.
|
||||||
|
/// </summary>
|
||||||
|
public struct TextureSlice
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// A texture slice specifies a subresource of a texture.
|
|
||||||
/// </summary>
|
|
||||||
public struct TextureSlice
|
|
||||||
{
|
|
||||||
public Texture Texture;
|
public Texture Texture;
|
||||||
public uint MipLevel;
|
public uint MipLevel;
|
||||||
public uint Layer;
|
public uint Layer;
|
||||||
|
@ -20,14 +19,13 @@ namespace MoonWorks.Graphics
|
||||||
Layer = 0;
|
Layer = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Refresh.TextureSlice ToRefreshTextureSlice()
|
public SDL_Gpu.TextureSlice ToSDL()
|
||||||
{
|
{
|
||||||
return new Refresh.TextureSlice
|
return new SDL_Gpu.TextureSlice
|
||||||
{
|
{
|
||||||
texture = Texture.Handle,
|
Texture = Texture.Handle,
|
||||||
mipLevel = MipLevel,
|
MipLevel = MipLevel,
|
||||||
layer = Layer
|
Layer = Layer
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue