refactor ComputePass
parent
fe6734d6db
commit
97dee2a170
|
@ -1 +1 @@
|
||||||
Subproject commit 60e2c21a7b224dc6aa6a457dbb71d798a4e66241
|
Subproject commit 70925aa394c0f24388f3cfb97f1c6ee1f91baf52
|
|
@ -1,19 +0,0 @@
|
||||||
using SDL2_gpuCS;
|
|
||||||
namespace MoonWorks.Graphics;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A buffer-offset pair to be used when binding buffers.
|
|
||||||
/// </summary>
|
|
||||||
public readonly record struct BufferBinding(
|
|
||||||
GpuBuffer Buffer,
|
|
||||||
uint Offset
|
|
||||||
) {
|
|
||||||
public SDL_Gpu.BufferBinding ToSDL()
|
|
||||||
{
|
|
||||||
return new SDL_Gpu.BufferBinding
|
|
||||||
{
|
|
||||||
Buffer = Buffer.Handle,
|
|
||||||
Offset = Offset
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,34 +0,0 @@
|
||||||
using SDL2_gpuCS;
|
|
||||||
|
|
||||||
namespace MoonWorks.Graphics;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Binding specification to be used when binding buffers for compute shaders.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="GpuBuffer">The GpuBuffer to bind.</param>
|
|
||||||
/// <param name="WriteOption">
|
|
||||||
/// Specifies data dependency behavior when this buffer is written to in the shader. <br/>
|
|
||||||
///
|
|
||||||
/// Cycle:
|
|
||||||
/// If this buffer has been used in commands that have not finished,
|
|
||||||
/// the implementation may choose to prevent a dependency on those commands
|
|
||||||
/// at the cost of increased memory usage.
|
|
||||||
/// You may NOT assume that any of the previous data is retained.
|
|
||||||
/// This may prevent stalls when frequently updating a resource. <br />
|
|
||||||
///
|
|
||||||
/// SafeOverwrite:
|
|
||||||
/// Overwrites the data safely using a GPU memory barrier.
|
|
||||||
/// </param>
|
|
||||||
public readonly record struct ComputeBufferBinding(
|
|
||||||
GpuBuffer GpuBuffer,
|
|
||||||
WriteOptions WriteOption
|
|
||||||
) {
|
|
||||||
public SDL_Gpu.BufferBinding ToRefresh()
|
|
||||||
{
|
|
||||||
return new Refresh.ComputeBufferBinding
|
|
||||||
{
|
|
||||||
gpuBuffer = GpuBuffer.Handle,
|
|
||||||
writeOption = (Refresh.WriteOptions) WriteOption
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,35 +0,0 @@
|
||||||
using RefreshCS;
|
|
||||||
|
|
||||||
namespace MoonWorks.Graphics
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Binding specification used for binding texture slices for compute shaders.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="TextureSlice">The TextureSlice to bind.</param>
|
|
||||||
/// <param name="WriteOption">
|
|
||||||
/// Specifies data dependency behavior when this texture is written to in the shader. <br/>
|
|
||||||
///
|
|
||||||
/// Cycle:
|
|
||||||
/// If this buffer has been used in commands that have not finished,
|
|
||||||
/// the implementation may choose to prevent a dependency on those commands
|
|
||||||
/// at the cost of increased memory usage.
|
|
||||||
/// You may NOT assume that any of the previous data is retained.
|
|
||||||
/// This may prevent stalls when frequently updating a resource. <br />
|
|
||||||
///
|
|
||||||
/// SafeOverwrite:
|
|
||||||
/// Overwrites the data safely using a GPU memory barrier.
|
|
||||||
/// </param>
|
|
||||||
public readonly record struct ComputeTextureBinding(
|
|
||||||
TextureSlice TextureSlice,
|
|
||||||
WriteOptions WriteOption
|
|
||||||
) {
|
|
||||||
public Refresh.ComputeTextureBinding ToRefresh()
|
|
||||||
{
|
|
||||||
return new Refresh.ComputeTextureBinding
|
|
||||||
{
|
|
||||||
textureSlice = TextureSlice.ToRefreshTextureSlice(),
|
|
||||||
writeOption = (Refresh.WriteOptions) WriteOption
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,21 +0,0 @@
|
||||||
using SDL2_gpuCS;
|
|
||||||
|
|
||||||
namespace MoonWorks.Graphics
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// A texture-sampler pair to be used when binding samplers.
|
|
||||||
/// </summary>
|
|
||||||
public readonly record struct TextureSamplerBinding(
|
|
||||||
Texture Texture,
|
|
||||||
Sampler Sampler
|
|
||||||
) {
|
|
||||||
public SDL_Gpu.TextureSamplerBinding ToSDL()
|
|
||||||
{
|
|
||||||
return new SDL_Gpu.TextureSamplerBinding
|
|
||||||
{
|
|
||||||
Texture = Texture.Handle,
|
|
||||||
Sampler = Sampler.Handle
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -641,401 +641,106 @@ public class CommandBuffer
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void BeginComputePass()
|
public unsafe ComputePass BeginComputePass(
|
||||||
{
|
in StorageTextureReadWriteBinding readWriteTextureBinding
|
||||||
|
) {
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
AssertNotSubmitted();
|
AssertNotSubmitted();
|
||||||
AssertNotInPass("Cannot begin compute pass while in another pass!");
|
AssertNotInPass("Cannot begin compute pass while in another pass!");
|
||||||
computePassActive = true;
|
computePassActive = true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Refresh.Refresh_BeginComputePass(
|
var sdlTextureBinding = readWriteTextureBinding.ToSDL();
|
||||||
Device.Handle,
|
|
||||||
Handle
|
var computePassHandle = SDL_Gpu.SDL_GpuBeginComputePass(
|
||||||
|
Handle,
|
||||||
|
&sdlTextureBinding,
|
||||||
|
1,
|
||||||
|
(SDL_Gpu.StorageBufferReadWriteBinding*) nint.Size,
|
||||||
|
0
|
||||||
);
|
);
|
||||||
|
|
||||||
|
var computePass = Device.ComputePassPool.Obtain();
|
||||||
|
computePass.SetHandle(computePassHandle);
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
computePass.active = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return computePass;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
public unsafe ComputePass BeginComputePass(
|
||||||
/// Binds a compute pipeline so that compute work may be dispatched.
|
in StorageBufferReadWriteBinding readWriteBufferBinding
|
||||||
/// </summary>
|
|
||||||
/// <param name="computePipeline">The compute pipeline to bind.</param>
|
|
||||||
public void BindComputePipeline(
|
|
||||||
ComputePipeline computePipeline
|
|
||||||
) {
|
) {
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
AssertNotSubmitted();
|
AssertNotSubmitted();
|
||||||
AssertInComputePass("Cannot bind compute pipeline outside of compute pass!");
|
AssertNotInPass("Cannot begin compute pass while in another pass!");
|
||||||
|
computePassActive = true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Refresh.Refresh_BindComputePipeline(
|
var sdlBufferBinding = readWriteBufferBinding.ToSDL();
|
||||||
Device.Handle,
|
|
||||||
|
var computePassHandle = SDL_Gpu.SDL_GpuBeginComputePass(
|
||||||
Handle,
|
Handle,
|
||||||
computePipeline.Handle
|
(SDL_Gpu.StorageTextureReadWriteBinding*) nint.Zero,
|
||||||
|
0,
|
||||||
|
&sdlBufferBinding,
|
||||||
|
1
|
||||||
);
|
);
|
||||||
|
|
||||||
|
var computePass = Device.ComputePassPool.Obtain();
|
||||||
|
computePass.SetHandle(computePassHandle);
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
currentComputePipeline = computePipeline;
|
computePass.active = true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
return computePass;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
public unsafe ComputePass BeginComputePass(
|
||||||
/// Binds a buffer to be used in the compute shader.
|
in StorageTextureReadWriteBinding readWriteTextureBinding,
|
||||||
/// </summary>
|
in StorageBufferReadWriteBinding readWriteBufferBinding
|
||||||
public unsafe void BindComputeBuffers(
|
|
||||||
ComputeBufferBinding binding
|
|
||||||
) {
|
) {
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
AssertNotSubmitted();
|
AssertNotSubmitted();
|
||||||
AssertInComputePass("Cannot bind compute buffers outside of compute pass!");
|
AssertNotInPass("Cannot begin compute pass while in another pass!");
|
||||||
AssertComputePipelineBound();
|
computePassActive = true;
|
||||||
AssertComputeBufferCount(1);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
var bindingArray = stackalloc Refresh.ComputeBufferBinding[1];
|
var sdlTextureBinding = readWriteTextureBinding.ToSDL();
|
||||||
bindingArray[0] = binding.ToRefresh();
|
var sdlBufferBinding = readWriteBufferBinding.ToSDL();
|
||||||
|
|
||||||
Refresh.Refresh_BindComputeBuffers(
|
var computePassHandle = SDL_Gpu.SDL_GpuBeginComputePass(
|
||||||
Device.Handle,
|
|
||||||
Handle,
|
Handle,
|
||||||
bindingArray
|
&sdlTextureBinding,
|
||||||
|
1,
|
||||||
|
&sdlBufferBinding,
|
||||||
|
1
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
var computePass = Device.ComputePassPool.Obtain();
|
||||||
/// Binds buffers to be used in the compute shader.
|
computePass.SetHandle(computePassHandle);
|
||||||
/// </summary>
|
|
||||||
public unsafe void BindComputeBuffers(
|
|
||||||
ComputeBufferBinding bindingOne,
|
|
||||||
ComputeBufferBinding bindingTwo
|
|
||||||
) {
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
AssertNotSubmitted();
|
computePass.active = true;
|
||||||
AssertInComputePass("Cannot bind compute buffers outside of compute pass!");
|
|
||||||
AssertComputePipelineBound();
|
|
||||||
AssertComputeBufferCount(2);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
var bindingArray = stackalloc Refresh.ComputeBufferBinding[2];
|
return computePass;
|
||||||
bindingArray[0] = bindingOne.ToRefresh();
|
|
||||||
bindingArray[1] = bindingTwo.ToRefresh();
|
|
||||||
|
|
||||||
Refresh.Refresh_BindComputeBuffers(
|
|
||||||
Device.Handle,
|
|
||||||
Handle,
|
|
||||||
bindingArray
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
public void EndComputePass(ComputePass computePass)
|
||||||
/// Binds buffers to be used in the compute shader.
|
|
||||||
/// </summary>
|
|
||||||
public unsafe void BindComputeBuffers(
|
|
||||||
ComputeBufferBinding bindingOne,
|
|
||||||
ComputeBufferBinding bindingTwo,
|
|
||||||
ComputeBufferBinding bindingThree
|
|
||||||
) {
|
|
||||||
#if DEBUG
|
|
||||||
AssertNotSubmitted();
|
|
||||||
AssertInComputePass("Cannot bind compute buffers outside of compute pass!");
|
|
||||||
AssertComputePipelineBound();
|
|
||||||
AssertComputeBufferCount(3);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
var bindingArray = stackalloc Refresh.ComputeBufferBinding[3];
|
|
||||||
bindingArray[0] = bindingOne.ToRefresh();
|
|
||||||
bindingArray[1] = bindingTwo.ToRefresh();
|
|
||||||
bindingArray[2] = bindingThree.ToRefresh();
|
|
||||||
|
|
||||||
Refresh.Refresh_BindComputeBuffers(
|
|
||||||
Device.Handle,
|
|
||||||
Handle,
|
|
||||||
bindingArray
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Binds buffers to be used in the compute shader.
|
|
||||||
/// </summary>
|
|
||||||
public unsafe void BindComputeBuffers(
|
|
||||||
ComputeBufferBinding bindingOne,
|
|
||||||
ComputeBufferBinding bindingTwo,
|
|
||||||
ComputeBufferBinding bindingThree,
|
|
||||||
ComputeBufferBinding bindingFour
|
|
||||||
) {
|
|
||||||
#if DEBUG
|
|
||||||
AssertNotSubmitted();
|
|
||||||
AssertInComputePass("Cannot bind compute buffers outside of compute pass!");
|
|
||||||
AssertComputePipelineBound();
|
|
||||||
AssertComputeBufferCount(4);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
var bindingArray = stackalloc Refresh.ComputeBufferBinding[4];
|
|
||||||
bindingArray[0] = bindingOne.ToRefresh();
|
|
||||||
bindingArray[1] = bindingTwo.ToRefresh();
|
|
||||||
bindingArray[2] = bindingThree.ToRefresh();
|
|
||||||
bindingArray[3] = bindingFour.ToRefresh();
|
|
||||||
|
|
||||||
Refresh.Refresh_BindComputeBuffers(
|
|
||||||
Device.Handle,
|
|
||||||
Handle,
|
|
||||||
bindingArray
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Binds buffers to be used in the compute shader.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="buffers">A Span of buffers to bind.</param>
|
|
||||||
public unsafe void BindComputeBuffers(
|
|
||||||
in Span<ComputeBufferBinding> bindings
|
|
||||||
) {
|
|
||||||
#if DEBUG
|
|
||||||
AssertNotSubmitted();
|
|
||||||
AssertInComputePass("Cannot bind compute buffers outside of compute pass!");
|
|
||||||
AssertComputePipelineBound();
|
|
||||||
AssertComputeBufferCount(bindings.Length);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Refresh.ComputeBufferBinding* bindingArray = (Refresh.ComputeBufferBinding*) NativeMemory.Alloc(
|
|
||||||
(nuint) (Marshal.SizeOf<ComputeBufferBinding>() * bindings.Length)
|
|
||||||
);
|
|
||||||
|
|
||||||
for (var i = 0; i < bindings.Length; i += 1)
|
|
||||||
{
|
|
||||||
bindingArray[i] = bindings[i].ToRefresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
Refresh.Refresh_BindComputeBuffers(
|
|
||||||
Device.Handle,
|
|
||||||
Handle,
|
|
||||||
bindingArray
|
|
||||||
);
|
|
||||||
|
|
||||||
NativeMemory.Free(bindingArray);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Binds a texture slice to be used in the compute shader.
|
|
||||||
/// </summary>
|
|
||||||
public unsafe void BindComputeTextures(
|
|
||||||
ComputeTextureBinding binding
|
|
||||||
) {
|
|
||||||
#if DEBUG
|
|
||||||
AssertNotSubmitted();
|
|
||||||
AssertInComputePass("Cannot bind compute textures outside of compute pass!");
|
|
||||||
AssertComputePipelineBound();
|
|
||||||
AssertComputeTextureCount(1);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
var bindingArray = stackalloc Refresh.ComputeTextureBinding[1];
|
|
||||||
bindingArray[0] = binding.ToRefresh();
|
|
||||||
|
|
||||||
Refresh.Refresh_BindComputeTextures(
|
|
||||||
Device.Handle,
|
|
||||||
Handle,
|
|
||||||
bindingArray
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Binds textures to be used in the compute shader.
|
|
||||||
/// </summary>
|
|
||||||
public unsafe void BindComputeTextures(
|
|
||||||
ComputeTextureBinding bindingOne,
|
|
||||||
ComputeTextureBinding bindingTwo
|
|
||||||
) {
|
|
||||||
#if DEBUG
|
|
||||||
AssertNotSubmitted();
|
|
||||||
AssertInComputePass("Cannot bind compute textures outside of compute pass!");
|
|
||||||
AssertComputePipelineBound();
|
|
||||||
AssertComputeTextureCount(2);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
var bindingArray = stackalloc Refresh.ComputeTextureBinding[2];
|
|
||||||
bindingArray[0] = bindingOne.ToRefresh();
|
|
||||||
bindingArray[1] = bindingTwo.ToRefresh();
|
|
||||||
|
|
||||||
Refresh.Refresh_BindComputeTextures(
|
|
||||||
Device.Handle,
|
|
||||||
Handle,
|
|
||||||
bindingArray
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Binds textures to be used in the compute shader.
|
|
||||||
/// </summary>
|
|
||||||
public unsafe void BindComputeTextures(
|
|
||||||
ComputeTextureBinding bindingOne,
|
|
||||||
ComputeTextureBinding bindingTwo,
|
|
||||||
ComputeTextureBinding bindingThree
|
|
||||||
) {
|
|
||||||
#if DEBUG
|
|
||||||
AssertNotSubmitted();
|
|
||||||
AssertInComputePass("Cannot bind compute textures outside of compute pass!");
|
|
||||||
AssertComputePipelineBound();
|
|
||||||
AssertComputeTextureCount(3);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
var bindingArray = stackalloc Refresh.ComputeTextureBinding[3];
|
|
||||||
bindingArray[0] = bindingOne.ToRefresh();
|
|
||||||
bindingArray[1] = bindingTwo.ToRefresh();
|
|
||||||
bindingArray[2] = bindingThree.ToRefresh();
|
|
||||||
|
|
||||||
Refresh.Refresh_BindComputeTextures(
|
|
||||||
Device.Handle,
|
|
||||||
Handle,
|
|
||||||
bindingArray
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Binds textures to be used in the compute shader.
|
|
||||||
/// </summary>
|
|
||||||
public unsafe void BindComputeTextures(
|
|
||||||
ComputeTextureBinding bindingOne,
|
|
||||||
ComputeTextureBinding bindingTwo,
|
|
||||||
ComputeTextureBinding bindingThree,
|
|
||||||
ComputeTextureBinding bindingFour
|
|
||||||
) {
|
|
||||||
#if DEBUG
|
|
||||||
AssertNotSubmitted();
|
|
||||||
AssertInComputePass("Cannot bind compute textures outside of compute pass!");
|
|
||||||
AssertComputePipelineBound();
|
|
||||||
AssertComputeTextureCount(4);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
var textureSlicePtrs = stackalloc Refresh.ComputeTextureBinding[4];
|
|
||||||
textureSlicePtrs[0] = bindingOne.ToRefresh();
|
|
||||||
textureSlicePtrs[1] = bindingTwo.ToRefresh();
|
|
||||||
textureSlicePtrs[2] = bindingThree.ToRefresh();
|
|
||||||
textureSlicePtrs[3] = bindingFour.ToRefresh();
|
|
||||||
|
|
||||||
Refresh.Refresh_BindComputeTextures(
|
|
||||||
Device.Handle,
|
|
||||||
Handle,
|
|
||||||
textureSlicePtrs
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Binds textures to be used in the compute shader.
|
|
||||||
/// </summary>
|
|
||||||
public unsafe void BindComputeTextures(
|
|
||||||
in Span<ComputeTextureBinding> bindings
|
|
||||||
) {
|
|
||||||
#if DEBUG
|
|
||||||
AssertNotSubmitted();
|
|
||||||
AssertInComputePass("Cannot bind compute textures outside of compute pass!");
|
|
||||||
AssertComputePipelineBound();
|
|
||||||
AssertComputeTextureCount(bindings.Length);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Refresh.ComputeTextureBinding* bindingArray = (Refresh.ComputeTextureBinding*) NativeMemory.Alloc(
|
|
||||||
(nuint) (Marshal.SizeOf<Refresh.TextureSlice>() * bindings.Length)
|
|
||||||
);
|
|
||||||
|
|
||||||
for (var i = 0; i < bindings.Length; i += 1)
|
|
||||||
{
|
|
||||||
bindingArray[i] = bindings[i].ToRefresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
Refresh.Refresh_BindComputeTextures(
|
|
||||||
Device.Handle,
|
|
||||||
Handle,
|
|
||||||
bindingArray
|
|
||||||
);
|
|
||||||
|
|
||||||
NativeMemory.Free(bindingArray);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Pushes compute shader uniforms to the device.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>A starting offset to be used with dispatch calls.</returns>
|
|
||||||
public unsafe void PushComputeShaderUniforms(
|
|
||||||
void* uniformsPtr,
|
|
||||||
uint size
|
|
||||||
) {
|
|
||||||
#if DEBUG
|
|
||||||
AssertNotSubmitted();
|
|
||||||
AssertComputePipelineBound();
|
|
||||||
|
|
||||||
if (currentComputePipeline.ComputeShaderInfo.UniformBufferSize == 0)
|
|
||||||
{
|
|
||||||
throw new System.InvalidOperationException("The current compute shader does not take a uniform buffer!");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentComputePipeline.ComputeShaderInfo.UniformBufferSize != size)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException("Compute uniform data size mismatch!");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Refresh.Refresh_PushComputeShaderUniforms(
|
|
||||||
Device.Handle,
|
|
||||||
Handle,
|
|
||||||
(IntPtr) uniformsPtr,
|
|
||||||
size
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Pushes compute shader uniforms to the device.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>A starting offset to be used with dispatch calls.</returns>
|
|
||||||
public unsafe void PushComputeShaderUniforms<T>(
|
|
||||||
in T uniforms
|
|
||||||
) where T : unmanaged
|
|
||||||
{
|
|
||||||
fixed (T* uniformsPtr = &uniforms)
|
|
||||||
{
|
|
||||||
PushComputeShaderUniforms(uniformsPtr, (uint) Marshal.SizeOf<T>());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Dispatches compute work.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="groupCountX"></param>
|
|
||||||
/// <param name="groupCountY"></param>
|
|
||||||
/// <param name="groupCountZ"></param>
|
|
||||||
/// <param name="computeParamOffset"></param>
|
|
||||||
public void DispatchCompute(
|
|
||||||
uint groupCountX,
|
|
||||||
uint groupCountY,
|
|
||||||
uint groupCountZ
|
|
||||||
) {
|
|
||||||
#if DEBUG
|
|
||||||
AssertNotSubmitted();
|
|
||||||
AssertInComputePass("Cannot dispatch compute outside of compute pass!");
|
|
||||||
AssertComputePipelineBound();
|
|
||||||
|
|
||||||
if (groupCountX < 1 || groupCountY < 1 || groupCountZ < 1)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("All dimensions for the compute work group must be >= 1!");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Refresh.Refresh_DispatchCompute(
|
|
||||||
Device.Handle,
|
|
||||||
Handle,
|
|
||||||
groupCountX,
|
|
||||||
groupCountY,
|
|
||||||
groupCountZ
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void EndComputePass()
|
|
||||||
{
|
{
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
|
AssertNotSubmitted();
|
||||||
AssertInComputePass("Cannot end compute pass while not in a compute pass!");
|
AssertInComputePass("Cannot end compute pass while not in a compute pass!");
|
||||||
computePassActive = false;
|
computePassActive = false;
|
||||||
|
computePass.active = false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Refresh.Refresh_EndComputePass(
|
SDL_Gpu.SDL_GpuEndComputePass(
|
||||||
Device.Handle,
|
computePass.Handle
|
||||||
Handle
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,213 @@
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using SDL2;
|
||||||
|
using SDL2_gpuCS;
|
||||||
|
|
||||||
|
namespace MoonWorks.Graphics;
|
||||||
|
|
||||||
|
public class ComputePass
|
||||||
|
{
|
||||||
|
public nint Handle { get; private set; }
|
||||||
|
|
||||||
|
internal void SetHandle(nint handle)
|
||||||
|
{
|
||||||
|
Handle = handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
internal bool active;
|
||||||
|
|
||||||
|
ComputePipeline currentComputePipeline;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Binds a compute pipeline so that compute work may be dispatched.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="computePipeline">The compute pipeline to bind.</param>
|
||||||
|
public void BindComputePipeline(
|
||||||
|
ComputePipeline computePipeline
|
||||||
|
) {
|
||||||
|
#if DEBUG
|
||||||
|
AssertComputePassActive();
|
||||||
|
|
||||||
|
// TODO: validate formats?
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SDL_Gpu.SDL_GpuBindComputePipeline(
|
||||||
|
Handle,
|
||||||
|
computePipeline.Handle
|
||||||
|
);
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
currentComputePipeline = computePipeline;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Binds a texture to be used in the compute shader.
|
||||||
|
/// This texture must have been created with the ComputeShaderRead usage flag.
|
||||||
|
/// </summary>
|
||||||
|
public unsafe void BindStorageTexture(
|
||||||
|
in TextureSlice textureSlice,
|
||||||
|
uint slot = 0
|
||||||
|
) {
|
||||||
|
#if DEBUG
|
||||||
|
AssertComputePassActive();
|
||||||
|
AssertComputePipelineBound();
|
||||||
|
AssertTextureNonNull(textureSlice.Texture);
|
||||||
|
AssertTextureHasComputeStorageReadFlag(textureSlice.Texture);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
var sdlTextureSlice = textureSlice.ToSDL();
|
||||||
|
|
||||||
|
SDL_Gpu.SDL_GpuBindComputeStorageTextures(
|
||||||
|
Handle,
|
||||||
|
slot,
|
||||||
|
&sdlTextureSlice,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Binds a buffer to be used in the compute shader.
|
||||||
|
/// This buffer must have been created with the ComputeShaderRead usage flag.
|
||||||
|
/// </summary>
|
||||||
|
public unsafe void BindStorageBuffer(
|
||||||
|
GpuBuffer buffer,
|
||||||
|
uint slot = 0
|
||||||
|
) {
|
||||||
|
#if DEBUG
|
||||||
|
AssertComputePassActive();
|
||||||
|
AssertComputePipelineBound();
|
||||||
|
AssertBufferNonNull(buffer);
|
||||||
|
AssertBufferHasComputeStorageReadFlag(buffer);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
var bufferHandle = buffer.Handle;
|
||||||
|
|
||||||
|
SDL_Gpu.SDL_GpuBindComputeStorageBuffers(
|
||||||
|
Handle,
|
||||||
|
slot,
|
||||||
|
&bufferHandle,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pushes compute shader uniform data.
|
||||||
|
/// Subsequent draw calls will use this uniform data.
|
||||||
|
/// </summary>
|
||||||
|
public unsafe void PushUniformData(
|
||||||
|
void* uniformsPtr,
|
||||||
|
uint size,
|
||||||
|
uint slot = 0
|
||||||
|
) {
|
||||||
|
#if DEBUG
|
||||||
|
AssertComputePassActive();
|
||||||
|
AssertComputePipelineBound();
|
||||||
|
|
||||||
|
if (slot >= currentComputePipeline.ResourceInfo.UniformBufferCount)
|
||||||
|
{
|
||||||
|
throw new System.ArgumentException($"Slot {slot} given, but {currentComputePipeline.ResourceInfo.UniformBufferCount} uniform buffers are used on the shader!");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SDL_Gpu.SDL_GpuPushComputeUniformData(
|
||||||
|
Handle,
|
||||||
|
slot,
|
||||||
|
(nint) uniformsPtr,
|
||||||
|
size
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pushes compute shader uniform data.
|
||||||
|
/// Subsequent draw calls will use this uniform data.
|
||||||
|
/// </summary>
|
||||||
|
public unsafe void PushUniformData<T>(
|
||||||
|
in T uniforms,
|
||||||
|
uint slot = 0
|
||||||
|
) where T : unmanaged
|
||||||
|
{
|
||||||
|
fixed (T* uniformsPtr = &uniforms)
|
||||||
|
{
|
||||||
|
PushUniformData(uniformsPtr, (uint) Marshal.SizeOf<T>(), slot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Dispatches compute work.
|
||||||
|
/// </summary>
|
||||||
|
public void Dispatch(
|
||||||
|
uint groupCountX,
|
||||||
|
uint groupCountY,
|
||||||
|
uint groupCountZ
|
||||||
|
) {
|
||||||
|
#if DEBUG
|
||||||
|
AssertComputePassActive();
|
||||||
|
AssertComputePipelineBound();
|
||||||
|
|
||||||
|
if (groupCountX < 1 || groupCountY < 1 || groupCountZ < 1)
|
||||||
|
{
|
||||||
|
throw new System.ArgumentException("All dimensions for the compute work groups must be >= 1!");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SDL_Gpu.SDL_GpuDispatchCompute(
|
||||||
|
Handle,
|
||||||
|
groupCountX,
|
||||||
|
groupCountY,
|
||||||
|
groupCountZ
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
private void AssertComputePassActive(string message = "Render pass is not active!")
|
||||||
|
{
|
||||||
|
if (!active)
|
||||||
|
{
|
||||||
|
throw new System.InvalidOperationException(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AssertComputePipelineBound(string message = "No compute pipeline is bound!")
|
||||||
|
{
|
||||||
|
if (currentComputePipeline == null)
|
||||||
|
{
|
||||||
|
throw new System.InvalidOperationException(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AssertTextureNonNull(in TextureSlice textureSlice)
|
||||||
|
{
|
||||||
|
if (textureSlice.Texture == null || textureSlice.Texture.Handle == nint.Zero)
|
||||||
|
{
|
||||||
|
throw new System.NullReferenceException("Texture must not be null!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AssertTextureHasComputeStorageReadFlag(Texture texture)
|
||||||
|
{
|
||||||
|
if ((texture.UsageFlags & TextureUsageFlags.ComputeStorageRead) == 0)
|
||||||
|
{
|
||||||
|
throw new System.ArgumentException("The bound Texture's UsageFlags must include TextureUsageFlags.ComputeStorageRead!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AssertBufferNonNull(GpuBuffer buffer)
|
||||||
|
{
|
||||||
|
if (buffer == null || buffer.Handle == nint.Zero)
|
||||||
|
{
|
||||||
|
throw new System.NullReferenceException("Buffer must not be null!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AssertBufferHasComputeStorageReadFlag(GpuBuffer buffer)
|
||||||
|
{
|
||||||
|
if ((buffer.UsageFlags & BufferUsageFlags.ComputeStorageRead) == 0)
|
||||||
|
{
|
||||||
|
throw new System.ArgumentException("The bound Buffer's UsageFlags must include BufferUsageFlag.ComputeStorageRead!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
|
||||||
|
namespace MoonWorks.Graphics;
|
||||||
|
|
||||||
|
internal class ComputePassPool
|
||||||
|
{
|
||||||
|
private ConcurrentQueue<ComputePass> ComputePasses = new ConcurrentQueue<ComputePass>();
|
||||||
|
|
||||||
|
public ComputePass Obtain()
|
||||||
|
{
|
||||||
|
if (ComputePasses.TryDequeue(out var computePass))
|
||||||
|
{
|
||||||
|
return computePass;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return new ComputePass();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Return(ComputePass computePass)
|
||||||
|
{
|
||||||
|
ComputePasses.Enqueue(computePass);
|
||||||
|
}
|
||||||
|
}
|
|
@ -38,8 +38,9 @@ namespace MoonWorks.Graphics
|
||||||
|
|
||||||
private readonly HashSet<GCHandle> resources = new HashSet<GCHandle>();
|
private readonly HashSet<GCHandle> resources = new HashSet<GCHandle>();
|
||||||
private CommandBufferPool CommandBufferPool;
|
private CommandBufferPool CommandBufferPool;
|
||||||
internal RenderPassPool RenderPassPool;
|
|
||||||
private FencePool FencePool;
|
private FencePool FencePool;
|
||||||
|
internal RenderPassPool RenderPassPool;
|
||||||
|
internal ComputePassPool ComputePassPool;
|
||||||
|
|
||||||
internal unsafe GraphicsDevice(
|
internal unsafe GraphicsDevice(
|
||||||
BackendFlags preferredBackends,
|
BackendFlags preferredBackends,
|
||||||
|
|
|
@ -9,7 +9,7 @@ namespace MoonWorks.Graphics;
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class RenderPass
|
public class RenderPass
|
||||||
{
|
{
|
||||||
public nint Handle { get; internal set; }
|
public nint Handle { get; private set; }
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
internal bool active;
|
internal bool active;
|
||||||
|
@ -296,12 +296,13 @@ public class RenderPass
|
||||||
}
|
}
|
||||||
|
|
||||||
public unsafe void PushVertexUniformData<T>(
|
public unsafe void PushVertexUniformData<T>(
|
||||||
in T uniforms
|
in T uniforms,
|
||||||
|
uint slot = 0
|
||||||
) where T : unmanaged
|
) where T : unmanaged
|
||||||
{
|
{
|
||||||
fixed (T* uniformsPtr = &uniforms)
|
fixed (T* uniformsPtr = &uniforms)
|
||||||
{
|
{
|
||||||
PushVertexUniformData(uniformsPtr, (uint) Marshal.SizeOf<T>());
|
PushVertexUniformData(uniformsPtr, (uint) Marshal.SizeOf<T>(), slot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -328,12 +329,13 @@ public class RenderPass
|
||||||
}
|
}
|
||||||
|
|
||||||
public unsafe void PushFragmentUniformData<T>(
|
public unsafe void PushFragmentUniformData<T>(
|
||||||
in T uniforms
|
in T uniforms,
|
||||||
|
uint slot = 0
|
||||||
) where T : unmanaged
|
) where T : unmanaged
|
||||||
{
|
{
|
||||||
fixed (T* uniformsPtr = &uniforms)
|
fixed (T* uniformsPtr = &uniforms)
|
||||||
{
|
{
|
||||||
PushFragmentUniformData(uniformsPtr, (uint) Marshal.SizeOf<T>());
|
PushFragmentUniformData(uniformsPtr, (uint) Marshal.SizeOf<T>(), slot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,26 +1,25 @@
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
|
|
||||||
namespace MoonWorks.Graphics
|
namespace MoonWorks.Graphics;
|
||||||
|
|
||||||
|
internal class RenderPassPool
|
||||||
{
|
{
|
||||||
internal class RenderPassPool
|
private ConcurrentQueue<RenderPass> RenderPasses = new ConcurrentQueue<RenderPass>();
|
||||||
|
|
||||||
|
public RenderPass Obtain()
|
||||||
{
|
{
|
||||||
private ConcurrentQueue<RenderPass> RenderPasses = new ConcurrentQueue<RenderPass>();
|
if (RenderPasses.TryDequeue(out var renderPass))
|
||||||
|
|
||||||
public RenderPass Obtain()
|
|
||||||
{
|
{
|
||||||
if (RenderPasses.TryDequeue(out var renderPass))
|
return renderPass;
|
||||||
{
|
|
||||||
return renderPass;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return new RenderPass();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
public void Return(RenderPass renderPass)
|
|
||||||
{
|
{
|
||||||
RenderPasses.Enqueue(renderPass);
|
return new RenderPass();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Return(RenderPass renderPass)
|
||||||
|
{
|
||||||
|
RenderPasses.Enqueue(renderPass);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using RefreshCS;
|
using SDL2_gpuCS;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace MoonWorks.Graphics
|
namespace MoonWorks.Graphics
|
||||||
|
@ -8,34 +8,33 @@ namespace MoonWorks.Graphics
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ComputePipeline : SDL_GpuResource
|
public class ComputePipeline : SDL_GpuResource
|
||||||
{
|
{
|
||||||
protected override Action<IntPtr, IntPtr> ReleaseFunction => Refresh.Refresh_QueueDestroyComputePipeline;
|
protected override Action<IntPtr, IntPtr> ReleaseFunction => SDL_Gpu.SDL_GpuReleaseComputePipeline;
|
||||||
|
|
||||||
public ComputeShaderInfo ComputeShaderInfo { get; }
|
public ComputePipelineResourceInfo ResourceInfo { get; }
|
||||||
|
|
||||||
public unsafe ComputePipeline(
|
public unsafe ComputePipeline(
|
||||||
GraphicsDevice device,
|
GraphicsDevice device,
|
||||||
ComputeShaderInfo computeShaderInfo
|
Shader computeShader,
|
||||||
|
ComputePipelineResourceInfo resourceInfo
|
||||||
) : base(device)
|
) : base(device)
|
||||||
{
|
{
|
||||||
var refreshComputeShaderInfo = new Refresh.ComputeShaderInfo
|
var sdlComputePipelineCreateInfo = new SDL_Gpu.ComputePipelineCreateInfo
|
||||||
{
|
{
|
||||||
entryPointName = computeShaderInfo.EntryPointName,
|
ComputeShader = computeShader.Handle,
|
||||||
shaderModule = computeShaderInfo.ShaderModule.Handle,
|
PipelineResourceInfo = resourceInfo.ToSDL()
|
||||||
uniformBufferSize = computeShaderInfo.UniformBufferSize,
|
|
||||||
bufferBindingCount = computeShaderInfo.BufferBindingCount,
|
|
||||||
imageBindingCount = computeShaderInfo.ImageBindingCount
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Handle = Refresh.Refresh_CreateComputePipeline(
|
Handle = SDL_Gpu.SDL_GpuCreateComputePipeline(
|
||||||
device.Handle,
|
device.Handle,
|
||||||
refreshComputeShaderInfo
|
sdlComputePipelineCreateInfo
|
||||||
);
|
);
|
||||||
|
|
||||||
if (Handle == IntPtr.Zero)
|
if (Handle == IntPtr.Zero)
|
||||||
{
|
{
|
||||||
throw new Exception("Could not create compute pipeline!");
|
throw new Exception("Could not create compute pipeline!");
|
||||||
}
|
}
|
||||||
|
|
||||||
ComputeShaderInfo = computeShaderInfo;
|
ResourceInfo = resourceInfo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -230,10 +230,8 @@ namespace MoonWorks.Graphics
|
||||||
case TextureFormat.R8G8_SNORM:
|
case TextureFormat.R8G8_SNORM:
|
||||||
case TextureFormat.R8G8_UINT:
|
case TextureFormat.R8G8_UINT:
|
||||||
case TextureFormat.R16_UINT:
|
case TextureFormat.R16_UINT:
|
||||||
case TextureFormat.D16:
|
case TextureFormat.D16_UNORM:
|
||||||
return 2;
|
return 2;
|
||||||
case TextureFormat.D16S8:
|
|
||||||
return 3;
|
|
||||||
case TextureFormat.R8G8B8A8:
|
case TextureFormat.R8G8B8A8:
|
||||||
case TextureFormat.B8G8R8A8:
|
case TextureFormat.B8G8R8A8:
|
||||||
case TextureFormat.R32_SFLOAT:
|
case TextureFormat.R32_SFLOAT:
|
||||||
|
@ -243,9 +241,10 @@ namespace MoonWorks.Graphics
|
||||||
case TextureFormat.A2R10G10B10:
|
case TextureFormat.A2R10G10B10:
|
||||||
case TextureFormat.R8G8B8A8_UINT:
|
case TextureFormat.R8G8B8A8_UINT:
|
||||||
case TextureFormat.R16G16_UINT:
|
case TextureFormat.R16G16_UINT:
|
||||||
case TextureFormat.D32:
|
case TextureFormat.D24_UNORM_S8_UINT:
|
||||||
|
case TextureFormat.D32_SFLOAT:
|
||||||
return 4;
|
return 4;
|
||||||
case TextureFormat.D32S8:
|
case TextureFormat.D32_SFLOAT_S8_UINT:
|
||||||
return 5;
|
return 5;
|
||||||
case TextureFormat.R16G16B16A16_SFLOAT:
|
case TextureFormat.R16G16B16A16_SFLOAT:
|
||||||
case TextureFormat.R16G16B16A16:
|
case TextureFormat.R16G16B16A16:
|
||||||
|
@ -311,10 +310,11 @@ namespace MoonWorks.Graphics
|
||||||
case TextureFormat.R16_UINT:
|
case TextureFormat.R16_UINT:
|
||||||
case TextureFormat.R16G16_UINT:
|
case TextureFormat.R16G16_UINT:
|
||||||
case TextureFormat.R16G16B16A16_UINT:
|
case TextureFormat.R16G16B16A16_UINT:
|
||||||
case TextureFormat.D16:
|
case TextureFormat.D16_UNORM:
|
||||||
case TextureFormat.D32:
|
case TextureFormat.D24_UNORM:
|
||||||
case TextureFormat.D16S8:
|
case TextureFormat.D24_UNORM_S8_UINT:
|
||||||
case TextureFormat.D32S8:
|
case TextureFormat.D32_SFLOAT:
|
||||||
|
case TextureFormat.D32_SFLOAT_S8_UINT:
|
||||||
return 1;
|
return 1;
|
||||||
default:
|
default:
|
||||||
Logger.LogError("Texture format not recognized!");
|
Logger.LogError("Texture format not recognized!");
|
||||||
|
|
|
@ -840,6 +840,88 @@ public readonly record struct GraphicsPipelineResourceInfo(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public readonly record struct ComputePipelineResourceInfo(
|
||||||
|
uint ReadOnlyStorageTextureCount,
|
||||||
|
uint ReadOnlyStorageBufferCount,
|
||||||
|
uint ReadWriteStorageTextureCount,
|
||||||
|
uint ReadWriteStorageBufferCount,
|
||||||
|
uint UniformBufferCount
|
||||||
|
) {
|
||||||
|
public SDL_Gpu.ComputePipelineResourceInfo ToSDL()
|
||||||
|
{
|
||||||
|
return new SDL_Gpu.ComputePipelineResourceInfo
|
||||||
|
{
|
||||||
|
ReadOnlyStorageTextureCount = ReadOnlyStorageTextureCount,
|
||||||
|
ReadOnlyStorageBufferCount = ReadOnlyStorageBufferCount,
|
||||||
|
ReadWriteStorageTextureCount = ReadWriteStorageTextureCount,
|
||||||
|
ReadWriteStorageBufferCount = ReadWriteStorageBufferCount,
|
||||||
|
UniformBufferCount = UniformBufferCount
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A buffer-offset pair to be used when binding buffers.
|
||||||
|
/// </summary>
|
||||||
|
public readonly record struct BufferBinding(
|
||||||
|
GpuBuffer Buffer,
|
||||||
|
uint Offset
|
||||||
|
) {
|
||||||
|
public SDL_Gpu.BufferBinding ToSDL()
|
||||||
|
{
|
||||||
|
return new SDL_Gpu.BufferBinding
|
||||||
|
{
|
||||||
|
Buffer = Buffer.Handle,
|
||||||
|
Offset = Offset
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A texture-sampler pair to be used when binding samplers.
|
||||||
|
/// </summary>
|
||||||
|
public readonly record struct TextureSamplerBinding(
|
||||||
|
Texture Texture,
|
||||||
|
Sampler Sampler
|
||||||
|
) {
|
||||||
|
public SDL_Gpu.TextureSamplerBinding ToSDL()
|
||||||
|
{
|
||||||
|
return new SDL_Gpu.TextureSamplerBinding
|
||||||
|
{
|
||||||
|
Texture = Texture.Handle,
|
||||||
|
Sampler = Sampler.Handle
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly record struct StorageBufferReadWriteBinding(
|
||||||
|
GpuBuffer Buffer,
|
||||||
|
bool cycle
|
||||||
|
) {
|
||||||
|
public SDL_Gpu.StorageBufferReadWriteBinding ToSDL()
|
||||||
|
{
|
||||||
|
return new SDL_Gpu.StorageBufferReadWriteBinding
|
||||||
|
{
|
||||||
|
Buffer = Buffer.Handle,
|
||||||
|
Cycle = Conversions.BoolToInt(cycle)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly record struct StorageTextureReadWriteBinding(
|
||||||
|
in TextureSlice TextureSlice,
|
||||||
|
bool cycle
|
||||||
|
) {
|
||||||
|
public SDL_Gpu.StorageTextureReadWriteBinding ToSDL()
|
||||||
|
{
|
||||||
|
return new SDL_Gpu.StorageTextureReadWriteBinding
|
||||||
|
{
|
||||||
|
TextureSlice = TextureSlice.ToSDL(),
|
||||||
|
Cycle = Conversions.BoolToInt(cycle)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// All of the information that is used to create a GraphicsPipeline.
|
/// All of the information that is used to create a GraphicsPipeline.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -1,50 +0,0 @@
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
namespace MoonWorks.Graphics
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Information that the compute pipeline needs about a compute shader.
|
|
||||||
/// </summary>
|
|
||||||
public struct ComputeShaderInfo
|
|
||||||
{
|
|
||||||
public ShaderModule ShaderModule;
|
|
||||||
public string EntryPointName;
|
|
||||||
public uint UniformBufferSize;
|
|
||||||
public uint BufferBindingCount;
|
|
||||||
public uint ImageBindingCount;
|
|
||||||
|
|
||||||
public unsafe static ComputeShaderInfo Create<T>(
|
|
||||||
ShaderModule shaderModule,
|
|
||||||
string entryPointName,
|
|
||||||
uint bufferBindingCount,
|
|
||||||
uint imageBindingCount
|
|
||||||
) where T : unmanaged
|
|
||||||
{
|
|
||||||
return new ComputeShaderInfo
|
|
||||||
{
|
|
||||||
ShaderModule = shaderModule,
|
|
||||||
EntryPointName = entryPointName,
|
|
||||||
UniformBufferSize = (uint) Marshal.SizeOf<T>(),
|
|
||||||
BufferBindingCount = bufferBindingCount,
|
|
||||||
ImageBindingCount = imageBindingCount
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ComputeShaderInfo Create(
|
|
||||||
ShaderModule shaderModule,
|
|
||||||
string entryPointName,
|
|
||||||
uint bufferBindingCount,
|
|
||||||
uint imageBindingCount
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return new ComputeShaderInfo
|
|
||||||
{
|
|
||||||
ShaderModule = shaderModule,
|
|
||||||
EntryPointName = entryPointName,
|
|
||||||
UniformBufferSize = 0,
|
|
||||||
BufferBindingCount = bufferBindingCount,
|
|
||||||
ImageBindingCount = imageBindingCount
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue