rearrange methods in CommandBuffer
parent
fe520dc9cc
commit
d83501437d
|
@ -76,6 +76,57 @@ namespace MoonWorks.Graphics
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Acquires a swapchain texture.
|
||||||
|
/// This texture will be presented to the given window when the command buffer is submitted.
|
||||||
|
/// Can return null if the swapchain is unavailable. The user should ALWAYS handle the case where this occurs.
|
||||||
|
/// If null is returned, presentation will not occur.
|
||||||
|
/// It is an error to acquire two swapchain textures from the same window in one command buffer.
|
||||||
|
/// It is an error to dispose the swapchain texture. If you do this your game WILL crash. DO NOT DO THIS.
|
||||||
|
/// </summary>
|
||||||
|
public Texture AcquireSwapchainTexture(
|
||||||
|
Window window
|
||||||
|
) {
|
||||||
|
#if DEBUG
|
||||||
|
AssertNotSubmitted();
|
||||||
|
|
||||||
|
if (!window.Claimed)
|
||||||
|
{
|
||||||
|
throw new System.InvalidOperationException("Cannot acquire swapchain texture, window has not been claimed!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (swapchainTextureAcquired)
|
||||||
|
{
|
||||||
|
throw new System.InvalidOperationException("Cannot acquire two swapchain textures on the same command buffer!");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
var texturePtr = Refresh.Refresh_AcquireSwapchainTexture(
|
||||||
|
Device.Handle,
|
||||||
|
Handle,
|
||||||
|
window.Handle,
|
||||||
|
out var width,
|
||||||
|
out var height
|
||||||
|
);
|
||||||
|
|
||||||
|
if (texturePtr == IntPtr.Zero)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Override the texture properties to avoid allocating a new texture instance!
|
||||||
|
window.SwapchainTexture.Handle = texturePtr;
|
||||||
|
window.SwapchainTexture.Width = width;
|
||||||
|
window.SwapchainTexture.Height = height;
|
||||||
|
window.SwapchainTexture.Format = window.SwapchainFormat;
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
swapchainTextureAcquired = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return window.SwapchainTexture;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Begins a render pass.
|
/// Begins a render pass.
|
||||||
/// All render state, resource binding, and draw commands must be made within a render pass.
|
/// All render state, resource binding, and draw commands must be made within a render pass.
|
||||||
|
@ -526,397 +577,6 @@ namespace MoonWorks.Graphics
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
public void BeginComputePass()
|
|
||||||
{
|
|
||||||
#if DEBUG
|
|
||||||
AssertNotSubmitted();
|
|
||||||
AssertNotInPass("Cannot begin compute pass while in another pass!");
|
|
||||||
computePassActive = true;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Refresh.Refresh_BeginComputePass(
|
|
||||||
Device.Handle,
|
|
||||||
Handle
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <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
|
|
||||||
AssertNotSubmitted();
|
|
||||||
AssertInComputePass("Cannot bind compute pipeline outside of compute pass!");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Refresh.Refresh_BindComputePipeline(
|
|
||||||
Device.Handle,
|
|
||||||
Handle,
|
|
||||||
computePipeline.Handle
|
|
||||||
);
|
|
||||||
|
|
||||||
#if DEBUG
|
|
||||||
currentComputePipeline = computePipeline;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Binds a buffer to be used in the compute shader.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="buffer">A buffer to bind.</param>
|
|
||||||
public unsafe void BindComputeBuffers(
|
|
||||||
GpuBuffer buffer
|
|
||||||
) {
|
|
||||||
#if DEBUG
|
|
||||||
AssertNotSubmitted();
|
|
||||||
AssertInComputePass("Cannot bind compute buffers outside of compute pass!");
|
|
||||||
AssertComputePipelineBound();
|
|
||||||
AssertComputeBufferCount(1);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
var bufferPtrs = stackalloc IntPtr[1];
|
|
||||||
bufferPtrs[0] = buffer.Handle;
|
|
||||||
|
|
||||||
Refresh.Refresh_BindComputeBuffers(
|
|
||||||
Device.Handle,
|
|
||||||
Handle,
|
|
||||||
(IntPtr) bufferPtrs
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Binds buffers to be used in the compute shader.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="bufferOne">A buffer to bind.</param>
|
|
||||||
/// <param name="bufferTwo">A buffer to bind.</param>
|
|
||||||
public unsafe void BindComputeBuffers(
|
|
||||||
GpuBuffer bufferOne,
|
|
||||||
GpuBuffer bufferTwo
|
|
||||||
) {
|
|
||||||
#if DEBUG
|
|
||||||
AssertNotSubmitted();
|
|
||||||
AssertInComputePass("Cannot bind compute buffers outside of compute pass!");
|
|
||||||
AssertComputePipelineBound();
|
|
||||||
AssertComputeBufferCount(2);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
var bufferPtrs = stackalloc IntPtr[2];
|
|
||||||
bufferPtrs[0] = bufferOne.Handle;
|
|
||||||
bufferPtrs[1] = bufferTwo.Handle;
|
|
||||||
|
|
||||||
Refresh.Refresh_BindComputeBuffers(
|
|
||||||
Device.Handle,
|
|
||||||
Handle,
|
|
||||||
(IntPtr) bufferPtrs
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Binds buffers to be used in the compute shader.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="bufferOne">A buffer to bind.</param>
|
|
||||||
/// <param name="bufferTwo">A buffer to bind.</param>
|
|
||||||
/// <param name="bufferThree">A buffer to bind.</param>
|
|
||||||
public unsafe void BindComputeBuffers(
|
|
||||||
GpuBuffer bufferOne,
|
|
||||||
GpuBuffer bufferTwo,
|
|
||||||
GpuBuffer bufferThree
|
|
||||||
) {
|
|
||||||
#if DEBUG
|
|
||||||
AssertNotSubmitted();
|
|
||||||
AssertInComputePass("Cannot bind compute buffers outside of compute pass!");
|
|
||||||
AssertComputePipelineBound();
|
|
||||||
AssertComputeBufferCount(3);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
var bufferPtrs = stackalloc IntPtr[3];
|
|
||||||
bufferPtrs[0] = bufferOne.Handle;
|
|
||||||
bufferPtrs[1] = bufferTwo.Handle;
|
|
||||||
bufferPtrs[2] = bufferThree.Handle;
|
|
||||||
|
|
||||||
Refresh.Refresh_BindComputeBuffers(
|
|
||||||
Device.Handle,
|
|
||||||
Handle,
|
|
||||||
(IntPtr) bufferPtrs
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Binds buffers to be used in the compute shader.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="bufferOne">A buffer to bind.</param>
|
|
||||||
/// <param name="bufferTwo">A buffer to bind.</param>
|
|
||||||
/// <param name="bufferThree">A buffer to bind.</param>
|
|
||||||
/// <param name="bufferFour">A buffer to bind.</param>
|
|
||||||
public unsafe void BindComputeBuffers(
|
|
||||||
GpuBuffer bufferOne,
|
|
||||||
GpuBuffer bufferTwo,
|
|
||||||
GpuBuffer bufferThree,
|
|
||||||
GpuBuffer bufferFour
|
|
||||||
) {
|
|
||||||
#if DEBUG
|
|
||||||
AssertNotSubmitted();
|
|
||||||
AssertInComputePass("Cannot bind compute buffers outside of compute pass!");
|
|
||||||
AssertComputePipelineBound();
|
|
||||||
AssertComputeBufferCount(4);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
var bufferPtrs = stackalloc IntPtr[4];
|
|
||||||
bufferPtrs[0] = bufferOne.Handle;
|
|
||||||
bufferPtrs[1] = bufferTwo.Handle;
|
|
||||||
bufferPtrs[2] = bufferThree.Handle;
|
|
||||||
bufferPtrs[3] = bufferFour.Handle;
|
|
||||||
|
|
||||||
Refresh.Refresh_BindComputeBuffers(
|
|
||||||
Device.Handle,
|
|
||||||
Handle,
|
|
||||||
(IntPtr) bufferPtrs
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <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<GpuBuffer> buffers
|
|
||||||
) {
|
|
||||||
#if DEBUG
|
|
||||||
AssertNotSubmitted();
|
|
||||||
AssertInComputePass("Cannot bind compute buffers outside of compute pass!");
|
|
||||||
AssertComputePipelineBound();
|
|
||||||
AssertComputeBufferCount(buffers.Length);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
var bufferPtrs = stackalloc IntPtr[buffers.Length];
|
|
||||||
|
|
||||||
for (var i = 0; i < buffers.Length; i += 1)
|
|
||||||
{
|
|
||||||
bufferPtrs[i] = buffers[i].Handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
Refresh.Refresh_BindComputeBuffers(
|
|
||||||
Device.Handle,
|
|
||||||
Handle,
|
|
||||||
(IntPtr) bufferPtrs
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Binds a texture to be used in the compute shader.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="binding">A texture-level pair to bind.</param>
|
|
||||||
public unsafe void BindComputeTextures(
|
|
||||||
TextureLevelBinding binding
|
|
||||||
) {
|
|
||||||
#if DEBUG
|
|
||||||
AssertNotSubmitted();
|
|
||||||
AssertInComputePass("Cannot bind compute textures outside of compute pass!");
|
|
||||||
AssertComputePipelineBound();
|
|
||||||
AssertComputeTextureCount(1);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
var texturePtrs = stackalloc IntPtr[1];
|
|
||||||
texturePtrs[0] = binding.Texture.Handle;
|
|
||||||
|
|
||||||
var mipLevels = stackalloc uint[1];
|
|
||||||
mipLevels[0] = binding.MipLevel;
|
|
||||||
|
|
||||||
Refresh.Refresh_BindComputeTextures(
|
|
||||||
Device.Handle,
|
|
||||||
Handle,
|
|
||||||
(IntPtr) texturePtrs,
|
|
||||||
(IntPtr) mipLevels
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Binds textures to be used in the compute shader.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="bindingOne">A texture-level pair to bind.</param>
|
|
||||||
/// <param name="bindingTwo">A texture-level pair to bind.</param>
|
|
||||||
public unsafe void BindComputeTextures(
|
|
||||||
TextureLevelBinding bindingOne,
|
|
||||||
TextureLevelBinding bindingTwo
|
|
||||||
) {
|
|
||||||
#if DEBUG
|
|
||||||
AssertNotSubmitted();
|
|
||||||
AssertInComputePass("Cannot bind compute textures outside of compute pass!");
|
|
||||||
AssertComputePipelineBound();
|
|
||||||
AssertComputeTextureCount(2);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
var texturePtrs = stackalloc IntPtr[2];
|
|
||||||
texturePtrs[0] = bindingOne.Texture.Handle;
|
|
||||||
texturePtrs[1] = bindingTwo.Texture.Handle;
|
|
||||||
|
|
||||||
var mipLevels = stackalloc uint[2];
|
|
||||||
mipLevels[0] = bindingOne.MipLevel;
|
|
||||||
mipLevels[1] = bindingTwo.MipLevel;
|
|
||||||
|
|
||||||
Refresh.Refresh_BindComputeTextures(
|
|
||||||
Device.Handle,
|
|
||||||
Handle,
|
|
||||||
(IntPtr) texturePtrs,
|
|
||||||
(IntPtr) mipLevels
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Binds textures to be used in the compute shader.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="bindingOne">A texture-level pair to bind.</param>
|
|
||||||
/// <param name="bindingTwo">A texture-level pair to bind.</param>
|
|
||||||
/// <param name="bindingThree">A texture-level pair to bind.</param>
|
|
||||||
public unsafe void BindComputeTextures(
|
|
||||||
TextureLevelBinding bindingOne,
|
|
||||||
TextureLevelBinding bindingTwo,
|
|
||||||
TextureLevelBinding bindingThree
|
|
||||||
) {
|
|
||||||
#if DEBUG
|
|
||||||
AssertNotSubmitted();
|
|
||||||
AssertInComputePass("Cannot bind compute textures outside of compute pass!");
|
|
||||||
AssertComputePipelineBound();
|
|
||||||
AssertComputeTextureCount(3);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
var texturePtrs = stackalloc IntPtr[3];
|
|
||||||
texturePtrs[0] = bindingOne.Texture.Handle;
|
|
||||||
texturePtrs[1] = bindingTwo.Texture.Handle;
|
|
||||||
texturePtrs[2] = bindingThree.Texture.Handle;
|
|
||||||
|
|
||||||
var mipLevels = stackalloc uint[3];
|
|
||||||
mipLevels[0] = bindingOne.MipLevel;
|
|
||||||
mipLevels[1] = bindingTwo.MipLevel;
|
|
||||||
mipLevels[2] = bindingThree.MipLevel;
|
|
||||||
|
|
||||||
Refresh.Refresh_BindComputeTextures(
|
|
||||||
Device.Handle,
|
|
||||||
Handle,
|
|
||||||
(IntPtr) texturePtrs,
|
|
||||||
(IntPtr) mipLevels
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Binds textures to be used in the compute shader.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="bindingOne">A texture-level pair to bind.</param>
|
|
||||||
/// <param name="bindingTwo">A texture-level pair to bind.</param>
|
|
||||||
/// <param name="bindingThree">A texture-level pair to bind.</param>
|
|
||||||
/// <param name="bindingFour">A texture-level pair to bind.</param>
|
|
||||||
public unsafe void BindComputeTextures(
|
|
||||||
TextureLevelBinding bindingOne,
|
|
||||||
TextureLevelBinding bindingTwo,
|
|
||||||
TextureLevelBinding bindingThree,
|
|
||||||
TextureLevelBinding bindingFour
|
|
||||||
) {
|
|
||||||
#if DEBUG
|
|
||||||
AssertNotSubmitted();
|
|
||||||
AssertInComputePass("Cannot bind compute textures outside of compute pass!");
|
|
||||||
AssertComputePipelineBound();
|
|
||||||
AssertComputeTextureCount(4);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
var texturePtrs = stackalloc IntPtr[4];
|
|
||||||
texturePtrs[0] = bindingOne.Texture.Handle;
|
|
||||||
texturePtrs[1] = bindingTwo.Texture.Handle;
|
|
||||||
texturePtrs[2] = bindingThree.Texture.Handle;
|
|
||||||
texturePtrs[3] = bindingFour.Texture.Handle;
|
|
||||||
|
|
||||||
var mipLevels = stackalloc uint[4];
|
|
||||||
mipLevels[0] = bindingOne.MipLevel;
|
|
||||||
mipLevels[1] = bindingTwo.MipLevel;
|
|
||||||
mipLevels[2] = bindingThree.MipLevel;
|
|
||||||
mipLevels[3] = bindingFour.MipLevel;
|
|
||||||
|
|
||||||
Refresh.Refresh_BindComputeTextures(
|
|
||||||
Device.Handle,
|
|
||||||
Handle,
|
|
||||||
(IntPtr) texturePtrs,
|
|
||||||
(IntPtr) mipLevels
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Binds textures to be used in the compute shader.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="bindings">A set of texture-level pairs to bind.</param>
|
|
||||||
public unsafe void BindComputeTextures(
|
|
||||||
in Span<TextureLevelBinding> bindings
|
|
||||||
) {
|
|
||||||
#if DEBUG
|
|
||||||
AssertNotSubmitted();
|
|
||||||
AssertInComputePass("Cannot bind compute textures outside of compute pass!");
|
|
||||||
AssertComputePipelineBound();
|
|
||||||
AssertComputeTextureCount(bindings.Length);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
var texturePtrs = stackalloc IntPtr[bindings.Length];
|
|
||||||
var mipLevels = stackalloc uint[bindings.Length];
|
|
||||||
|
|
||||||
for (var i = 0; i < bindings.Length; i += 1)
|
|
||||||
{
|
|
||||||
texturePtrs[i] = bindings[i].Texture.Handle;
|
|
||||||
mipLevels[i] = bindings[i].MipLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
Refresh.Refresh_BindComputeTextures(
|
|
||||||
Device.Handle,
|
|
||||||
Handle,
|
|
||||||
(IntPtr) texturePtrs,
|
|
||||||
(IntPtr) mipLevels
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <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
|
|
||||||
AssertInComputePass("Cannot end compute pass while not in a compute pass!");
|
|
||||||
computePassActive = false;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Refresh.Refresh_EndComputePass(
|
|
||||||
Device.Handle,
|
|
||||||
Handle
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Binds a graphics pipeline so that rendering work may be performed.
|
/// Binds a graphics pipeline so that rendering work may be performed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -1671,51 +1331,6 @@ namespace MoonWorks.Graphics
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <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>
|
/// <summary>
|
||||||
/// Draws using instanced rendering.
|
/// Draws using instanced rendering.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -1865,55 +1480,440 @@ namespace MoonWorks.Graphics
|
||||||
EndRenderPass();
|
EndRenderPass();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void BeginComputePass()
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
AssertNotSubmitted();
|
||||||
|
AssertNotInPass("Cannot begin compute pass while in another pass!");
|
||||||
|
computePassActive = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Refresh.Refresh_BeginComputePass(
|
||||||
|
Device.Handle,
|
||||||
|
Handle
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Acquires a swapchain texture.
|
/// Binds a compute pipeline so that compute work may be dispatched.
|
||||||
/// This texture will be presented to the given window when the command buffer is submitted.
|
|
||||||
/// Can return null if the swapchain is unavailable. The user should ALWAYS handle the case where this occurs.
|
|
||||||
/// If null is returned, presentation will not occur.
|
|
||||||
/// It is an error to acquire two swapchain textures from the same window in one command buffer.
|
|
||||||
/// It is an error to dispose the swapchain texture. If you do this your game WILL crash. DO NOT DO THIS.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Texture AcquireSwapchainTexture(
|
/// <param name="computePipeline">The compute pipeline to bind.</param>
|
||||||
Window window
|
public void BindComputePipeline(
|
||||||
|
ComputePipeline computePipeline
|
||||||
) {
|
) {
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
AssertNotSubmitted();
|
AssertNotSubmitted();
|
||||||
|
AssertInComputePass("Cannot bind compute pipeline outside of compute pass!");
|
||||||
if (!window.Claimed)
|
|
||||||
{
|
|
||||||
throw new System.InvalidOperationException("Cannot acquire swapchain texture, window has not been claimed!");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (swapchainTextureAcquired)
|
|
||||||
{
|
|
||||||
throw new System.InvalidOperationException("Cannot acquire two swapchain textures on the same command buffer!");
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
var texturePtr = Refresh.Refresh_AcquireSwapchainTexture(
|
Refresh.Refresh_BindComputePipeline(
|
||||||
Device.Handle,
|
Device.Handle,
|
||||||
Handle,
|
Handle,
|
||||||
window.Handle,
|
computePipeline.Handle
|
||||||
out var width,
|
|
||||||
out var height
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if (texturePtr == IntPtr.Zero)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Override the texture properties to avoid allocating a new texture instance!
|
|
||||||
window.SwapchainTexture.Handle = texturePtr;
|
|
||||||
window.SwapchainTexture.Width = width;
|
|
||||||
window.SwapchainTexture.Height = height;
|
|
||||||
window.SwapchainTexture.Format = window.SwapchainFormat;
|
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
swapchainTextureAcquired = true;
|
currentComputePipeline = computePipeline;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Binds a buffer to be used in the compute shader.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="buffer">A buffer to bind.</param>
|
||||||
|
public unsafe void BindComputeBuffers(
|
||||||
|
GpuBuffer buffer
|
||||||
|
) {
|
||||||
|
#if DEBUG
|
||||||
|
AssertNotSubmitted();
|
||||||
|
AssertInComputePass("Cannot bind compute buffers outside of compute pass!");
|
||||||
|
AssertComputePipelineBound();
|
||||||
|
AssertComputeBufferCount(1);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return window.SwapchainTexture;
|
var bufferPtrs = stackalloc IntPtr[1];
|
||||||
|
bufferPtrs[0] = buffer.Handle;
|
||||||
|
|
||||||
|
Refresh.Refresh_BindComputeBuffers(
|
||||||
|
Device.Handle,
|
||||||
|
Handle,
|
||||||
|
(IntPtr) bufferPtrs
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Binds buffers to be used in the compute shader.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="bufferOne">A buffer to bind.</param>
|
||||||
|
/// <param name="bufferTwo">A buffer to bind.</param>
|
||||||
|
public unsafe void BindComputeBuffers(
|
||||||
|
GpuBuffer bufferOne,
|
||||||
|
GpuBuffer bufferTwo
|
||||||
|
) {
|
||||||
|
#if DEBUG
|
||||||
|
AssertNotSubmitted();
|
||||||
|
AssertInComputePass("Cannot bind compute buffers outside of compute pass!");
|
||||||
|
AssertComputePipelineBound();
|
||||||
|
AssertComputeBufferCount(2);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
var bufferPtrs = stackalloc IntPtr[2];
|
||||||
|
bufferPtrs[0] = bufferOne.Handle;
|
||||||
|
bufferPtrs[1] = bufferTwo.Handle;
|
||||||
|
|
||||||
|
Refresh.Refresh_BindComputeBuffers(
|
||||||
|
Device.Handle,
|
||||||
|
Handle,
|
||||||
|
(IntPtr) bufferPtrs
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Binds buffers to be used in the compute shader.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="bufferOne">A buffer to bind.</param>
|
||||||
|
/// <param name="bufferTwo">A buffer to bind.</param>
|
||||||
|
/// <param name="bufferThree">A buffer to bind.</param>
|
||||||
|
public unsafe void BindComputeBuffers(
|
||||||
|
GpuBuffer bufferOne,
|
||||||
|
GpuBuffer bufferTwo,
|
||||||
|
GpuBuffer bufferThree
|
||||||
|
) {
|
||||||
|
#if DEBUG
|
||||||
|
AssertNotSubmitted();
|
||||||
|
AssertInComputePass("Cannot bind compute buffers outside of compute pass!");
|
||||||
|
AssertComputePipelineBound();
|
||||||
|
AssertComputeBufferCount(3);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
var bufferPtrs = stackalloc IntPtr[3];
|
||||||
|
bufferPtrs[0] = bufferOne.Handle;
|
||||||
|
bufferPtrs[1] = bufferTwo.Handle;
|
||||||
|
bufferPtrs[2] = bufferThree.Handle;
|
||||||
|
|
||||||
|
Refresh.Refresh_BindComputeBuffers(
|
||||||
|
Device.Handle,
|
||||||
|
Handle,
|
||||||
|
(IntPtr) bufferPtrs
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Binds buffers to be used in the compute shader.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="bufferOne">A buffer to bind.</param>
|
||||||
|
/// <param name="bufferTwo">A buffer to bind.</param>
|
||||||
|
/// <param name="bufferThree">A buffer to bind.</param>
|
||||||
|
/// <param name="bufferFour">A buffer to bind.</param>
|
||||||
|
public unsafe void BindComputeBuffers(
|
||||||
|
GpuBuffer bufferOne,
|
||||||
|
GpuBuffer bufferTwo,
|
||||||
|
GpuBuffer bufferThree,
|
||||||
|
GpuBuffer bufferFour
|
||||||
|
) {
|
||||||
|
#if DEBUG
|
||||||
|
AssertNotSubmitted();
|
||||||
|
AssertInComputePass("Cannot bind compute buffers outside of compute pass!");
|
||||||
|
AssertComputePipelineBound();
|
||||||
|
AssertComputeBufferCount(4);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
var bufferPtrs = stackalloc IntPtr[4];
|
||||||
|
bufferPtrs[0] = bufferOne.Handle;
|
||||||
|
bufferPtrs[1] = bufferTwo.Handle;
|
||||||
|
bufferPtrs[2] = bufferThree.Handle;
|
||||||
|
bufferPtrs[3] = bufferFour.Handle;
|
||||||
|
|
||||||
|
Refresh.Refresh_BindComputeBuffers(
|
||||||
|
Device.Handle,
|
||||||
|
Handle,
|
||||||
|
(IntPtr) bufferPtrs
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <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<GpuBuffer> buffers
|
||||||
|
) {
|
||||||
|
#if DEBUG
|
||||||
|
AssertNotSubmitted();
|
||||||
|
AssertInComputePass("Cannot bind compute buffers outside of compute pass!");
|
||||||
|
AssertComputePipelineBound();
|
||||||
|
AssertComputeBufferCount(buffers.Length);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
var bufferPtrs = stackalloc IntPtr[buffers.Length];
|
||||||
|
|
||||||
|
for (var i = 0; i < buffers.Length; i += 1)
|
||||||
|
{
|
||||||
|
bufferPtrs[i] = buffers[i].Handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
Refresh.Refresh_BindComputeBuffers(
|
||||||
|
Device.Handle,
|
||||||
|
Handle,
|
||||||
|
(IntPtr) bufferPtrs
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Binds a texture to be used in the compute shader.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="binding">A texture-level pair to bind.</param>
|
||||||
|
public unsafe void BindComputeTextures(
|
||||||
|
TextureLevelBinding binding
|
||||||
|
) {
|
||||||
|
#if DEBUG
|
||||||
|
AssertNotSubmitted();
|
||||||
|
AssertInComputePass("Cannot bind compute textures outside of compute pass!");
|
||||||
|
AssertComputePipelineBound();
|
||||||
|
AssertComputeTextureCount(1);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
var texturePtrs = stackalloc IntPtr[1];
|
||||||
|
texturePtrs[0] = binding.Texture.Handle;
|
||||||
|
|
||||||
|
var mipLevels = stackalloc uint[1];
|
||||||
|
mipLevels[0] = binding.MipLevel;
|
||||||
|
|
||||||
|
Refresh.Refresh_BindComputeTextures(
|
||||||
|
Device.Handle,
|
||||||
|
Handle,
|
||||||
|
(IntPtr) texturePtrs,
|
||||||
|
(IntPtr) mipLevels
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Binds textures to be used in the compute shader.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="bindingOne">A texture-level pair to bind.</param>
|
||||||
|
/// <param name="bindingTwo">A texture-level pair to bind.</param>
|
||||||
|
public unsafe void BindComputeTextures(
|
||||||
|
TextureLevelBinding bindingOne,
|
||||||
|
TextureLevelBinding bindingTwo
|
||||||
|
) {
|
||||||
|
#if DEBUG
|
||||||
|
AssertNotSubmitted();
|
||||||
|
AssertInComputePass("Cannot bind compute textures outside of compute pass!");
|
||||||
|
AssertComputePipelineBound();
|
||||||
|
AssertComputeTextureCount(2);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
var texturePtrs = stackalloc IntPtr[2];
|
||||||
|
texturePtrs[0] = bindingOne.Texture.Handle;
|
||||||
|
texturePtrs[1] = bindingTwo.Texture.Handle;
|
||||||
|
|
||||||
|
var mipLevels = stackalloc uint[2];
|
||||||
|
mipLevels[0] = bindingOne.MipLevel;
|
||||||
|
mipLevels[1] = bindingTwo.MipLevel;
|
||||||
|
|
||||||
|
Refresh.Refresh_BindComputeTextures(
|
||||||
|
Device.Handle,
|
||||||
|
Handle,
|
||||||
|
(IntPtr) texturePtrs,
|
||||||
|
(IntPtr) mipLevels
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Binds textures to be used in the compute shader.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="bindingOne">A texture-level pair to bind.</param>
|
||||||
|
/// <param name="bindingTwo">A texture-level pair to bind.</param>
|
||||||
|
/// <param name="bindingThree">A texture-level pair to bind.</param>
|
||||||
|
public unsafe void BindComputeTextures(
|
||||||
|
TextureLevelBinding bindingOne,
|
||||||
|
TextureLevelBinding bindingTwo,
|
||||||
|
TextureLevelBinding bindingThree
|
||||||
|
) {
|
||||||
|
#if DEBUG
|
||||||
|
AssertNotSubmitted();
|
||||||
|
AssertInComputePass("Cannot bind compute textures outside of compute pass!");
|
||||||
|
AssertComputePipelineBound();
|
||||||
|
AssertComputeTextureCount(3);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
var texturePtrs = stackalloc IntPtr[3];
|
||||||
|
texturePtrs[0] = bindingOne.Texture.Handle;
|
||||||
|
texturePtrs[1] = bindingTwo.Texture.Handle;
|
||||||
|
texturePtrs[2] = bindingThree.Texture.Handle;
|
||||||
|
|
||||||
|
var mipLevels = stackalloc uint[3];
|
||||||
|
mipLevels[0] = bindingOne.MipLevel;
|
||||||
|
mipLevels[1] = bindingTwo.MipLevel;
|
||||||
|
mipLevels[2] = bindingThree.MipLevel;
|
||||||
|
|
||||||
|
Refresh.Refresh_BindComputeTextures(
|
||||||
|
Device.Handle,
|
||||||
|
Handle,
|
||||||
|
(IntPtr) texturePtrs,
|
||||||
|
(IntPtr) mipLevels
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Binds textures to be used in the compute shader.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="bindingOne">A texture-level pair to bind.</param>
|
||||||
|
/// <param name="bindingTwo">A texture-level pair to bind.</param>
|
||||||
|
/// <param name="bindingThree">A texture-level pair to bind.</param>
|
||||||
|
/// <param name="bindingFour">A texture-level pair to bind.</param>
|
||||||
|
public unsafe void BindComputeTextures(
|
||||||
|
TextureLevelBinding bindingOne,
|
||||||
|
TextureLevelBinding bindingTwo,
|
||||||
|
TextureLevelBinding bindingThree,
|
||||||
|
TextureLevelBinding bindingFour
|
||||||
|
) {
|
||||||
|
#if DEBUG
|
||||||
|
AssertNotSubmitted();
|
||||||
|
AssertInComputePass("Cannot bind compute textures outside of compute pass!");
|
||||||
|
AssertComputePipelineBound();
|
||||||
|
AssertComputeTextureCount(4);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
var texturePtrs = stackalloc IntPtr[4];
|
||||||
|
texturePtrs[0] = bindingOne.Texture.Handle;
|
||||||
|
texturePtrs[1] = bindingTwo.Texture.Handle;
|
||||||
|
texturePtrs[2] = bindingThree.Texture.Handle;
|
||||||
|
texturePtrs[3] = bindingFour.Texture.Handle;
|
||||||
|
|
||||||
|
var mipLevels = stackalloc uint[4];
|
||||||
|
mipLevels[0] = bindingOne.MipLevel;
|
||||||
|
mipLevels[1] = bindingTwo.MipLevel;
|
||||||
|
mipLevels[2] = bindingThree.MipLevel;
|
||||||
|
mipLevels[3] = bindingFour.MipLevel;
|
||||||
|
|
||||||
|
Refresh.Refresh_BindComputeTextures(
|
||||||
|
Device.Handle,
|
||||||
|
Handle,
|
||||||
|
(IntPtr) texturePtrs,
|
||||||
|
(IntPtr) mipLevels
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Binds textures to be used in the compute shader.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="bindings">A set of texture-level pairs to bind.</param>
|
||||||
|
public unsafe void BindComputeTextures(
|
||||||
|
in Span<TextureLevelBinding> bindings
|
||||||
|
) {
|
||||||
|
#if DEBUG
|
||||||
|
AssertNotSubmitted();
|
||||||
|
AssertInComputePass("Cannot bind compute textures outside of compute pass!");
|
||||||
|
AssertComputePipelineBound();
|
||||||
|
AssertComputeTextureCount(bindings.Length);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
var texturePtrs = stackalloc IntPtr[bindings.Length];
|
||||||
|
var mipLevels = stackalloc uint[bindings.Length];
|
||||||
|
|
||||||
|
for (var i = 0; i < bindings.Length; i += 1)
|
||||||
|
{
|
||||||
|
texturePtrs[i] = bindings[i].Texture.Handle;
|
||||||
|
mipLevels[i] = bindings[i].MipLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
Refresh.Refresh_BindComputeTextures(
|
||||||
|
Device.Handle,
|
||||||
|
Handle,
|
||||||
|
(IntPtr) texturePtrs,
|
||||||
|
(IntPtr) mipLevels
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <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
|
||||||
|
AssertInComputePass("Cannot end compute pass while not in a compute pass!");
|
||||||
|
computePassActive = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Refresh.Refresh_EndComputePass(
|
||||||
|
Device.Handle,
|
||||||
|
Handle
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy Pass
|
// Copy Pass
|
||||||
|
|
Loading…
Reference in New Issue