2022-02-23 05:14:32 +00:00
using System ;
2022-12-14 03:01:40 +00:00
using System.Runtime.InteropServices ;
2021-01-20 03:33:27 +00:00
using RefreshCS ;
namespace MoonWorks.Graphics
{
2022-02-23 05:14:32 +00:00
/// <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>
2024-01-18 20:27:34 +00:00
public class CommandBuffer
2022-02-23 05:14:32 +00:00
{
public GraphicsDevice Device { get ; }
2024-01-18 20:27:34 +00:00
public IntPtr Handle { get ; internal set ; }
2022-09-07 20:07:17 +00:00
2022-11-17 20:35:21 +00:00
#if DEBUG
2024-01-18 20:27:34 +00:00
bool swapchainTextureAcquired ;
2022-09-29 22:22:50 +00:00
GraphicsPipeline currentGraphicsPipeline ;
ComputePipeline currentComputePipeline ;
bool renderPassActive ;
2024-01-16 07:11:28 +00:00
SampleCount colorAttachmentSampleCount ;
uint colorAttachmentCount ;
2022-11-17 20:35:21 +00:00
TextureFormat colorFormatOne ;
TextureFormat colorFormatTwo ;
TextureFormat colorFormatThree ;
TextureFormat colorFormatFour ;
2024-01-16 07:11:28 +00:00
bool hasDepthStencilAttachment ;
SampleCount depthStencilAttachmentSampleCount ;
2022-11-17 20:35:21 +00:00
TextureFormat depthStencilFormat ;
2024-01-18 20:27:34 +00:00
2024-02-23 08:06:04 +00:00
bool copyPassActive ;
bool computePassActive ;
2024-01-18 20:27:34 +00:00
internal bool Submitted ;
2022-11-17 20:35:21 +00:00
# endif
2022-02-23 05:14:32 +00:00
2024-01-18 20:27:34 +00:00
// called from CommandBufferPool
internal CommandBuffer ( GraphicsDevice device )
2022-02-23 05:14:32 +00:00
{
Device = device ;
2024-01-18 20:27:34 +00:00
Handle = IntPtr . Zero ;
#if DEBUG
ResetStateTracking ( ) ;
# endif
}
internal void SetHandle ( nint handle )
{
2022-02-23 05:14:32 +00:00
Handle = handle ;
2024-01-18 20:27:34 +00:00
}
2022-11-17 20:35:21 +00:00
#if DEBUG
2024-01-18 20:27:34 +00:00
internal void ResetStateTracking ( )
{
swapchainTextureAcquired = false ;
2022-09-29 22:22:50 +00:00
currentGraphicsPipeline = null ;
currentComputePipeline = null ;
renderPassActive = false ;
2024-01-16 07:11:28 +00:00
colorAttachmentSampleCount = SampleCount . One ;
depthStencilAttachmentSampleCount = SampleCount . One ;
colorAttachmentCount = 0 ;
2022-11-17 20:35:21 +00:00
colorFormatOne = TextureFormat . R8G8B8A8 ;
colorFormatTwo = TextureFormat . R8G8B8A8 ;
colorFormatThree = TextureFormat . R8G8B8A8 ;
colorFormatFour = TextureFormat . R8G8B8A8 ;
depthStencilFormat = TextureFormat . D16 ;
2024-01-18 20:27:34 +00:00
2024-02-23 08:06:04 +00:00
copyPassActive = false ;
computePassActive = false ;
2024-01-18 20:27:34 +00:00
Submitted = false ;
2022-02-23 05:14:32 +00:00
}
2024-01-18 20:27:34 +00:00
# endif
2022-02-23 05:14:32 +00:00
2024-02-23 23:53:49 +00:00
/// <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 ;
}
2022-11-17 20:35:21 +00:00
/// <summary>
/// Begins a render pass.
/// All render state, resource binding, and draw commands must be made within a render pass.
2024-02-23 08:06:04 +00:00
/// It is an error to call this during any kind of pass.
2022-11-17 20:35:21 +00:00
/// </summary>
/// <param name="colorAttachmentInfo">The color attachment to use in the render pass.</param>
public unsafe void BeginRenderPass (
in ColorAttachmentInfo colorAttachmentInfo
) {
#if DEBUG
2024-01-18 20:27:34 +00:00
AssertNotSubmitted ( ) ;
2024-02-23 20:39:59 +00:00
AssertNotInPass ( "Cannot begin a render pass inside another pass!" ) ;
2022-11-17 20:35:21 +00:00
AssertTextureNotNull ( colorAttachmentInfo ) ;
AssertColorTarget ( colorAttachmentInfo ) ;
# endif
var refreshColorAttachmentInfos = stackalloc Refresh . ColorAttachmentInfo [ 1 ] ;
refreshColorAttachmentInfos [ 0 ] = colorAttachmentInfo . ToRefresh ( ) ;
Refresh . Refresh_BeginRenderPass (
Device . Handle ,
Handle ,
( IntPtr ) refreshColorAttachmentInfos ,
1 ,
IntPtr . Zero
) ;
#if DEBUG
renderPassActive = true ;
2024-01-16 07:11:28 +00:00
hasDepthStencilAttachment = false ;
2024-03-01 07:53:11 +00:00
colorAttachmentSampleCount = colorAttachmentInfo . TextureSlice . Texture . SampleCount ;
2024-01-16 07:11:28 +00:00
colorAttachmentCount = 1 ;
2024-03-01 07:53:11 +00:00
colorFormatOne = colorAttachmentInfo . TextureSlice . Texture . Format ;
2022-11-17 20:35:21 +00:00
# endif
}
2022-04-13 03:06:14 +00:00
2022-02-23 05:14:32 +00:00
/// <summary>
/// Begins a render pass.
/// All render state, resource binding, and draw commands must be made within a render pass.
/// It is an error to call this after calling BeginRenderPass but before calling EndRenderPass.
/// </summary>
2022-11-17 20:35:21 +00:00
/// <param name="colorAttachmentInfoOne">The first color attachment to use in the render pass.</param>
/// <param name="colorAttachmentInfoTwo">The second color attachment to use in the render pass.</param>
2022-02-23 05:14:32 +00:00
public unsafe void BeginRenderPass (
2022-11-17 20:35:21 +00:00
in ColorAttachmentInfo colorAttachmentInfoOne ,
in ColorAttachmentInfo colorAttachmentInfoTwo
) {
2022-02-25 05:34:36 +00:00
#if DEBUG
2024-01-18 20:27:34 +00:00
AssertNotSubmitted ( ) ;
2022-11-17 20:35:21 +00:00
AssertTextureNotNull ( colorAttachmentInfoOne ) ;
AssertColorTarget ( colorAttachmentInfoOne ) ;
AssertTextureNotNull ( colorAttachmentInfoTwo ) ;
AssertColorTarget ( colorAttachmentInfoTwo ) ;
2024-03-01 07:53:11 +00:00
AssertSameSampleCount ( colorAttachmentInfoOne . TextureSlice . Texture , colorAttachmentInfoTwo . TextureSlice . Texture ) ;
2022-02-25 05:34:36 +00:00
# endif
2022-11-17 20:35:21 +00:00
var refreshColorAttachmentInfos = stackalloc Refresh . ColorAttachmentInfo [ 2 ] ;
refreshColorAttachmentInfos [ 0 ] = colorAttachmentInfoOne . ToRefresh ( ) ;
refreshColorAttachmentInfos [ 1 ] = colorAttachmentInfoTwo . ToRefresh ( ) ;
2022-02-25 05:34:36 +00:00
2022-11-17 20:35:21 +00:00
Refresh . Refresh_BeginRenderPass (
Device . Handle ,
Handle ,
( IntPtr ) refreshColorAttachmentInfos ,
2 ,
IntPtr . Zero
) ;
2022-02-25 05:34:36 +00:00
2022-11-17 20:35:21 +00:00
#if DEBUG
renderPassActive = true ;
2024-01-16 07:11:28 +00:00
hasDepthStencilAttachment = false ;
2024-03-01 07:53:11 +00:00
colorAttachmentSampleCount = colorAttachmentInfoOne . TextureSlice . Texture . SampleCount ;
2024-01-16 07:11:28 +00:00
colorAttachmentCount = 2 ;
2024-03-01 07:53:11 +00:00
colorFormatOne = colorAttachmentInfoOne . TextureSlice . Texture . Format ;
colorFormatTwo = colorAttachmentInfoTwo . TextureSlice . Texture . Format ;
2022-11-17 20:35:21 +00:00
# endif
}
/// <summary>
/// Begins a render pass.
/// All render state, resource binding, and draw commands must be made within a render pass.
/// It is an error to call this after calling BeginRenderPass but before calling EndRenderPass.
/// </summary>
/// <param name="colorAttachmentInfoOne">The first color attachment to use in the render pass.</param>
/// <param name="colorAttachmentInfoTwo">The second color attachment to use in the render pass.</param>
/// <param name="colorAttachmentInfoThree">The third color attachment to use in the render pass.</param>
public unsafe void BeginRenderPass (
in ColorAttachmentInfo colorAttachmentInfoOne ,
in ColorAttachmentInfo colorAttachmentInfoTwo ,
in ColorAttachmentInfo colorAttachmentInfoThree
) {
#if DEBUG
2024-01-18 20:27:34 +00:00
AssertNotSubmitted ( ) ;
2022-11-17 20:35:21 +00:00
AssertTextureNotNull ( colorAttachmentInfoOne ) ;
AssertColorTarget ( colorAttachmentInfoOne ) ;
2022-09-07 20:07:17 +00:00
2022-11-17 20:35:21 +00:00
AssertTextureNotNull ( colorAttachmentInfoTwo ) ;
AssertColorTarget ( colorAttachmentInfoTwo ) ;
AssertTextureNotNull ( colorAttachmentInfoThree ) ;
AssertColorTarget ( colorAttachmentInfoThree ) ;
2024-03-01 07:53:11 +00:00
AssertSameSampleCount ( colorAttachmentInfoOne . TextureSlice . Texture , colorAttachmentInfoTwo . TextureSlice . Texture ) ;
AssertSameSampleCount ( colorAttachmentInfoOne . TextureSlice . Texture , colorAttachmentInfoThree . TextureSlice . Texture ) ;
2022-11-17 20:35:21 +00:00
# endif
var refreshColorAttachmentInfos = stackalloc Refresh . ColorAttachmentInfo [ 3 ] ;
refreshColorAttachmentInfos [ 0 ] = colorAttachmentInfoOne . ToRefresh ( ) ;
refreshColorAttachmentInfos [ 1 ] = colorAttachmentInfoTwo . ToRefresh ( ) ;
refreshColorAttachmentInfos [ 2 ] = colorAttachmentInfoThree . ToRefresh ( ) ;
Refresh . Refresh_BeginRenderPass (
Device . Handle ,
Handle ,
( IntPtr ) refreshColorAttachmentInfos ,
3 ,
IntPtr . Zero
) ;
#if DEBUG
2022-09-07 20:07:17 +00:00
renderPassActive = true ;
2024-01-16 07:11:28 +00:00
hasDepthStencilAttachment = false ;
2024-03-01 07:53:11 +00:00
colorAttachmentSampleCount = colorAttachmentInfoOne . TextureSlice . Texture . SampleCount ;
2024-01-16 07:11:28 +00:00
colorAttachmentCount = 3 ;
2024-03-01 07:53:11 +00:00
colorFormatOne = colorAttachmentInfoOne . TextureSlice . Texture . Format ;
colorFormatTwo = colorAttachmentInfoTwo . TextureSlice . Texture . Format ;
colorFormatThree = colorAttachmentInfoThree . TextureSlice . Texture . Format ;
2022-11-17 20:35:21 +00:00
# endif
}
/// <summary>
/// Begins a render pass.
/// All render state, resource binding, and draw commands must be made within a render pass.
/// It is an error to call this after calling BeginRenderPass but before calling EndRenderPass.
/// </summary>
/// <param name="colorAttachmentInfoOne">The first color attachment to use in the render pass.</param>
/// <param name="colorAttachmentInfoTwo">The second color attachment to use in the render pass.</param>
/// <param name="colorAttachmentInfoThree">The third color attachment to use in the render pass.</param>
/// <param name="colorAttachmentInfoFour">The four color attachment to use in the render pass.</param>
public unsafe void BeginRenderPass (
in ColorAttachmentInfo colorAttachmentInfoOne ,
in ColorAttachmentInfo colorAttachmentInfoTwo ,
in ColorAttachmentInfo colorAttachmentInfoThree ,
in ColorAttachmentInfo colorAttachmentInfoFour
) {
#if DEBUG
2024-01-18 20:27:34 +00:00
AssertNotSubmitted ( ) ;
2022-11-17 20:35:21 +00:00
AssertTextureNotNull ( colorAttachmentInfoOne ) ;
AssertColorTarget ( colorAttachmentInfoOne ) ;
AssertTextureNotNull ( colorAttachmentInfoTwo ) ;
AssertColorTarget ( colorAttachmentInfoTwo ) ;
AssertTextureNotNull ( colorAttachmentInfoThree ) ;
AssertColorTarget ( colorAttachmentInfoThree ) ;
AssertTextureNotNull ( colorAttachmentInfoFour ) ;
AssertColorTarget ( colorAttachmentInfoFour ) ;
2024-03-01 07:53:11 +00:00
AssertSameSampleCount ( colorAttachmentInfoOne . TextureSlice . Texture , colorAttachmentInfoTwo . TextureSlice . Texture ) ;
AssertSameSampleCount ( colorAttachmentInfoOne . TextureSlice . Texture , colorAttachmentInfoThree . TextureSlice . Texture ) ;
AssertSameSampleCount ( colorAttachmentInfoOne . TextureSlice . Texture , colorAttachmentInfoFour . TextureSlice . Texture ) ;
2022-11-17 20:35:21 +00:00
# endif
var refreshColorAttachmentInfos = stackalloc Refresh . ColorAttachmentInfo [ 4 ] ;
refreshColorAttachmentInfos [ 0 ] = colorAttachmentInfoOne . ToRefresh ( ) ;
refreshColorAttachmentInfos [ 1 ] = colorAttachmentInfoTwo . ToRefresh ( ) ;
refreshColorAttachmentInfos [ 2 ] = colorAttachmentInfoThree . ToRefresh ( ) ;
refreshColorAttachmentInfos [ 3 ] = colorAttachmentInfoFour . ToRefresh ( ) ;
Refresh . Refresh_BeginRenderPass (
Device . Handle ,
Handle ,
( IntPtr ) refreshColorAttachmentInfos ,
4 ,
IntPtr . Zero
) ;
#if DEBUG
renderPassActive = true ;
2024-01-16 07:11:28 +00:00
hasDepthStencilAttachment = false ;
2024-03-01 07:53:11 +00:00
colorAttachmentSampleCount = colorAttachmentInfoOne . TextureSlice . Texture . SampleCount ;
2024-01-16 07:11:28 +00:00
colorAttachmentCount = 4 ;
2024-03-01 07:53:11 +00:00
colorFormatOne = colorAttachmentInfoOne . TextureSlice . Texture . Format ;
colorFormatTwo = colorAttachmentInfoTwo . TextureSlice . Texture . Format ;
colorFormatThree = colorAttachmentInfoThree . TextureSlice . Texture . Format ;
colorFormatFour = colorAttachmentInfoFour . TextureSlice . Texture . Format ;
2022-11-17 20:35:21 +00:00
# endif
2022-02-23 05:14:32 +00:00
}
/// <summary>
/// Begins a render pass.
/// All render state, resource binding, and draw commands must be made within a render pass.
/// It is an error to call this after calling BeginRenderPass but before calling EndRenderPass.
/// </summary>
2022-02-25 05:34:36 +00:00
/// <param name="depthStencilAttachmentInfo">The depth stencil attachment to use in the render pass.</param>
2022-02-23 05:14:32 +00:00
public unsafe void BeginRenderPass (
2022-11-17 20:35:21 +00:00
in DepthStencilAttachmentInfo depthStencilAttachmentInfo
) {
2022-02-25 05:34:36 +00:00
#if DEBUG
2024-01-18 20:27:34 +00:00
AssertNotSubmitted ( ) ;
2022-11-09 18:49:53 +00:00
AssertValidDepthAttachment ( depthStencilAttachmentInfo ) ;
2022-02-25 05:34:36 +00:00
# endif
2022-11-17 20:35:21 +00:00
var refreshDepthStencilAttachmentInfo = depthStencilAttachmentInfo . ToRefresh ( ) ;
Refresh . Refresh_BeginRenderPass (
Device . Handle ,
Handle ,
( Refresh . ColorAttachmentInfo * ) IntPtr . Zero ,
0 ,
& refreshDepthStencilAttachmentInfo
) ;
2022-02-25 05:34:36 +00:00
2022-11-17 20:35:21 +00:00
#if DEBUG
renderPassActive = true ;
2024-01-16 07:11:28 +00:00
hasDepthStencilAttachment = true ;
2024-03-01 07:53:11 +00:00
depthStencilAttachmentSampleCount = depthStencilAttachmentInfo . TextureSlice . Texture . SampleCount ;
depthStencilFormat = depthStencilAttachmentInfo . TextureSlice . Texture . Format ;
2022-11-17 20:35:21 +00:00
# endif
}
/// <summary>
/// Begins a render pass.
/// All render state, resource binding, and draw commands must be made within a render pass.
/// It is an error to call this after calling BeginRenderPass but before calling EndRenderPass.
/// </summary>
/// <param name="depthStencilAttachmentInfo">The depth stencil attachment to use in the render pass.</param>
/// <param name="colorAttachmentInfo">The color attachment to use in the render pass.</param>
public unsafe void BeginRenderPass (
in DepthStencilAttachmentInfo depthStencilAttachmentInfo ,
in ColorAttachmentInfo colorAttachmentInfo
) {
#if DEBUG
2024-01-18 20:27:34 +00:00
AssertNotSubmitted ( ) ;
2022-11-17 20:35:21 +00:00
AssertValidDepthAttachment ( depthStencilAttachmentInfo ) ;
AssertTextureNotNull ( colorAttachmentInfo ) ;
AssertColorTarget ( colorAttachmentInfo ) ;
2024-03-01 07:53:11 +00:00
AssertSameSampleCount ( colorAttachmentInfo . TextureSlice . Texture , depthStencilAttachmentInfo . TextureSlice . Texture ) ;
2022-11-17 20:35:21 +00:00
# endif
var refreshColorAttachmentInfos = stackalloc Refresh . ColorAttachmentInfo [ 1 ] ;
refreshColorAttachmentInfos [ 0 ] = colorAttachmentInfo . ToRefresh ( ) ;
2022-02-25 05:34:36 +00:00
var refreshDepthStencilAttachmentInfo = depthStencilAttachmentInfo . ToRefresh ( ) ;
2022-11-17 20:35:21 +00:00
Refresh . Refresh_BeginRenderPass (
Device . Handle ,
Handle ,
refreshColorAttachmentInfos ,
1 ,
& refreshDepthStencilAttachmentInfo
) ;
#if DEBUG
renderPassActive = true ;
2024-01-16 07:11:28 +00:00
hasDepthStencilAttachment = true ;
2024-03-01 07:53:11 +00:00
colorAttachmentSampleCount = colorAttachmentInfo . TextureSlice . Texture . SampleCount ;
2024-01-16 07:11:28 +00:00
colorAttachmentCount = 1 ;
2024-03-01 07:53:11 +00:00
depthStencilAttachmentSampleCount = depthStencilAttachmentInfo . TextureSlice . Texture . SampleCount ;
colorFormatOne = colorAttachmentInfo . TextureSlice . Texture . Format ;
depthStencilFormat = depthStencilAttachmentInfo . TextureSlice . Texture . Format ;
2022-11-17 20:35:21 +00:00
# endif
}
/// <summary>
/// Begins a render pass.
/// All render state, resource binding, and draw commands must be made within a render pass.
/// It is an error to call this after calling BeginRenderPass but before calling EndRenderPass.
/// </summary>
/// <param name="depthStencilAttachmentInfo">The depth stencil attachment to use in the render pass.</param>
/// <param name="colorAttachmentInfoOne">The first color attachment to use in the render pass.</param>
/// <param name="colorAttachmentInfoTwo">The second color attachment to use in the render pass.</param>
public unsafe void BeginRenderPass (
in DepthStencilAttachmentInfo depthStencilAttachmentInfo ,
in ColorAttachmentInfo colorAttachmentInfoOne ,
in ColorAttachmentInfo colorAttachmentInfoTwo
) {
#if DEBUG
2024-01-18 20:27:34 +00:00
AssertNotSubmitted ( ) ;
2022-11-17 20:35:21 +00:00
AssertValidDepthAttachment ( depthStencilAttachmentInfo ) ;
AssertTextureNotNull ( colorAttachmentInfoOne ) ;
AssertColorTarget ( colorAttachmentInfoOne ) ;
AssertTextureNotNull ( colorAttachmentInfoTwo ) ;
AssertColorTarget ( colorAttachmentInfoTwo ) ;
2024-03-01 07:53:11 +00:00
AssertSameSampleCount ( colorAttachmentInfoOne . TextureSlice . Texture , colorAttachmentInfoTwo . TextureSlice . Texture ) ;
AssertSameSampleCount ( colorAttachmentInfoOne . TextureSlice . Texture , depthStencilAttachmentInfo . TextureSlice . Texture ) ;
2022-11-17 20:35:21 +00:00
# endif
var refreshColorAttachmentInfos = stackalloc Refresh . ColorAttachmentInfo [ 2 ] ;
refreshColorAttachmentInfos [ 0 ] = colorAttachmentInfoOne . ToRefresh ( ) ;
refreshColorAttachmentInfos [ 1 ] = colorAttachmentInfoTwo . ToRefresh ( ) ;
var refreshDepthStencilAttachmentInfo = depthStencilAttachmentInfo . ToRefresh ( ) ;
Refresh . Refresh_BeginRenderPass (
Device . Handle ,
Handle ,
refreshColorAttachmentInfos ,
2 ,
& refreshDepthStencilAttachmentInfo
) ;
#if DEBUG
renderPassActive = true ;
2024-01-16 07:11:28 +00:00
hasDepthStencilAttachment = true ;
2024-03-01 07:53:11 +00:00
colorAttachmentSampleCount = colorAttachmentInfoOne . TextureSlice . Texture . SampleCount ;
2024-01-16 07:11:28 +00:00
colorAttachmentCount = 2 ;
2024-03-01 07:53:11 +00:00
colorFormatOne = colorAttachmentInfoOne . TextureSlice . Texture . Format ;
colorFormatTwo = colorAttachmentInfoTwo . TextureSlice . Texture . Format ;
depthStencilFormat = depthStencilAttachmentInfo . TextureSlice . Texture . Format ;
2022-11-17 20:35:21 +00:00
# endif
}
/// <summary>
/// Begins a render pass.
/// All render state, resource binding, and draw commands must be made within a render pass.
/// It is an error to call this after calling BeginRenderPass but before calling EndRenderPass.
/// </summary>
/// <param name="depthStencilAttachmentInfo">The depth stencil attachment to use in the render pass.</param>
/// <param name="colorAttachmentInfoOne">The first color attachment to use in the render pass.</param>
/// <param name="colorAttachmentInfoTwo">The second color attachment to use in the render pass.</param>
/// <param name="colorAttachmentInfoThree">The third color attachment to use in the render pass.</param>
public unsafe void BeginRenderPass (
in DepthStencilAttachmentInfo depthStencilAttachmentInfo ,
in ColorAttachmentInfo colorAttachmentInfoOne ,
in ColorAttachmentInfo colorAttachmentInfoTwo ,
in ColorAttachmentInfo colorAttachmentInfoThree
) {
#if DEBUG
2024-01-18 20:27:34 +00:00
AssertNotSubmitted ( ) ;
2022-11-17 20:35:21 +00:00
AssertValidDepthAttachment ( depthStencilAttachmentInfo ) ;
AssertTextureNotNull ( colorAttachmentInfoOne ) ;
AssertColorTarget ( colorAttachmentInfoOne ) ;
AssertTextureNotNull ( colorAttachmentInfoTwo ) ;
AssertColorTarget ( colorAttachmentInfoTwo ) ;
AssertTextureNotNull ( colorAttachmentInfoThree ) ;
AssertColorTarget ( colorAttachmentInfoThree ) ;
2024-03-01 07:53:11 +00:00
AssertSameSampleCount ( colorAttachmentInfoOne . TextureSlice . Texture , colorAttachmentInfoTwo . TextureSlice . Texture ) ;
AssertSameSampleCount ( colorAttachmentInfoOne . TextureSlice . Texture , colorAttachmentInfoTwo . TextureSlice . Texture ) ;
AssertSameSampleCount ( colorAttachmentInfoOne . TextureSlice . Texture , depthStencilAttachmentInfo . TextureSlice . Texture ) ;
2022-11-17 20:35:21 +00:00
# endif
var refreshColorAttachmentInfos = stackalloc Refresh . ColorAttachmentInfo [ 3 ] ;
refreshColorAttachmentInfos [ 0 ] = colorAttachmentInfoOne . ToRefresh ( ) ;
refreshColorAttachmentInfos [ 1 ] = colorAttachmentInfoTwo . ToRefresh ( ) ;
refreshColorAttachmentInfos [ 2 ] = colorAttachmentInfoThree . ToRefresh ( ) ;
var refreshDepthStencilAttachmentInfo = depthStencilAttachmentInfo . ToRefresh ( ) ;
Refresh . Refresh_BeginRenderPass (
Device . Handle ,
Handle ,
refreshColorAttachmentInfos ,
3 ,
& refreshDepthStencilAttachmentInfo
) ;
#if DEBUG
renderPassActive = true ;
2024-01-16 07:11:28 +00:00
hasDepthStencilAttachment = true ;
2024-03-01 07:53:11 +00:00
colorAttachmentSampleCount = colorAttachmentInfoOne . TextureSlice . Texture . SampleCount ;
2024-01-16 07:11:28 +00:00
colorAttachmentCount = 3 ;
2024-03-01 07:53:11 +00:00
colorFormatOne = colorAttachmentInfoOne . TextureSlice . Texture . Format ;
colorFormatTwo = colorAttachmentInfoTwo . TextureSlice . Texture . Format ;
colorFormatThree = colorAttachmentInfoThree . TextureSlice . Texture . Format ;
depthStencilFormat = depthStencilAttachmentInfo . TextureSlice . Texture . Format ;
2022-11-17 20:35:21 +00:00
# endif
}
/// <summary>
/// Begins a render pass.
/// All render state, resource binding, and draw commands must be made within a render pass.
/// It is an error to call this after calling BeginRenderPass but before calling EndRenderPass.
/// </summary>
/// <param name="depthStencilAttachmentInfo">The depth stencil attachment to use in the render pass.</param>
/// <param name="colorAttachmentInfoOne">The first color attachment to use in the render pass.</param>
/// <param name="colorAttachmentInfoTwo">The second color attachment to use in the render pass.</param>
/// <param name="colorAttachmentInfoThree">The third color attachment to use in the render pass.</param>
/// <param name="colorAttachmentInfoFour">The four color attachment to use in the render pass.</param>
public unsafe void BeginRenderPass (
in DepthStencilAttachmentInfo depthStencilAttachmentInfo ,
in ColorAttachmentInfo colorAttachmentInfoOne ,
in ColorAttachmentInfo colorAttachmentInfoTwo ,
in ColorAttachmentInfo colorAttachmentInfoThree ,
in ColorAttachmentInfo colorAttachmentInfoFour
) {
#if DEBUG
2024-01-18 20:27:34 +00:00
AssertNotSubmitted ( ) ;
2022-11-17 20:35:21 +00:00
AssertValidDepthAttachment ( depthStencilAttachmentInfo ) ;
AssertTextureNotNull ( colorAttachmentInfoOne ) ;
AssertColorTarget ( colorAttachmentInfoOne ) ;
AssertTextureNotNull ( colorAttachmentInfoTwo ) ;
AssertColorTarget ( colorAttachmentInfoTwo ) ;
AssertTextureNotNull ( colorAttachmentInfoThree ) ;
AssertColorTarget ( colorAttachmentInfoThree ) ;
AssertTextureNotNull ( colorAttachmentInfoFour ) ;
AssertColorTarget ( colorAttachmentInfoFour ) ;
2024-03-01 07:53:11 +00:00
AssertSameSampleCount ( colorAttachmentInfoOne . TextureSlice . Texture , colorAttachmentInfoTwo . TextureSlice . Texture ) ;
AssertSameSampleCount ( colorAttachmentInfoOne . TextureSlice . Texture , colorAttachmentInfoThree . TextureSlice . Texture ) ;
AssertSameSampleCount ( colorAttachmentInfoOne . TextureSlice . Texture , colorAttachmentInfoFour . TextureSlice . Texture ) ;
AssertSameSampleCount ( colorAttachmentInfoOne . TextureSlice . Texture , depthStencilAttachmentInfo . TextureSlice . Texture ) ;
2022-11-17 20:35:21 +00:00
# endif
var refreshColorAttachmentInfos = stackalloc Refresh . ColorAttachmentInfo [ 4 ] ;
refreshColorAttachmentInfos [ 0 ] = colorAttachmentInfoOne . ToRefresh ( ) ;
refreshColorAttachmentInfos [ 1 ] = colorAttachmentInfoTwo . ToRefresh ( ) ;
refreshColorAttachmentInfos [ 2 ] = colorAttachmentInfoThree . ToRefresh ( ) ;
refreshColorAttachmentInfos [ 3 ] = colorAttachmentInfoFour . ToRefresh ( ) ;
var refreshDepthStencilAttachmentInfo = depthStencilAttachmentInfo . ToRefresh ( ) ;
2022-09-07 20:07:17 +00:00
2022-11-17 20:35:21 +00:00
Refresh . Refresh_BeginRenderPass (
Device . Handle ,
Handle ,
refreshColorAttachmentInfos ,
4 ,
& refreshDepthStencilAttachmentInfo
) ;
#if DEBUG
2022-09-07 20:07:17 +00:00
renderPassActive = true ;
2024-01-16 07:11:28 +00:00
hasDepthStencilAttachment = true ;
2024-03-01 07:53:11 +00:00
colorAttachmentSampleCount = colorAttachmentInfoOne . TextureSlice . Texture . SampleCount ;
2024-01-16 07:11:28 +00:00
colorAttachmentCount = 4 ;
2024-03-01 07:53:11 +00:00
colorFormatOne = colorAttachmentInfoOne . TextureSlice . Texture . Format ;
colorFormatTwo = colorAttachmentInfoTwo . TextureSlice . Texture . Format ;
colorFormatThree = colorAttachmentInfoThree . TextureSlice . Texture . Format ;
colorFormatFour = colorAttachmentInfoFour . TextureSlice . Texture . Format ;
depthStencilFormat = depthStencilAttachmentInfo . TextureSlice . Texture . Format ;
2022-11-17 20:35:21 +00:00
# endif
2022-02-23 05:14:32 +00:00
}
/// <summary>
2024-02-23 23:53:49 +00:00
/// Binds a graphics pipeline so that rendering work may be performed.
2022-02-23 05:14:32 +00:00
/// </summary>
2024-02-23 23:53:49 +00:00
/// <param name="graphicsPipeline">The graphics pipeline to bind.</param>
public void BindGraphicsPipeline (
GraphicsPipeline graphicsPipeline
2022-11-17 20:35:21 +00:00
) {
2024-01-18 20:27:34 +00:00
#if DEBUG
AssertNotSubmitted ( ) ;
2024-02-23 23:53:49 +00:00
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}" ) ;
}
}
2024-01-18 20:27:34 +00:00
# endif
2024-02-23 23:53:49 +00:00
Refresh . Refresh_BindGraphicsPipeline (
2022-02-23 05:14:32 +00:00
Device . Handle ,
Handle ,
2024-02-23 23:53:49 +00:00
graphicsPipeline . Handle
2022-02-23 05:14:32 +00:00
) ;
2022-09-07 20:07:17 +00:00
2022-11-17 20:35:21 +00:00
#if DEBUG
2024-02-23 23:53:49 +00:00
currentGraphicsPipeline = graphicsPipeline ;
2022-11-17 20:35:21 +00:00
# endif
}
/// <summary>
2024-02-23 23:53:49 +00:00
/// Sets the viewport. Only valid during a render pass.
2022-11-17 20:35:21 +00:00
/// </summary>
2024-02-23 23:53:49 +00:00
public void SetViewport ( in Viewport viewport )
{
2022-11-17 20:35:21 +00:00
#if DEBUG
2024-01-18 20:27:34 +00:00
AssertNotSubmitted ( ) ;
2024-02-23 23:53:49 +00:00
AssertRenderPassActive ( ) ;
2022-11-17 20:35:21 +00:00
# endif
2024-02-23 23:53:49 +00:00
Refresh . Refresh_SetViewport (
2022-11-17 20:35:21 +00:00
Device . Handle ,
Handle ,
2024-02-23 23:53:49 +00:00
viewport . ToRefresh ( )
2022-11-17 20:35:21 +00:00
) ;
2022-02-23 05:14:32 +00:00
}
/// <summary>
2024-02-23 23:53:49 +00:00
/// Sets the scissor area. Only valid during a render pass.
2022-02-23 05:14:32 +00:00
/// </summary>
2024-02-23 23:53:49 +00:00
public void SetScissor ( in Rect scissor )
{
2022-09-07 20:07:17 +00:00
#if DEBUG
2024-01-18 20:27:34 +00:00
AssertNotSubmitted ( ) ;
2024-02-23 23:53:49 +00:00
AssertRenderPassActive ( ) ;
2022-09-07 20:07:17 +00:00
2024-02-23 23:53:49 +00:00
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
2022-09-07 20:07:17 +00:00
2024-02-23 23:53:49 +00:00
Refresh . Refresh_SetScissor (
2022-11-17 20:35:21 +00:00
Device . Handle ,
Handle ,
2024-02-23 23:53:49 +00:00
scissor . ToRefresh ( )
2022-11-17 20:35:21 +00:00
) ;
}
/// <summary>
2024-02-23 23:53:49 +00:00
/// Binds vertex buffers to be used by subsequent draw calls.
2022-11-17 20:35:21 +00:00
/// </summary>
2024-02-23 23:53:49 +00:00
/// <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
2022-11-17 20:35:21 +00:00
) {
#if DEBUG
2024-01-18 20:27:34 +00:00
AssertNotSubmitted ( ) ;
2024-02-23 23:53:49 +00:00
AssertGraphicsPipelineBound ( ) ;
2022-11-17 20:35:21 +00:00
# endif
2024-03-01 23:03:14 +00:00
var bindingArray = stackalloc Refresh . BufferBinding [ 1 ] ;
bindingArray [ 0 ] = bufferBinding . ToRefresh ( ) ;
2024-02-23 23:53:49 +00:00
Refresh . Refresh_BindVertexBuffers (
2022-11-17 20:35:21 +00:00
Device . Handle ,
Handle ,
2024-02-23 23:53:49 +00:00
firstBinding ,
1 ,
2024-03-01 23:03:14 +00:00
bindingArray
2022-11-17 20:35:21 +00:00
) ;
}
/// <summary>
2024-02-23 23:53:49 +00:00
/// Binds vertex buffers to be used by subsequent draw calls.
2022-11-17 20:35:21 +00:00
/// </summary>
2024-02-23 23:53:49 +00:00
/// <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
2022-11-17 20:35:21 +00:00
) {
#if DEBUG
2024-01-18 20:27:34 +00:00
AssertNotSubmitted ( ) ;
2024-02-23 23:53:49 +00:00
AssertGraphicsPipelineBound ( ) ;
2022-11-17 20:35:21 +00:00
# endif
2024-03-01 23:03:14 +00:00
var bindingArray = stackalloc Refresh . BufferBinding [ 2 ] ;
bindingArray [ 0 ] = bufferBindingOne . ToRefresh ( ) ;
bindingArray [ 1 ] = bufferBindingTwo . ToRefresh ( ) ;
2024-02-23 23:53:49 +00:00
Refresh . Refresh_BindVertexBuffers (
2022-11-17 20:35:21 +00:00
Device . Handle ,
Handle ,
2024-02-23 23:53:49 +00:00
firstBinding ,
2 ,
2024-03-01 23:03:14 +00:00
bindingArray
2022-11-17 20:35:21 +00:00
) ;
}
/// <summary>
2024-02-23 23:53:49 +00:00
/// Binds vertex buffers to be used by subsequent draw calls.
2022-11-17 20:35:21 +00:00
/// </summary>
2024-02-23 23:53:49 +00:00
/// <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
2022-11-17 20:35:21 +00:00
) {
#if DEBUG
2024-01-18 20:27:34 +00:00
AssertNotSubmitted ( ) ;
2024-02-23 23:53:49 +00:00
AssertGraphicsPipelineBound ( ) ;
2022-09-07 20:07:17 +00:00
# endif
2024-03-01 23:03:14 +00:00
var bindingArray = stackalloc Refresh . BufferBinding [ 3 ] ;
bindingArray [ 0 ] = bufferBindingOne . ToRefresh ( ) ;
bindingArray [ 1 ] = bufferBindingTwo . ToRefresh ( ) ;
bindingArray [ 2 ] = bufferBindingThree . ToRefresh ( ) ;
2024-02-23 23:53:49 +00:00
Refresh . Refresh_BindVertexBuffers (
2022-02-23 05:14:32 +00:00
Device . Handle ,
Handle ,
2024-02-23 23:53:49 +00:00
firstBinding ,
3 ,
2024-03-01 23:03:14 +00:00
bindingArray
2024-02-23 23:53:49 +00:00
) ;
2022-02-23 05:14:32 +00:00
}
2022-11-17 20:35:21 +00:00
/// <summary>
2024-02-23 23:53:49 +00:00
/// Binds vertex buffers to be used by subsequent draw calls.
2022-11-17 20:35:21 +00:00
/// </summary>
2024-02-23 23:53:49 +00:00
/// <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
2022-11-17 20:35:21 +00:00
) {
#if DEBUG
2024-01-18 20:27:34 +00:00
AssertNotSubmitted ( ) ;
2024-02-23 23:53:49 +00:00
AssertGraphicsPipelineBound ( ) ;
2022-11-17 20:35:21 +00:00
# endif
2024-03-01 23:03:14 +00:00
var bindingArray = stackalloc Refresh . BufferBinding [ 4 ] ;
bindingArray [ 0 ] = bufferBindingOne . ToRefresh ( ) ;
bindingArray [ 1 ] = bufferBindingTwo . ToRefresh ( ) ;
bindingArray [ 2 ] = bufferBindingThree . ToRefresh ( ) ;
bindingArray [ 3 ] = bufferBindingFour . ToRefresh ( ) ;
2024-02-23 23:53:49 +00:00
Refresh . Refresh_BindVertexBuffers (
2022-11-17 20:35:21 +00:00
Device . Handle ,
Handle ,
2024-02-23 23:53:49 +00:00
firstBinding ,
4 ,
2024-03-01 23:03:14 +00:00
bindingArray
2022-11-17 20:35:21 +00:00
) ;
}
2022-02-23 05:14:32 +00:00
/// <summary>
2024-02-23 23:53:49 +00:00
/// Binds vertex buffers to be used by subsequent draw calls.
2022-02-23 05:14:32 +00:00
/// </summary>
2024-02-23 23:53:49 +00:00
/// <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
2022-11-17 20:35:21 +00:00
) {
2022-09-07 20:07:17 +00:00
#if DEBUG
2024-01-18 20:27:34 +00:00
AssertNotSubmitted ( ) ;
2024-02-23 23:53:49 +00:00
AssertGraphicsPipelineBound ( ) ;
2022-11-17 20:35:21 +00:00
# endif
2022-09-07 20:07:17 +00:00
2024-03-01 23:03:14 +00:00
Refresh . BufferBinding * bufferBindingsArray = ( Refresh . BufferBinding * ) NativeMemory . Alloc ( ( nuint ) ( Marshal . SizeOf < Refresh . BufferBinding > ( ) * bufferBindings . Length ) ) ;
2024-02-23 08:06:04 +00:00
2024-02-23 23:53:49 +00:00
for ( var i = 0 ; i < bufferBindings . Length ; i + = 1 )
{
2024-03-01 23:03:14 +00:00
bufferBindingsArray [ i ] = bufferBindings [ i ] . ToRefresh ( ) ;
2024-02-23 23:53:49 +00:00
}
2022-09-07 20:07:17 +00:00
2024-02-23 23:53:49 +00:00
Refresh . Refresh_BindVertexBuffers (
2022-11-17 20:35:21 +00:00
Device . Handle ,
Handle ,
2024-02-23 23:53:49 +00:00
firstBinding ,
( uint ) bufferBindings . Length ,
2024-03-01 23:03:14 +00:00
bufferBindingsArray
2022-11-17 20:35:21 +00:00
) ;
2024-03-01 23:03:14 +00:00
NativeMemory . Free ( bufferBindingsArray ) ;
2022-11-17 20:35:21 +00:00
}
/// <summary>
2024-02-23 23:53:49 +00:00
/// Binds an index buffer to be used by subsequent draw calls.
2022-11-17 20:35:21 +00:00
/// </summary>
2024-02-23 23:53:49 +00:00
/// <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 (
2024-03-01 23:03:14 +00:00
BufferBinding bufferBinding ,
IndexElementSize indexElementSize
2024-02-23 23:53:49 +00:00
)
{
2022-11-17 20:35:21 +00:00
#if DEBUG
2024-01-18 20:27:34 +00:00
AssertNotSubmitted ( ) ;
2022-11-17 20:35:21 +00:00
# endif
2024-02-23 23:53:49 +00:00
Refresh . Refresh_BindIndexBuffer (
2022-11-17 20:35:21 +00:00
Device . Handle ,
Handle ,
2024-03-01 23:03:14 +00:00
bufferBinding . ToRefresh ( ) ,
2024-02-23 23:53:49 +00:00
( Refresh . IndexElementSize ) indexElementSize
2022-11-17 20:35:21 +00:00
) ;
}
/// <summary>
2024-02-23 23:53:49 +00:00
/// Binds samplers to be used by the vertex shader.
2022-11-17 20:35:21 +00:00
/// </summary>
2024-02-23 23:53:49 +00:00
/// <param name="textureSamplerBindings">The texture-sampler to bind.</param>
public unsafe void BindVertexSamplers (
in TextureSamplerBinding textureSamplerBinding
2022-11-17 20:35:21 +00:00
) {
#if DEBUG
2024-01-18 20:27:34 +00:00
AssertNotSubmitted ( ) ;
2024-02-23 23:53:49 +00:00
AssertGraphicsPipelineBound ( ) ;
AssertVertexSamplerCount ( 1 ) ;
AssertTextureSamplerBindingNonNull ( textureSamplerBinding ) ;
AssertTextureBindingUsageFlags ( textureSamplerBinding . Texture ) ;
2022-11-17 20:35:21 +00:00
# endif
2024-03-01 23:03:14 +00:00
var bindingArray = stackalloc Refresh . TextureSamplerBinding [ 1 ] ;
bindingArray [ 0 ] = textureSamplerBinding . ToRefresh ( ) ;
2022-11-17 20:35:21 +00:00
2024-02-23 23:53:49 +00:00
Refresh . Refresh_BindVertexSamplers (
2022-11-17 20:35:21 +00:00
Device . Handle ,
Handle ,
2024-03-01 23:03:14 +00:00
bindingArray
2022-11-17 20:35:21 +00:00
) ;
}
/// <summary>
2024-02-23 23:53:49 +00:00
/// Binds samplers to be used by the vertex shader.
2022-11-17 20:35:21 +00:00
/// </summary>
2024-02-23 23:53:49 +00:00
/// <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
2022-11-17 20:35:21 +00:00
) {
#if DEBUG
2024-01-18 20:27:34 +00:00
AssertNotSubmitted ( ) ;
2024-02-23 23:53:49 +00:00
AssertGraphicsPipelineBound ( ) ;
AssertVertexSamplerCount ( 2 ) ;
AssertTextureSamplerBindingNonNull ( textureSamplerBindingOne ) ;
AssertTextureSamplerBindingNonNull ( textureSamplerBindingTwo ) ;
AssertTextureBindingUsageFlags ( textureSamplerBindingOne . Texture ) ;
AssertTextureBindingUsageFlags ( textureSamplerBindingTwo . Texture ) ;
2022-09-07 20:07:17 +00:00
# endif
2024-03-01 23:03:14 +00:00
var bindingArray = stackalloc Refresh . TextureSamplerBinding [ 2 ] ;
bindingArray [ 0 ] = textureSamplerBindingOne . ToRefresh ( ) ;
bindingArray [ 1 ] = textureSamplerBindingTwo . ToRefresh ( ) ;
2024-02-23 23:53:49 +00:00
Refresh . Refresh_BindVertexSamplers (
2022-02-23 05:14:32 +00:00
Device . Handle ,
Handle ,
2024-03-01 23:03:14 +00:00
bindingArray
2022-02-23 05:14:32 +00:00
) ;
}
/// <summary>
2024-02-23 23:53:49 +00:00
/// Binds samplers to be used by the vertex shader.
2022-02-23 05:14:32 +00:00
/// </summary>
2024-02-23 23:53:49 +00:00
/// <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
2022-11-17 20:35:21 +00:00
) {
2022-09-07 20:07:17 +00:00
#if DEBUG
2024-01-18 20:27:34 +00:00
AssertNotSubmitted ( ) ;
2024-02-23 23:53:49 +00:00
AssertGraphicsPipelineBound ( ) ;
AssertVertexSamplerCount ( 3 ) ;
AssertTextureSamplerBindingNonNull ( textureSamplerBindingOne ) ;
AssertTextureSamplerBindingNonNull ( textureSamplerBindingTwo ) ;
AssertTextureSamplerBindingNonNull ( textureSamplerBindingThree ) ;
AssertTextureBindingUsageFlags ( textureSamplerBindingOne . Texture ) ;
AssertTextureBindingUsageFlags ( textureSamplerBindingTwo . Texture ) ;
AssertTextureBindingUsageFlags ( textureSamplerBindingThree . Texture ) ;
2022-09-07 20:07:17 +00:00
# endif
2024-03-01 23:03:14 +00:00
var bindingArray = stackalloc Refresh . TextureSamplerBinding [ 3 ] ;
bindingArray [ 0 ] = textureSamplerBindingOne . ToRefresh ( ) ;
bindingArray [ 1 ] = textureSamplerBindingTwo . ToRefresh ( ) ;
bindingArray [ 2 ] = textureSamplerBindingThree . ToRefresh ( ) ;
2024-02-23 23:53:49 +00:00
Refresh . Refresh_BindVertexSamplers (
2022-02-23 05:14:32 +00:00
Device . Handle ,
Handle ,
2024-03-01 23:03:14 +00:00
bindingArray
2024-02-23 18:43:39 +00:00
) ;
}
2022-02-23 05:14:32 +00:00
/// <summary>
2024-02-23 23:53:49 +00:00
/// Binds samplers to be used by the vertex shader.
2022-02-23 05:14:32 +00:00
/// </summary>
2024-02-23 23:53:49 +00:00
/// <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
2022-11-17 20:35:21 +00:00
) {
2022-11-09 18:49:53 +00:00
#if DEBUG
2024-01-18 20:27:34 +00:00
AssertNotSubmitted ( ) ;
2024-02-23 23:53:49 +00:00
AssertGraphicsPipelineBound ( ) ;
AssertVertexSamplerCount ( 4 ) ;
AssertTextureSamplerBindingNonNull ( textureSamplerBindingOne ) ;
AssertTextureSamplerBindingNonNull ( textureSamplerBindingTwo ) ;
AssertTextureSamplerBindingNonNull ( textureSamplerBindingThree ) ;
AssertTextureSamplerBindingNonNull ( textureSamplerBindingFour ) ;
AssertTextureBindingUsageFlags ( textureSamplerBindingOne . Texture ) ;
AssertTextureBindingUsageFlags ( textureSamplerBindingTwo . Texture ) ;
AssertTextureBindingUsageFlags ( textureSamplerBindingThree . Texture ) ;
AssertTextureBindingUsageFlags ( textureSamplerBindingFour . Texture ) ;
# endif
2022-11-09 18:49:53 +00:00
2024-03-01 23:03:14 +00:00
var bindingArray = stackalloc Refresh . TextureSamplerBinding [ 4 ] ;
bindingArray [ 0 ] = textureSamplerBindingOne . ToRefresh ( ) ;
bindingArray [ 1 ] = textureSamplerBindingTwo . ToRefresh ( ) ;
bindingArray [ 2 ] = textureSamplerBindingThree . ToRefresh ( ) ;
bindingArray [ 3 ] = textureSamplerBindingFour . ToRefresh ( ) ;
2024-02-23 23:53:49 +00:00
Refresh . Refresh_BindVertexSamplers (
2022-02-23 05:14:32 +00:00
Device . Handle ,
Handle ,
2024-03-01 23:03:14 +00:00
bindingArray
2022-02-23 05:14:32 +00:00
) ;
}
2022-03-04 22:14:22 +00:00
/// <summary>
2024-02-23 23:53:49 +00:00
/// Binds samplers to be used by the vertex shader.
2022-03-04 22:14:22 +00:00
/// </summary>
2024-02-23 23:53:49 +00:00
/// <param name="textureSamplerBindings">The texture-sampler pairs to bind.</param>
public unsafe void BindVertexSamplers (
in Span < TextureSamplerBinding > textureSamplerBindings
) {
2022-09-07 20:07:17 +00:00
#if DEBUG
2024-01-18 20:27:34 +00:00
AssertNotSubmitted ( ) ;
2024-02-23 23:53:49 +00:00
AssertGraphicsPipelineBound ( ) ;
AssertVertexSamplerCount ( textureSamplerBindings . Length ) ;
2022-09-07 20:07:17 +00:00
# endif
2024-03-01 23:03:14 +00:00
Refresh . TextureSamplerBinding * bindingsArray = ( Refresh . TextureSamplerBinding * ) NativeMemory . Alloc ( ( nuint ) ( Marshal . SizeOf < Refresh . TextureSamplerBinding > ( ) * textureSamplerBindings . Length ) ) ;
2022-03-04 21:21:52 +00:00
2024-02-23 23:53:49 +00:00
for ( var i = 0 ; i < textureSamplerBindings . Length ; i + = 1 )
{
2022-09-07 20:07:17 +00:00
#if DEBUG
2024-02-23 23:53:49 +00:00
AssertTextureSamplerBindingNonNull ( textureSamplerBindings [ i ] ) ;
AssertTextureBindingUsageFlags ( textureSamplerBindings [ i ] . Texture ) ;
# endif
2022-12-14 00:09:32 +00:00
2024-03-01 23:03:14 +00:00
bindingsArray [ i ] = textureSamplerBindings [ i ] . ToRefresh ( ) ;
2022-12-14 00:09:32 +00:00
}
2022-09-07 20:07:17 +00:00
2024-02-23 23:53:49 +00:00
Refresh . Refresh_BindVertexSamplers (
2022-11-17 20:35:21 +00:00
Device . Handle ,
Handle ,
2024-03-01 23:03:14 +00:00
bindingsArray
2022-11-17 20:35:21 +00:00
) ;
2024-03-01 23:03:14 +00:00
NativeMemory . Free ( bindingsArray ) ;
2022-11-17 20:35:21 +00:00
}
/// <summary>
2024-02-23 23:53:49 +00:00
/// Binds samplers to be used by the fragment shader.
2022-11-17 20:35:21 +00:00
/// </summary>
2024-02-23 23:53:49 +00:00
/// <param name="textureSamplerBinding">The texture-sampler to bind.</param>
public unsafe void BindFragmentSamplers (
in TextureSamplerBinding textureSamplerBinding
2022-11-17 20:35:21 +00:00
) {
2022-12-29 03:18:36 +00:00
#if DEBUG
2024-01-18 20:27:34 +00:00
AssertNotSubmitted ( ) ;
2022-12-29 03:18:36 +00:00
AssertGraphicsPipelineBound ( ) ;
2024-02-23 23:53:49 +00:00
AssertFragmentSamplerCount ( 1 ) ;
AssertTextureSamplerBindingNonNull ( textureSamplerBinding ) ;
AssertTextureBindingUsageFlags ( textureSamplerBinding . Texture ) ;
2022-12-29 03:18:36 +00:00
# endif
2024-03-01 23:03:14 +00:00
var bindingArray = stackalloc Refresh . TextureSamplerBinding [ 1 ] ;
bindingArray [ 0 ] = textureSamplerBinding . ToRefresh ( ) ;
2022-11-17 20:35:21 +00:00
2024-02-23 23:53:49 +00:00
Refresh . Refresh_BindFragmentSamplers (
2022-11-17 20:35:21 +00:00
Device . Handle ,
Handle ,
2024-03-01 23:03:14 +00:00
bindingArray
2022-11-17 20:35:21 +00:00
) ;
}
/// <summary>
2024-02-23 23:53:49 +00:00
/// Binds samplers to be used by the fragment shader.
2022-11-17 20:35:21 +00:00
/// </summary>
2024-02-23 23:53:49 +00:00
/// <param name="textureSamplerBindingOne">The first texture-sampler to bind.</param>
/// <param name="textureSamplerBindingTwo">The second texture-sampler to bind.</param>
public unsafe void BindFragmentSamplers (
in TextureSamplerBinding textureSamplerBindingOne ,
in TextureSamplerBinding textureSamplerBindingTwo
2022-11-17 20:35:21 +00:00
) {
2022-12-29 03:18:36 +00:00
#if DEBUG
2024-01-18 20:27:34 +00:00
AssertNotSubmitted ( ) ;
2022-12-29 03:18:36 +00:00
AssertGraphicsPipelineBound ( ) ;
2024-02-23 23:53:49 +00:00
AssertFragmentSamplerCount ( 2 ) ;
AssertTextureSamplerBindingNonNull ( textureSamplerBindingOne ) ;
AssertTextureSamplerBindingNonNull ( textureSamplerBindingTwo ) ;
AssertTextureBindingUsageFlags ( textureSamplerBindingOne . Texture ) ;
AssertTextureBindingUsageFlags ( textureSamplerBindingTwo . Texture ) ;
2022-12-29 03:18:36 +00:00
# endif
2024-03-01 23:03:14 +00:00
var bindingArray = stackalloc Refresh . TextureSamplerBinding [ 2 ] ;
bindingArray [ 0 ] = textureSamplerBindingOne . ToRefresh ( ) ;
bindingArray [ 1 ] = textureSamplerBindingTwo . ToRefresh ( ) ;
2022-11-17 20:35:21 +00:00
2024-02-23 23:53:49 +00:00
Refresh . Refresh_BindFragmentSamplers (
2022-11-17 20:35:21 +00:00
Device . Handle ,
Handle ,
2024-03-01 23:03:14 +00:00
bindingArray
2022-11-17 20:35:21 +00:00
) ;
}
/// <summary>
2024-02-23 23:53:49 +00:00
/// Binds samplers to be used by the fragment shader.
2022-11-17 20:35:21 +00:00
/// </summary>
2024-02-23 23:53:49 +00:00
/// <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 BindFragmentSamplers (
in TextureSamplerBinding textureSamplerBindingOne ,
in TextureSamplerBinding textureSamplerBindingTwo ,
in TextureSamplerBinding textureSamplerBindingThree
2022-11-17 20:35:21 +00:00
) {
2022-12-29 03:18:36 +00:00
#if DEBUG
2024-01-18 20:27:34 +00:00
AssertNotSubmitted ( ) ;
2022-12-29 03:18:36 +00:00
AssertGraphicsPipelineBound ( ) ;
2024-02-23 23:53:49 +00:00
AssertFragmentSamplerCount ( 3 ) ;
AssertTextureSamplerBindingNonNull ( textureSamplerBindingOne ) ;
AssertTextureSamplerBindingNonNull ( textureSamplerBindingTwo ) ;
AssertTextureSamplerBindingNonNull ( textureSamplerBindingThree ) ;
AssertTextureBindingUsageFlags ( textureSamplerBindingOne . Texture ) ;
AssertTextureBindingUsageFlags ( textureSamplerBindingTwo . Texture ) ;
AssertTextureBindingUsageFlags ( textureSamplerBindingThree . Texture ) ;
2022-12-29 03:18:36 +00:00
# endif
2024-03-01 23:03:14 +00:00
var bindingArray = stackalloc Refresh . TextureSamplerBinding [ 3 ] ;
bindingArray [ 0 ] = textureSamplerBindingOne . ToRefresh ( ) ;
bindingArray [ 1 ] = textureSamplerBindingTwo . ToRefresh ( ) ;
bindingArray [ 2 ] = textureSamplerBindingThree . ToRefresh ( ) ;
2022-11-17 20:35:21 +00:00
2024-02-23 23:53:49 +00:00
Refresh . Refresh_BindFragmentSamplers (
2022-03-04 21:21:52 +00:00
Device . Handle ,
Handle ,
2024-03-01 23:03:14 +00:00
bindingArray
2022-03-04 21:21:52 +00:00
) ;
}
2022-02-23 05:14:32 +00:00
/// <summary>
2024-02-23 23:53:49 +00:00
/// Binds samplers to be used by the fragment shader.
2022-02-23 05:14:32 +00:00
/// </summary>
2024-02-23 23:53:49 +00:00
/// <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="textureSamplerBindingFour">The fourth texture-sampler to bind.</param>
public unsafe void BindFragmentSamplers (
in TextureSamplerBinding textureSamplerBindingOne ,
in TextureSamplerBinding textureSamplerBindingTwo ,
in TextureSamplerBinding textureSamplerBindingThree ,
in TextureSamplerBinding textureSamplerBindingFour
2022-11-17 20:35:21 +00:00
) {
2022-12-29 03:18:36 +00:00
#if DEBUG
2024-01-18 20:27:34 +00:00
AssertNotSubmitted ( ) ;
2022-12-29 03:18:36 +00:00
AssertGraphicsPipelineBound ( ) ;
2024-02-23 23:53:49 +00:00
AssertFragmentSamplerCount ( 4 ) ;
AssertTextureSamplerBindingNonNull ( textureSamplerBindingOne ) ;
AssertTextureSamplerBindingNonNull ( textureSamplerBindingTwo ) ;
AssertTextureSamplerBindingNonNull ( textureSamplerBindingThree ) ;
AssertTextureSamplerBindingNonNull ( textureSamplerBindingFour ) ;
AssertTextureBindingUsageFlags ( textureSamplerBindingOne . Texture ) ;
AssertTextureBindingUsageFlags ( textureSamplerBindingTwo . Texture ) ;
AssertTextureBindingUsageFlags ( textureSamplerBindingThree . Texture ) ;
AssertTextureBindingUsageFlags ( textureSamplerBindingFour . Texture ) ;
# endif
2022-11-17 20:35:21 +00:00
2024-03-01 23:03:14 +00:00
var bindingArray = stackalloc Refresh . TextureSamplerBinding [ 4 ] ;
bindingArray [ 0 ] = textureSamplerBindingOne . ToRefresh ( ) ;
bindingArray [ 1 ] = textureSamplerBindingTwo . ToRefresh ( ) ;
bindingArray [ 2 ] = textureSamplerBindingThree . ToRefresh ( ) ;
bindingArray [ 3 ] = textureSamplerBindingFour . ToRefresh ( ) ;
2024-02-23 23:53:49 +00:00
Refresh . Refresh_BindFragmentSamplers (
2022-02-23 05:14:32 +00:00
Device . Handle ,
Handle ,
2024-03-01 23:03:14 +00:00
bindingArray
2022-02-23 05:14:32 +00:00
) ;
}
/// <summary>
2024-02-23 23:53:49 +00:00
/// Binds samplers to be used by the fragment shader.
2022-02-23 05:14:32 +00:00
/// </summary>
2024-02-23 23:53:49 +00:00
/// <param name="textureSamplerBindings">The texture-sampler pairs to bind.</param>
public unsafe void BindFragmentSamplers (
in Span < TextureSamplerBinding > textureSamplerBindings
2022-11-17 20:35:21 +00:00
) {
2022-12-29 03:18:36 +00:00
#if DEBUG
2024-01-18 20:27:34 +00:00
AssertNotSubmitted ( ) ;
2022-12-29 03:18:36 +00:00
AssertGraphicsPipelineBound ( ) ;
2024-02-23 23:53:49 +00:00
AssertFragmentSamplerCount ( textureSamplerBindings . Length ) ;
2022-12-29 03:18:36 +00:00
# endif
2024-03-01 23:03:14 +00:00
Refresh . TextureSamplerBinding * bindingArray = ( Refresh . TextureSamplerBinding * ) NativeMemory . Alloc ( ( nuint ) ( Marshal . SizeOf < Refresh . TextureSamplerBinding > ( ) * textureSamplerBindings . Length ) ) ;
2022-02-23 05:14:32 +00:00
2024-02-23 23:53:49 +00:00
for ( var i = 0 ; i < textureSamplerBindings . Length ; i + = 1 )
2022-02-23 05:14:32 +00:00
{
2024-02-23 23:53:49 +00:00
#if DEBUG
AssertTextureSamplerBindingNonNull ( textureSamplerBindings [ i ] ) ;
AssertTextureBindingUsageFlags ( textureSamplerBindings [ i ] . Texture ) ;
# endif
2024-03-01 23:03:14 +00:00
bindingArray [ i ] = textureSamplerBindings [ i ] . ToRefresh ( ) ;
2022-02-23 05:14:32 +00:00
}
2024-02-23 23:53:49 +00:00
Refresh . Refresh_BindFragmentSamplers (
2022-02-23 05:14:32 +00:00
Device . Handle ,
Handle ,
2024-03-01 23:03:14 +00:00
bindingArray
2022-02-23 05:14:32 +00:00
) ;
2024-03-01 23:03:14 +00:00
NativeMemory . Free ( bindingArray ) ;
2022-02-23 05:14:32 +00:00
}
/// <summary>
2024-02-23 23:53:49 +00:00
/// Pushes vertex shader uniforms to the device.
2022-02-23 05:14:32 +00:00
/// </summary>
2024-02-23 23:53:49 +00:00
/// <returns>A starting offset value to be used with draw calls.</returns>
public unsafe void PushVertexShaderUniforms (
void * uniformsPtr ,
uint size
) {
2024-01-18 20:27:34 +00:00
#if DEBUG
AssertNotSubmitted ( ) ;
2024-02-23 23:53:49 +00:00
AssertGraphicsPipelineBound ( ) ;
if ( currentGraphicsPipeline . VertexShaderInfo . UniformBufferSize = = 0 )
{
throw new InvalidOperationException ( "The current vertex shader does not take a uniform buffer!" ) ;
}
if ( currentGraphicsPipeline . VertexShaderInfo . UniformBufferSize ! = size )
{
throw new InvalidOperationException ( "Vertex uniform data size mismatch!" ) ;
}
2024-01-18 20:27:34 +00:00
# endif
2024-02-23 23:53:49 +00:00
Refresh . Refresh_PushVertexShaderUniforms (
2022-02-23 05:14:32 +00:00
Device . Handle ,
Handle ,
2024-02-23 23:53:49 +00:00
( IntPtr ) uniformsPtr ,
size
2022-02-23 05:14:32 +00:00
) ;
}
/// <summary>
2024-02-23 23:53:49 +00:00
/// Pushes vertex shader uniforms to the device.
2022-02-23 05:14:32 +00:00
/// </summary>
2024-02-23 23:53:49 +00:00
/// <returns>A starting offset value to be used with draw calls.</returns>
public unsafe void PushVertexShaderUniforms < T > (
in T uniforms
) where T : unmanaged
{
fixed ( T * uniformsPtr = & uniforms )
{
PushVertexShaderUniforms ( uniformsPtr , ( uint ) Marshal . SizeOf < T > ( ) ) ;
}
}
/// <summary>
/// Pushes fragment shader uniforms to the device.
/// </summary>
/// <returns>A starting offset to be used with draw calls.</returns>
public unsafe void PushFragmentShaderUniforms (
void * uniformsPtr ,
uint size
2022-11-17 20:35:21 +00:00
) {
2022-09-07 20:07:17 +00:00
#if DEBUG
2024-01-18 20:27:34 +00:00
AssertNotSubmitted ( ) ;
2022-09-07 20:07:17 +00:00
AssertGraphicsPipelineBound ( ) ;
2024-02-23 23:53:49 +00:00
if ( currentGraphicsPipeline . FragmentShaderInfo . UniformBufferSize = = 0 )
{
throw new InvalidOperationException ( "The current fragment shader does not take a uniform buffer!" ) ;
}
2022-09-07 20:07:17 +00:00
2024-02-23 23:53:49 +00:00
if ( currentGraphicsPipeline . FragmentShaderInfo . UniformBufferSize ! = size )
{
throw new InvalidOperationException ( "Fragment uniform data size mismatch!" ) ;
}
# endif
2022-09-07 20:07:17 +00:00
2024-02-23 23:53:49 +00:00
Refresh . Refresh_PushFragmentShaderUniforms (
2022-11-17 20:35:21 +00:00
Device . Handle ,
Handle ,
2024-02-23 23:53:49 +00:00
( IntPtr ) uniformsPtr ,
size
2022-11-17 20:35:21 +00:00
) ;
}
2022-02-23 05:14:32 +00:00
2022-11-17 20:35:21 +00:00
/// <summary>
2024-02-23 23:53:49 +00:00
/// Pushes fragment shader uniforms to the device.
2022-11-17 20:35:21 +00:00
/// </summary>
2024-02-23 23:53:49 +00:00
/// <returns>A starting offset to be used with draw calls.</returns>
public unsafe void PushFragmentShaderUniforms < T > (
in T uniforms
) where T : unmanaged
{
fixed ( T * uniformsPtr = & uniforms )
{
PushFragmentShaderUniforms ( uniformsPtr , ( uint ) Marshal . SizeOf < T > ( ) ) ;
}
}
/// <summary>
/// Draws using instanced rendering.
/// </summary>
/// <param name="baseVertex">The starting index offset for the vertex buffer.</param>
/// <param name="startIndex">The starting index offset for the index buffer.</param>
/// <param name="primitiveCount">The number of primitives to draw.</param>
/// <param name="instanceCount">The number of instances to draw.</param>
public void DrawInstancedPrimitives (
uint baseVertex ,
uint startIndex ,
uint primitiveCount ,
uint instanceCount
)
{
2022-11-08 19:29:05 +00:00
#if DEBUG
2024-01-18 20:27:34 +00:00
AssertNotSubmitted ( ) ;
2022-11-17 20:35:21 +00:00
AssertGraphicsPipelineBound ( ) ;
2022-11-08 19:29:05 +00:00
# endif
2024-02-23 23:53:49 +00:00
Refresh . Refresh_DrawInstancedPrimitives (
Device . Handle ,
Handle ,
baseVertex ,
startIndex ,
primitiveCount ,
instanceCount
) ;
}
2022-11-17 20:35:21 +00:00
2024-02-23 23:53:49 +00:00
/// <summary>
/// Draws using a vertex buffer and an index buffer.
/// </summary>
/// <param name="baseVertex">The starting index offset for the vertex buffer.</param>
/// <param name="startIndex">The starting index offset for the index buffer.</param>
/// <param name="primitiveCount">The number of primitives to draw.</param>
public void DrawIndexedPrimitives (
uint baseVertex ,
uint startIndex ,
uint primitiveCount
)
{
#if DEBUG
AssertNotSubmitted ( ) ;
AssertGraphicsPipelineBound ( ) ;
# endif
2022-02-23 05:14:32 +00:00
2024-02-23 23:53:49 +00:00
Refresh . Refresh_DrawIndexedPrimitives (
2022-02-23 05:14:32 +00:00
Device . Handle ,
Handle ,
2024-02-23 23:53:49 +00:00
baseVertex ,
startIndex ,
primitiveCount
2022-02-23 05:14:32 +00:00
) ;
}
/// <summary>
2024-02-23 23:53:49 +00:00
/// Draws using a vertex buffer.
2022-02-23 05:14:32 +00:00
/// </summary>
2024-02-23 23:53:49 +00:00
/// <param name="vertexStart"></param>
/// <param name="primitiveCount"></param>
public void DrawPrimitives (
uint vertexStart ,
uint primitiveCount
)
{
2022-11-17 20:35:21 +00:00
#if DEBUG
2024-01-18 20:27:34 +00:00
AssertNotSubmitted ( ) ;
2022-11-17 20:35:21 +00:00
AssertGraphicsPipelineBound ( ) ;
# endif
2024-02-23 23:53:49 +00:00
Refresh . Refresh_DrawPrimitives (
Device . Handle ,
Handle ,
vertexStart ,
primitiveCount
) ;
}
2022-11-17 20:35:21 +00:00
2024-02-23 23:53:49 +00:00
/// <summary>
/// Similar to DrawPrimitives, but parameters are set from a buffer.
/// </summary>
/// <param name="buffer">The draw parameters buffer.</param>
/// <param name="offsetInBytes">The offset to start reading from the draw parameters buffer.</param>
/// <param name="drawCount">The number of draw parameter sets that should be read from the buffer.</param>
/// <param name="stride">The byte stride between sets of draw parameters.</param>
/// <param name="vertexParamOffset">An offset value obtained from PushVertexShaderUniforms. If no uniforms are required then use 0.</param>
/// <param name="fragmentParamOffset">An offset value obtained from PushFragmentShaderUniforms. If no uniforms are required the use 0.</param>
public void DrawPrimitivesIndirect (
GpuBuffer buffer ,
uint offsetInBytes ,
uint drawCount ,
uint stride
)
{
#if DEBUG
AssertNotSubmitted ( ) ;
AssertGraphicsPipelineBound ( ) ;
# endif
2022-11-17 20:35:21 +00:00
2024-02-23 23:53:49 +00:00
Refresh . Refresh_DrawPrimitivesIndirect (
2022-11-17 20:35:21 +00:00
Device . Handle ,
Handle ,
2024-02-23 23:53:49 +00:00
buffer . Handle ,
offsetInBytes ,
drawCount ,
stride
2022-11-17 20:35:21 +00:00
) ;
2022-11-16 01:53:30 +00:00
}
/// <summary>
2024-02-23 23:53:49 +00:00
/// Ends the current render pass.
/// This must be called before beginning another render pass or submitting the command buffer.
2022-11-16 01:53:30 +00:00
/// </summary>
2024-02-23 23:53:49 +00:00
public void EndRenderPass ( )
{
2022-09-07 20:07:17 +00:00
#if DEBUG
2024-01-18 20:27:34 +00:00
AssertNotSubmitted ( ) ;
2022-11-17 20:35:21 +00:00
# endif
2022-09-07 20:07:17 +00:00
2024-02-23 23:53:49 +00:00
Refresh . Refresh_EndRenderPass (
Device . Handle ,
Handle
) ;
2022-09-07 20:07:17 +00:00
2024-02-23 23:53:49 +00:00
#if DEBUG
currentGraphicsPipeline = null ;
renderPassActive = false ;
# endif
}
2022-11-17 20:35:21 +00:00
2024-02-23 23:53:49 +00:00
/// <summary>
/// Blits a texture to another texture with the specified filter.
///
/// This operation cannot be performed inside any pass.
/// </summary>
2024-03-01 23:03:14 +00:00
/// <param name="writeOption">Specifies data dependency behavior.</param>
2024-02-23 23:53:49 +00:00
public void Blit (
2024-03-01 23:03:14 +00:00
TextureSlice source ,
TextureSlice destination ,
Filter filter ,
WriteOptions writeOption
2024-02-23 23:53:49 +00:00
) {
var sampler = filter = = Filter . Linear ? Device . LinearSampler : Device . PointSampler ;
2022-11-17 20:35:21 +00:00
2024-03-01 23:03:14 +00:00
// FIXME: this will break with non-2D textures
// FIXME: this should take a TextureRegion
BeginRenderPass ( new ColorAttachmentInfo ( destination , writeOption ) ) ;
2024-02-23 23:53:49 +00:00
BindGraphicsPipeline ( Device . BlitPipeline ) ;
2024-03-01 23:03:14 +00:00
BindFragmentSamplers ( new TextureSamplerBinding ( source . Texture , sampler ) ) ;
2024-02-23 23:53:49 +00:00
DrawPrimitives ( 0 , 2 ) ;
EndRenderPass ( ) ;
}
public void BeginComputePass ( )
{
#if DEBUG
AssertNotSubmitted ( ) ;
AssertNotInPass ( "Cannot begin compute pass while in another pass!" ) ;
computePassActive = true ;
# endif
Refresh . Refresh_BeginComputePass (
2022-11-17 20:35:21 +00:00
Device . Handle ,
2024-02-23 23:53:49 +00:00
Handle
2022-11-17 20:35:21 +00:00
) ;
}
/// <summary>
2024-02-23 23:53:49 +00:00
/// Binds a compute pipeline so that compute work may be dispatched.
2022-11-17 20:35:21 +00:00
/// </summary>
2024-02-23 23:53:49 +00:00
/// <param name="computePipeline">The compute pipeline to bind.</param>
public void BindComputePipeline (
ComputePipeline computePipeline
2022-11-17 20:35:21 +00:00
) {
#if DEBUG
2024-01-18 20:27:34 +00:00
AssertNotSubmitted ( ) ;
2024-02-23 23:53:49 +00:00
AssertInComputePass ( "Cannot bind compute pipeline outside of compute pass!" ) ;
2022-09-07 20:07:17 +00:00
# endif
2024-02-23 23:53:49 +00:00
Refresh . Refresh_BindComputePipeline (
Device . Handle ,
Handle ,
computePipeline . Handle
) ;
2022-02-23 05:14:32 +00:00
2022-11-08 19:29:05 +00:00
#if DEBUG
2024-02-23 23:53:49 +00:00
currentComputePipeline = computePipeline ;
2022-11-08 19:29:05 +00:00
# endif
2024-02-23 23:53:49 +00:00
}
2022-03-17 21:42:43 +00:00
2024-02-23 23:53:49 +00:00
/// <summary>
/// Binds a buffer to be used in the compute shader.
/// </summary>
public unsafe void BindComputeBuffers (
2024-03-01 23:03:14 +00:00
ComputeBufferBinding binding
2024-02-23 23:53:49 +00:00
) {
#if DEBUG
AssertNotSubmitted ( ) ;
AssertInComputePass ( "Cannot bind compute buffers outside of compute pass!" ) ;
AssertComputePipelineBound ( ) ;
AssertComputeBufferCount ( 1 ) ;
# endif
2022-02-23 05:14:32 +00:00
2024-03-01 23:03:14 +00:00
var bindingArray = stackalloc Refresh . ComputeBufferBinding [ 1 ] ;
bindingArray [ 0 ] = binding . ToRefresh ( ) ;
2024-02-23 23:53:49 +00:00
Refresh . Refresh_BindComputeBuffers (
2022-11-17 20:35:21 +00:00
Device . Handle ,
Handle ,
2024-03-01 23:03:14 +00:00
bindingArray
2022-11-17 20:35:21 +00:00
) ;
}
/// <summary>
2024-02-23 23:53:49 +00:00
/// Binds buffers to be used in the compute shader.
2022-11-17 20:35:21 +00:00
/// </summary>
2024-02-23 23:53:49 +00:00
public unsafe void BindComputeBuffers (
2024-03-01 23:03:14 +00:00
ComputeBufferBinding bindingOne ,
ComputeBufferBinding bindingTwo
2022-11-17 20:35:21 +00:00
) {
#if DEBUG
2024-01-18 20:27:34 +00:00
AssertNotSubmitted ( ) ;
2024-02-23 23:53:49 +00:00
AssertInComputePass ( "Cannot bind compute buffers outside of compute pass!" ) ;
AssertComputePipelineBound ( ) ;
AssertComputeBufferCount ( 2 ) ;
2022-11-17 20:35:21 +00:00
# endif
2024-03-01 23:03:14 +00:00
var bindingArray = stackalloc Refresh . ComputeBufferBinding [ 2 ] ;
bindingArray [ 0 ] = bindingOne . ToRefresh ( ) ;
bindingArray [ 1 ] = bindingTwo . ToRefresh ( ) ;
2022-11-17 20:35:21 +00:00
2024-02-23 23:53:49 +00:00
Refresh . Refresh_BindComputeBuffers (
Device . Handle ,
Handle ,
2024-03-01 23:03:14 +00:00
bindingArray
2024-02-23 23:53:49 +00:00
) ;
}
/// <summary>
/// Binds buffers to be used in the compute shader.
/// </summary>
public unsafe void BindComputeBuffers (
2024-03-01 23:03:14 +00:00
ComputeBufferBinding bindingOne ,
ComputeBufferBinding bindingTwo ,
ComputeBufferBinding bindingThree
2024-02-23 23:53:49 +00:00
) {
#if DEBUG
AssertNotSubmitted ( ) ;
AssertInComputePass ( "Cannot bind compute buffers outside of compute pass!" ) ;
AssertComputePipelineBound ( ) ;
AssertComputeBufferCount ( 3 ) ;
# endif
2024-03-01 23:03:14 +00:00
var bindingArray = stackalloc Refresh . ComputeBufferBinding [ 3 ] ;
bindingArray [ 0 ] = bindingOne . ToRefresh ( ) ;
bindingArray [ 1 ] = bindingTwo . ToRefresh ( ) ;
bindingArray [ 2 ] = bindingThree . ToRefresh ( ) ;
2022-11-17 20:35:21 +00:00
2024-02-23 23:53:49 +00:00
Refresh . Refresh_BindComputeBuffers (
2022-02-23 05:14:32 +00:00
Device . Handle ,
Handle ,
2024-03-01 23:03:14 +00:00
bindingArray
2022-02-23 05:14:32 +00:00
) ;
}
2022-11-16 01:53:30 +00:00
/// <summary>
2024-02-23 23:53:49 +00:00
/// Binds buffers to be used in the compute shader.
2022-11-16 01:53:30 +00:00
/// </summary>
2024-02-23 23:53:49 +00:00
public unsafe void BindComputeBuffers (
2024-03-01 23:03:14 +00:00
ComputeBufferBinding bindingOne ,
ComputeBufferBinding bindingTwo ,
ComputeBufferBinding bindingThree ,
ComputeBufferBinding bindingFour
2022-11-17 20:35:21 +00:00
) {
#if DEBUG
2024-01-18 20:27:34 +00:00
AssertNotSubmitted ( ) ;
2024-02-23 23:53:49 +00:00
AssertInComputePass ( "Cannot bind compute buffers outside of compute pass!" ) ;
AssertComputePipelineBound ( ) ;
AssertComputeBufferCount ( 4 ) ;
2022-11-17 20:35:21 +00:00
# endif
2024-03-01 23:03:14 +00:00
var bindingArray = stackalloc Refresh . ComputeBufferBinding [ 4 ] ;
bindingArray [ 0 ] = bindingOne . ToRefresh ( ) ;
bindingArray [ 1 ] = bindingTwo . ToRefresh ( ) ;
bindingArray [ 2 ] = bindingThree . ToRefresh ( ) ;
bindingArray [ 3 ] = bindingFour . ToRefresh ( ) ;
2022-11-17 20:35:21 +00:00
2024-02-23 23:53:49 +00:00
Refresh . Refresh_BindComputeBuffers (
2022-11-17 20:35:21 +00:00
Device . Handle ,
Handle ,
2024-03-01 23:03:14 +00:00
bindingArray
2022-11-17 20:35:21 +00:00
) ;
}
/// <summary>
2024-02-23 23:53:49 +00:00
/// Binds buffers to be used in the compute shader.
2022-11-17 20:35:21 +00:00
/// </summary>
2024-02-23 23:53:49 +00:00
/// <param name="buffers">A Span of buffers to bind.</param>
public unsafe void BindComputeBuffers (
2024-03-01 23:03:14 +00:00
in Span < ComputeBufferBinding > bindings
2022-11-17 20:35:21 +00:00
) {
#if DEBUG
2024-01-18 20:27:34 +00:00
AssertNotSubmitted ( ) ;
2024-02-23 23:53:49 +00:00
AssertInComputePass ( "Cannot bind compute buffers outside of compute pass!" ) ;
AssertComputePipelineBound ( ) ;
2024-03-01 23:03:14 +00:00
AssertComputeBufferCount ( bindings . Length ) ;
2022-11-17 20:35:21 +00:00
# endif
2024-03-01 23:03:14 +00:00
Refresh . ComputeBufferBinding * bindingArray = ( Refresh . ComputeBufferBinding * ) NativeMemory . Alloc (
( nuint ) ( Marshal . SizeOf < ComputeBufferBinding > ( ) * bindings . Length )
) ;
2022-11-17 20:35:21 +00:00
2024-03-01 23:03:14 +00:00
for ( var i = 0 ; i < bindings . Length ; i + = 1 )
2024-02-23 23:53:49 +00:00
{
2024-03-01 23:03:14 +00:00
bindingArray [ i ] = bindings [ i ] . ToRefresh ( ) ;
2024-02-23 23:53:49 +00:00
}
2022-11-17 20:35:21 +00:00
2024-02-23 23:53:49 +00:00
Refresh . Refresh_BindComputeBuffers (
2022-11-17 20:35:21 +00:00
Device . Handle ,
Handle ,
2024-03-01 23:03:14 +00:00
bindingArray
2022-11-17 20:35:21 +00:00
) ;
2024-03-01 23:03:14 +00:00
NativeMemory . Free ( bindingArray ) ;
2022-11-17 20:35:21 +00:00
}
/// <summary>
2024-03-01 23:03:14 +00:00
/// Binds a texture slice to be used in the compute shader.
2022-11-17 20:35:21 +00:00
/// </summary>
2024-02-23 23:53:49 +00:00
public unsafe void BindComputeTextures (
2024-03-01 23:03:14 +00:00
ComputeTextureBinding binding
2022-11-17 20:35:21 +00:00
) {
#if DEBUG
2024-01-18 20:27:34 +00:00
AssertNotSubmitted ( ) ;
2024-02-23 23:53:49 +00:00
AssertInComputePass ( "Cannot bind compute textures outside of compute pass!" ) ;
AssertComputePipelineBound ( ) ;
AssertComputeTextureCount ( 1 ) ;
2022-11-17 20:35:21 +00:00
# endif
2024-03-01 23:03:14 +00:00
var bindingArray = stackalloc Refresh . ComputeTextureBinding [ 1 ] ;
bindingArray [ 0 ] = binding . ToRefresh ( ) ;
2022-11-17 20:35:21 +00:00
2024-02-23 23:53:49 +00:00
Refresh . Refresh_BindComputeTextures (
2022-11-17 20:35:21 +00:00
Device . Handle ,
Handle ,
2024-03-01 23:03:14 +00:00
bindingArray
2022-11-17 20:35:21 +00:00
) ;
}
/// <summary>
2024-02-23 23:53:49 +00:00
/// Binds textures to be used in the compute shader.
2022-11-17 20:35:21 +00:00
/// </summary>
2024-02-23 23:53:49 +00:00
public unsafe void BindComputeTextures (
2024-03-01 23:03:14 +00:00
ComputeTextureBinding bindingOne ,
ComputeTextureBinding bindingTwo
2022-11-17 20:35:21 +00:00
) {
#if DEBUG
2024-01-18 20:27:34 +00:00
AssertNotSubmitted ( ) ;
2024-02-23 23:53:49 +00:00
AssertInComputePass ( "Cannot bind compute textures outside of compute pass!" ) ;
AssertComputePipelineBound ( ) ;
AssertComputeTextureCount ( 2 ) ;
2022-11-17 20:35:21 +00:00
# endif
2024-03-01 23:03:14 +00:00
var bindingArray = stackalloc Refresh . ComputeTextureBinding [ 2 ] ;
bindingArray [ 0 ] = bindingOne . ToRefresh ( ) ;
bindingArray [ 1 ] = bindingTwo . ToRefresh ( ) ;
2022-11-17 20:35:21 +00:00
2024-02-23 23:53:49 +00:00
Refresh . Refresh_BindComputeTextures (
2022-11-17 20:35:21 +00:00
Device . Handle ,
Handle ,
2024-03-01 23:03:14 +00:00
bindingArray
2022-11-17 20:35:21 +00:00
) ;
2022-11-16 01:53:30 +00:00
}
2022-02-23 05:14:32 +00:00
/// <summary>
2024-02-23 23:53:49 +00:00
/// Binds textures to be used in the compute shader.
2022-02-23 05:14:32 +00:00
/// </summary>
2024-02-23 23:53:49 +00:00
public unsafe void BindComputeTextures (
2024-03-01 23:03:14 +00:00
ComputeTextureBinding bindingOne ,
ComputeTextureBinding bindingTwo ,
ComputeTextureBinding bindingThree
2023-02-24 00:59:34 +00:00
) {
2022-09-07 20:07:17 +00:00
#if DEBUG
2024-01-18 20:27:34 +00:00
AssertNotSubmitted ( ) ;
2024-02-23 23:53:49 +00:00
AssertInComputePass ( "Cannot bind compute textures outside of compute pass!" ) ;
AssertComputePipelineBound ( ) ;
AssertComputeTextureCount ( 3 ) ;
# endif
2022-09-07 20:07:17 +00:00
2024-03-01 23:03:14 +00:00
var bindingArray = stackalloc Refresh . ComputeTextureBinding [ 3 ] ;
bindingArray [ 0 ] = bindingOne . ToRefresh ( ) ;
bindingArray [ 1 ] = bindingTwo . ToRefresh ( ) ;
bindingArray [ 2 ] = bindingThree . ToRefresh ( ) ;
2022-11-08 19:29:05 +00:00
2024-02-23 23:53:49 +00:00
Refresh . Refresh_BindComputeTextures (
2023-02-24 00:59:34 +00:00
Device . Handle ,
Handle ,
2024-03-01 23:03:14 +00:00
bindingArray
2023-02-24 00:59:34 +00:00
) ;
}
/// <summary>
2024-02-23 23:53:49 +00:00
/// Binds textures to be used in the compute shader.
2023-02-24 00:59:34 +00:00
/// </summary>
2024-02-23 23:53:49 +00:00
public unsafe void BindComputeTextures (
2024-03-01 23:03:14 +00:00
ComputeTextureBinding bindingOne ,
ComputeTextureBinding bindingTwo ,
ComputeTextureBinding bindingThree ,
ComputeTextureBinding bindingFour
2024-02-23 23:53:49 +00:00
) {
#if DEBUG
AssertNotSubmitted ( ) ;
AssertInComputePass ( "Cannot bind compute textures outside of compute pass!" ) ;
AssertComputePipelineBound ( ) ;
AssertComputeTextureCount ( 4 ) ;
# endif
2024-03-01 23:03:14 +00:00
var textureSlicePtrs = stackalloc Refresh . ComputeTextureBinding [ 4 ] ;
textureSlicePtrs [ 0 ] = bindingOne . ToRefresh ( ) ;
textureSlicePtrs [ 1 ] = bindingTwo . ToRefresh ( ) ;
textureSlicePtrs [ 2 ] = bindingThree . ToRefresh ( ) ;
textureSlicePtrs [ 3 ] = bindingFour . ToRefresh ( ) ;
2024-02-23 23:53:49 +00:00
Refresh . Refresh_BindComputeTextures (
Device . Handle ,
Handle ,
2024-03-01 23:03:14 +00:00
textureSlicePtrs
2024-02-23 23:53:49 +00:00
) ;
2022-02-23 05:14:32 +00:00
}
/// <summary>
2024-02-23 23:53:49 +00:00
/// Binds textures to be used in the compute shader.
2022-02-23 05:14:32 +00:00
/// </summary>
2024-02-23 23:53:49 +00:00
public unsafe void BindComputeTextures (
2024-03-01 23:03:14 +00:00
in Span < ComputeTextureBinding > bindings
2023-02-24 00:59:34 +00:00
) {
2022-09-07 20:07:17 +00:00
#if DEBUG
2024-01-18 20:27:34 +00:00
AssertNotSubmitted ( ) ;
2024-02-23 23:53:49 +00:00
AssertInComputePass ( "Cannot bind compute textures outside of compute pass!" ) ;
AssertComputePipelineBound ( ) ;
2024-03-01 23:03:14 +00:00
AssertComputeTextureCount ( bindings . Length ) ;
2024-02-23 23:53:49 +00:00
# endif
2022-09-07 20:07:17 +00:00
2024-03-01 23:03:14 +00:00
Refresh . ComputeTextureBinding * bindingArray = ( Refresh . ComputeTextureBinding * ) NativeMemory . Alloc (
( nuint ) ( Marshal . SizeOf < Refresh . TextureSlice > ( ) * bindings . Length )
2024-03-01 07:53:11 +00:00
) ;
2024-02-23 08:06:04 +00:00
2024-03-01 23:03:14 +00:00
for ( var i = 0 ; i < bindings . Length ; i + = 1 )
2024-02-23 08:06:04 +00:00
{
2024-03-01 23:03:14 +00:00
bindingArray [ i ] = bindings [ i ] . ToRefresh ( ) ;
2024-02-23 08:06:04 +00:00
}
2023-02-24 00:59:34 +00:00
2024-02-23 23:53:49 +00:00
Refresh . Refresh_BindComputeTextures (
2023-02-24 00:59:34 +00:00
Device . Handle ,
Handle ,
2024-03-01 23:03:14 +00:00
bindingArray
2023-02-24 00:59:34 +00:00
) ;
2024-03-01 07:53:11 +00:00
2024-03-01 23:03:14 +00:00
NativeMemory . Free ( bindingArray ) ;
2023-02-24 00:59:34 +00:00
}
2022-02-23 05:14:32 +00:00
/// <summary>
/// Pushes compute shader uniforms to the device.
/// </summary>
/// <returns>A starting offset to be used with dispatch calls.</returns>
2024-02-23 08:06:04 +00:00
public unsafe void PushComputeShaderUniforms (
2023-02-24 00:59:34 +00:00
void * uniformsPtr ,
uint size
) {
2022-09-07 20:07:17 +00:00
#if DEBUG
2024-01-18 20:27:34 +00:00
AssertNotSubmitted ( ) ;
2022-09-07 20:07:17 +00:00
AssertComputePipelineBound ( ) ;
if ( currentComputePipeline . ComputeShaderInfo . UniformBufferSize = = 0 )
{
throw new System . InvalidOperationException ( "The current compute shader does not take a uniform buffer!" ) ;
}
2024-02-23 08:06:04 +00:00
if ( currentComputePipeline . ComputeShaderInfo . UniformBufferSize ! = size )
{
throw new InvalidOperationException ( "Compute uniform data size mismatch!" ) ;
}
2022-09-07 20:07:17 +00:00
# endif
2024-02-23 08:06:04 +00:00
Refresh . Refresh_PushComputeShaderUniforms (
2023-02-24 00:59:34 +00:00
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>
2024-02-23 08:06:04 +00:00
public unsafe void PushComputeShaderUniforms < T > (
2023-02-24 00:59:34 +00:00
in T uniforms
) where T : unmanaged
{
2022-11-17 20:35:21 +00:00
fixed ( T * uniformsPtr = & uniforms )
2022-02-23 05:14:32 +00:00
{
2024-02-23 08:06:04 +00:00
PushComputeShaderUniforms ( uniformsPtr , ( uint ) Marshal . SizeOf < T > ( ) ) ;
2022-02-23 05:14:32 +00:00
}
}
/// <summary>
2024-02-23 23:53:49 +00:00
/// Dispatches compute work.
2022-02-23 05:14:32 +00:00
/// </summary>
2024-02-23 23:53:49 +00:00
/// <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
) {
2022-09-07 20:07:17 +00:00
#if DEBUG
2024-01-18 20:27:34 +00:00
AssertNotSubmitted ( ) ;
2024-02-23 23:53:49 +00:00
AssertInComputePass ( "Cannot dispatch compute outside of compute pass!" ) ;
AssertComputePipelineBound ( ) ;
2022-02-23 05:14:32 +00:00
2024-02-23 23:53:49 +00:00
if ( groupCountX < 1 | | groupCountY < 1 | | groupCountZ < 1 )
{
throw new ArgumentException ( "All dimensions for the compute work group must be >= 1!" ) ;
}
2022-09-07 20:07:17 +00:00
# endif
2024-02-23 23:53:49 +00:00
Refresh . Refresh_DispatchCompute (
2022-08-25 19:32:49 +00:00
Device . Handle ,
Handle ,
2024-02-23 23:53:49 +00:00
groupCountX ,
groupCountY ,
groupCountZ
2022-08-25 19:32:49 +00:00
) ;
}
2024-02-23 23:53:49 +00:00
public void EndComputePass ( )
2022-02-23 05:14:32 +00:00
{
2024-01-18 20:27:34 +00:00
#if DEBUG
2024-02-23 23:53:49 +00:00
AssertInComputePass ( "Cannot end compute pass while not in a compute pass!" ) ;
computePassActive = false ;
2024-01-18 20:27:34 +00:00
# endif
2024-02-23 23:53:49 +00:00
Refresh . Refresh_EndComputePass (
2022-02-23 05:14:32 +00:00
Device . Handle ,
Handle
) ;
}
2024-02-23 08:06:04 +00:00
// Copy Pass
2022-02-23 06:16:06 +00:00
2023-04-05 19:40:34 +00:00
/// <summary>
2024-02-23 08:06:04 +00:00
/// Begins a copy pass.
/// All copy commands must be made within a copy pass.
/// It is an error to call this during any kind of pass.
2023-04-05 19:40:34 +00:00
/// </summary>
2024-02-23 08:06:04 +00:00
public void BeginCopyPass ( )
2023-04-05 19:40:34 +00:00
{
2024-02-23 08:06:04 +00:00
#if DEBUG
AssertNotSubmitted ( ) ;
AssertNotInPass ( "Cannot begin copy pass while in another pass!" ) ;
copyPassActive = true ;
# endif
Refresh . Refresh_BeginCopyPass (
Device . Handle ,
Handle
2023-04-05 19:40:34 +00:00
) ;
}
2024-03-01 23:03:14 +00:00
2022-02-23 05:14:32 +00:00
/// <summary>
2024-02-23 23:40:01 +00:00
/// Uploads data from a TransferBuffer to a TextureSlice.
2024-02-23 08:06:04 +00:00
/// This copy occurs on the GPU timeline.
///
2024-02-23 23:40:01 +00:00
/// Overwriting the contents of the TransferBuffer before the command buffer
2024-02-23 08:06:04 +00:00
/// has finished execution will cause undefined behavior.
///
/// You MAY assume that the copy has finished for subsequent commands.
2022-02-23 05:14:32 +00:00
/// </summary>
2024-03-01 23:03:14 +00:00
/// <param name="writeOption">Specifies data dependency behavior.</param>
2024-02-23 08:06:04 +00:00
public void UploadToTexture (
2024-02-23 18:43:39 +00:00
TransferBuffer transferBuffer ,
2024-03-01 07:53:11 +00:00
in TextureRegion textureRegion ,
2024-02-29 04:07:19 +00:00
in BufferImageCopy copyParams ,
2024-03-01 23:03:14 +00:00
WriteOptions writeOption
2022-02-23 05:14:32 +00:00
)
{
2022-09-07 20:07:17 +00:00
#if DEBUG
2024-01-18 20:27:34 +00:00
AssertNotSubmitted ( ) ;
2024-02-23 08:06:04 +00:00
AssertInCopyPass ( "Cannot upload to texture outside of copy pass!" ) ;
2024-03-01 07:53:11 +00:00
AssertBufferBoundsCheck ( transferBuffer . Size , copyParams . BufferOffset , textureRegion . Size ) ;
2022-09-07 20:07:17 +00:00
# endif
2024-02-23 08:06:04 +00:00
Refresh . Refresh_UploadToTexture (
2022-02-23 05:14:32 +00:00
Device . Handle ,
Handle ,
2024-02-23 18:43:39 +00:00
transferBuffer . Handle ,
2024-03-01 07:53:11 +00:00
textureRegion . ToRefreshTextureRegion ( ) ,
2024-02-29 04:07:19 +00:00
copyParams . ToRefresh ( ) ,
2024-03-01 23:03:14 +00:00
( Refresh . WriteOptions ) writeOption
2022-02-23 05:14:32 +00:00
) ;
}
/// <summary>
2024-02-23 08:06:04 +00:00
/// Uploads the contents of an entire buffer to a texture with no mips.
2022-02-23 05:14:32 +00:00
/// </summary>
2024-02-23 08:06:04 +00:00
public void UploadToTexture (
2024-02-23 18:43:39 +00:00
TransferBuffer transferBuffer ,
2024-02-29 04:07:19 +00:00
Texture texture ,
2024-03-01 23:03:14 +00:00
WriteOptions writeOption
2024-02-23 08:06:04 +00:00
) {
UploadToTexture (
2024-02-23 18:43:39 +00:00
transferBuffer ,
2024-03-01 07:53:11 +00:00
new TextureRegion ( texture ) ,
2024-02-29 04:07:19 +00:00
new BufferImageCopy ( 0 , 0 , 0 ) ,
2024-03-01 23:03:14 +00:00
writeOption
2024-02-23 08:06:04 +00:00
) ;
}
2023-08-07 17:12:46 +00:00
2024-02-23 08:06:04 +00:00
/// <summary>
2024-02-23 23:40:01 +00:00
/// Uploads data from a TransferBuffer to a GpuBuffer.
2024-02-23 08:06:04 +00:00
/// This copy occurs on the GPU timeline.
///
2024-02-23 23:40:01 +00:00
/// Overwriting the contents of the TransferBuffer before the command buffer
2024-02-23 08:06:04 +00:00
/// has finished execution will cause undefined behavior.
///
/// You MAY assume that the copy has finished for subsequent commands.
/// </summary>
public void UploadToBuffer (
2024-02-23 18:43:39 +00:00
TransferBuffer transferBuffer ,
2024-02-23 08:06:04 +00:00
GpuBuffer gpuBuffer ,
2024-02-29 04:07:19 +00:00
in BufferCopy copyParams ,
2024-03-01 23:03:14 +00:00
WriteOptions option
2024-02-23 08:06:04 +00:00
) {
2022-09-07 20:07:17 +00:00
#if DEBUG
2024-01-18 20:27:34 +00:00
AssertNotSubmitted ( ) ;
2024-02-23 08:06:04 +00:00
AssertInCopyPass ( "Cannot upload to texture outside of copy pass!" ) ;
2024-02-23 18:43:39 +00:00
AssertBufferBoundsCheck ( transferBuffer . Size , copyParams . SrcOffset , copyParams . Size ) ;
AssertBufferBoundsCheck ( gpuBuffer . Size , copyParams . DstOffset , copyParams . Size ) ;
2022-09-07 20:07:17 +00:00
# endif
2024-02-23 08:06:04 +00:00
Refresh . Refresh_UploadToBuffer (
Device . Handle ,
Handle ,
2024-02-23 18:43:39 +00:00
transferBuffer . Handle ,
2024-02-23 08:06:04 +00:00
gpuBuffer . Handle ,
2024-02-29 04:07:19 +00:00
copyParams . ToRefresh ( ) ,
2024-03-01 23:03:14 +00:00
( Refresh . WriteOptions ) option
2024-02-23 08:06:04 +00:00
) ;
2022-02-23 05:14:32 +00:00
}
2023-04-05 19:40:34 +00:00
/// <summary>
2024-02-23 23:40:01 +00:00
/// Copies the entire contents of a TransferBuffer to a GpuBuffer.
2023-04-05 19:40:34 +00:00
/// </summary>
2024-02-23 08:06:04 +00:00
public void UploadToBuffer (
2024-02-23 18:43:39 +00:00
TransferBuffer transferBuffer ,
2024-02-29 04:07:19 +00:00
GpuBuffer gpuBuffer ,
2024-03-01 23:03:14 +00:00
WriteOptions option
2024-02-23 08:06:04 +00:00
) {
UploadToBuffer (
2024-02-23 18:43:39 +00:00
transferBuffer ,
2024-02-23 08:06:04 +00:00
gpuBuffer ,
2024-02-29 04:07:19 +00:00
new BufferCopy ( 0 , 0 , transferBuffer . Size ) ,
option
2024-02-23 08:06:04 +00:00
) ;
2023-04-05 19:40:34 +00:00
}
2024-02-23 08:06:04 +00:00
/// <summary>
2024-02-23 23:40:01 +00:00
/// Copies data element-wise into from a TransferBuffer to a GpuBuffer.
/// </summary>
public void UploadToBuffer < T > (
TransferBuffer transferBuffer ,
GpuBuffer gpuBuffer ,
uint sourceStartElement ,
uint destinationStartElement ,
2024-02-29 04:07:19 +00:00
uint numElements ,
2024-03-01 23:03:14 +00:00
WriteOptions option
2024-02-23 23:40:01 +00:00
) where T : unmanaged
{
var elementSize = Marshal . SizeOf < T > ( ) ;
var dataLengthInBytes = ( uint ) ( elementSize * numElements ) ;
var srcOffsetInBytes = ( uint ) ( elementSize * sourceStartElement ) ;
var dstOffsetInBytes = ( uint ) ( elementSize * destinationStartElement ) ;
UploadToBuffer (
transferBuffer ,
gpuBuffer ,
new BufferCopy (
srcOffsetInBytes ,
dstOffsetInBytes ,
dataLengthInBytes
2024-02-29 04:07:19 +00:00
) ,
option
2024-02-23 23:40:01 +00:00
) ;
}
2022-02-23 05:14:32 +00:00
/// <summary>
2024-02-23 08:06:04 +00:00
/// Copies the contents of a TextureSlice to another TextureSlice.
/// The slices must have the same dimensions.
/// This copy occurs on the GPU timeline.
///
/// You MAY assume that the copy has finished in subsequent commands.
2022-02-23 05:14:32 +00:00
/// </summary>
2024-02-23 08:06:04 +00:00
public void CopyTextureToTexture (
2024-03-01 07:53:11 +00:00
in TextureRegion source ,
in TextureRegion destination ,
2024-03-01 23:03:14 +00:00
WriteOptions option
2024-02-23 08:06:04 +00:00
) {
2022-09-07 20:07:17 +00:00
#if DEBUG
2024-01-18 20:27:34 +00:00
AssertNotSubmitted ( ) ;
2024-02-23 08:06:04 +00:00
AssertInCopyPass ( "Cannot download from texture outside of copy pass!" ) ;
2024-02-23 18:43:39 +00:00
AssertTextureBoundsCheck ( destination . Size , source . Size ) ;
2022-09-07 20:07:17 +00:00
# endif
2024-02-23 08:06:04 +00:00
Refresh . Refresh_CopyTextureToTexture (
Device . Handle ,
Handle ,
2024-03-01 07:53:11 +00:00
source . ToRefreshTextureRegion ( ) ,
destination . ToRefreshTextureRegion ( ) ,
2024-03-01 23:03:14 +00:00
( Refresh . WriteOptions ) option
2024-02-23 08:06:04 +00:00
) ;
2022-02-23 05:14:32 +00:00
}
2023-04-05 19:40:34 +00:00
/// <summary>
2024-02-23 08:06:04 +00:00
/// Copies the contents of an entire Texture with no mips to another Texture with no mips.
/// The textures must have the same dimensions.
2023-04-05 19:40:34 +00:00
/// </summary>
2024-02-23 08:06:04 +00:00
public void CopyTextureToTexture (
Texture source ,
2024-02-29 04:07:19 +00:00
Texture destination ,
2024-03-01 23:03:14 +00:00
WriteOptions option
2024-02-23 08:06:04 +00:00
) {
CopyTextureToTexture (
2024-03-01 07:53:11 +00:00
new TextureRegion ( source ) ,
new TextureRegion ( destination ) ,
2024-02-29 04:07:19 +00:00
option
2024-02-23 08:06:04 +00:00
) ;
2023-04-05 19:40:34 +00:00
}
2024-02-23 08:06:04 +00:00
/// <summary>
/// Copies data from a GpuBuffer to another GpuBuffer.
/// This copy occurs on the GPU timeline.
///
/// You MAY assume that the copy has finished in subsequent commands.
/// </summary>
public void CopyBufferToBuffer (
GpuBuffer source ,
GpuBuffer destination ,
2024-02-29 04:07:19 +00:00
in BufferCopy copyParams ,
2024-03-01 23:03:14 +00:00
WriteOptions option
2024-02-23 08:06:04 +00:00
) {
2022-09-07 20:07:17 +00:00
#if DEBUG
2024-01-18 20:27:34 +00:00
AssertNotSubmitted ( ) ;
2024-02-23 08:06:04 +00:00
AssertInCopyPass ( "Cannot download from texture outside of copy pass!" ) ;
2024-02-23 18:43:39 +00:00
AssertBufferBoundsCheck ( source . Size , copyParams . SrcOffset , copyParams . Size ) ;
AssertBufferBoundsCheck ( destination . Size , copyParams . DstOffset , copyParams . Size ) ;
2022-09-07 20:07:17 +00:00
# endif
2024-02-23 08:06:04 +00:00
Refresh . Refresh_CopyBufferToBuffer (
2022-02-23 05:14:32 +00:00
Device . Handle ,
Handle ,
2024-02-23 08:06:04 +00:00
source . Handle ,
destination . Handle ,
2024-02-29 04:07:19 +00:00
copyParams . ToRefresh ( ) ,
2024-03-01 23:03:14 +00:00
( Refresh . WriteOptions ) option
2022-02-23 05:14:32 +00:00
) ;
}
/// <summary>
2024-02-23 08:06:04 +00:00
/// Copies the entire contents of a GpuBuffer to another GpuBuffer.
2022-02-23 05:14:32 +00:00
/// </summary>
2024-02-23 08:06:04 +00:00
public void CopyBufferToBuffer (
GpuBuffer source ,
2024-02-29 04:07:19 +00:00
GpuBuffer destination ,
2024-03-01 23:03:14 +00:00
WriteOptions option
2024-02-23 08:06:04 +00:00
) {
CopyBufferToBuffer (
source ,
destination ,
2024-02-29 04:07:19 +00:00
new BufferCopy ( 0 , 0 , source . Size ) ,
option
2024-02-23 08:06:04 +00:00
) ;
}
public void EndCopyPass ( )
2022-02-23 05:14:32 +00:00
{
2022-09-07 20:07:17 +00:00
#if DEBUG
2024-01-18 20:27:34 +00:00
AssertNotSubmitted ( ) ;
2024-02-23 08:06:04 +00:00
AssertInCopyPass ( "Cannot end copy pass while not in a copy pass!" ) ;
copyPassActive = false ;
2022-09-07 20:07:17 +00:00
# endif
2024-02-23 08:06:04 +00:00
Refresh . Refresh_EndCopyPass (
2022-02-23 05:14:32 +00:00
Device . Handle ,
2024-02-23 08:06:04 +00:00
Handle
2022-02-23 05:14:32 +00:00
) ;
}
2022-09-07 20:07:17 +00:00
#if DEBUG
private void AssertRenderPassActive ( string message = "No active render pass!" )
{
if ( ! renderPassActive )
{
throw new System . InvalidOperationException ( message ) ;
}
}
private void AssertRenderPassInactive ( string message = "Render pass is active!" )
{
if ( renderPassActive )
{
throw new System . InvalidCastException ( message ) ;
}
}
private void AssertGraphicsPipelineBound ( string message = "No graphics pipeline is bound!" )
{
if ( currentGraphicsPipeline = = null )
{
throw new System . InvalidOperationException ( message ) ;
}
}
2022-11-17 20:35:21 +00:00
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}" ) ;
}
}
2022-11-29 21:06:03 +00:00
if ( graphicsPipeline . AttachmentInfo . HasDepthStencilAttachment )
2022-11-17 20:35:21 +00:00
{
2022-11-29 21:06:03 +00:00
var pipelineDepthFormat = graphicsPipeline . AttachmentInfo . DepthStencilFormat ;
2024-01-16 07:11:28 +00:00
if ( ! hasDepthStencilAttachment )
{
throw new System . InvalidOperationException ( "Pipeline expects depth attachment!" ) ;
}
2022-11-29 21:06:03 +00:00
if ( pipelineDepthFormat ! = depthStencilFormat )
{
throw new System . InvalidOperationException ( $"Depth texture format mismatch! Pipeline expects {pipelineDepthFormat}, render pass attachment is {depthStencilFormat}" ) ;
}
2022-11-17 20:35:21 +00:00
}
}
private void AssertVertexSamplerCount ( int count )
{
if ( currentGraphicsPipeline . VertexShaderInfo . SamplerBindingCount ! = count )
{
throw new System . InvalidOperationException ( $"Vertex sampler expected {currentGraphicsPipeline.VertexShaderInfo.SamplerBindingCount} samplers, but received {count}" ) ;
}
}
private void AssertFragmentSamplerCount ( int count )
{
if ( currentGraphicsPipeline . FragmentShaderInfo . SamplerBindingCount ! = count )
{
throw new System . InvalidOperationException ( $"Fragment sampler expected {currentGraphicsPipeline.FragmentShaderInfo.SamplerBindingCount} samplers, but received {count}" ) ;
}
}
2022-09-07 20:07:17 +00:00
private void AssertComputePipelineBound ( string message = "No compute pipeline is bound!" )
{
if ( currentComputePipeline = = null )
{
throw new System . InvalidOperationException ( message ) ;
}
}
2022-11-08 19:29:05 +00:00
2022-11-17 20:35:21 +00:00
private void AssertComputeBufferCount ( int count )
2022-11-08 19:29:05 +00:00
{
2022-11-17 20:35:21 +00:00
if ( currentComputePipeline . ComputeShaderInfo . BufferBindingCount ! = count )
2022-11-08 19:29:05 +00:00
{
2022-11-17 20:35:21 +00:00
throw new System . InvalidOperationException ( $"Compute pipeline expects {currentComputePipeline.ComputeShaderInfo.BufferBindingCount} buffers, but received {count}" ) ;
2022-11-08 19:29:05 +00:00
}
2022-11-17 20:35:21 +00:00
}
2022-11-08 19:29:05 +00:00
2022-11-17 20:35:21 +00:00
private void AssertComputeTextureCount ( int count )
{
if ( currentComputePipeline . ComputeShaderInfo . ImageBindingCount ! = count )
2022-11-08 19:29:05 +00:00
{
2022-11-17 20:35:21 +00:00
throw new System . InvalidOperationException ( $"Compute pipeline expects {currentComputePipeline.ComputeShaderInfo.ImageBindingCount} textures, but received {count}" ) ;
2022-11-08 19:29:05 +00:00
}
2022-11-17 20:35:21 +00:00
}
2022-11-08 19:29:05 +00:00
2022-11-17 20:35:21 +00:00
private void AssertTextureNotNull ( ColorAttachmentInfo colorAttachmentInfo )
{
2024-03-01 07:53:11 +00:00
if ( colorAttachmentInfo . TextureSlice . Texture = = null | | colorAttachmentInfo . TextureSlice . Texture . Handle = = IntPtr . Zero )
2022-11-08 19:29:05 +00:00
{
2022-11-17 20:35:21 +00:00
throw new System . ArgumentException ( "Render pass color attachment Texture cannot be null!" ) ;
}
}
2022-11-08 19:29:05 +00:00
2022-11-17 20:35:21 +00:00
private void AssertColorTarget ( ColorAttachmentInfo colorAttachmentInfo )
{
2024-03-01 07:53:11 +00:00
if ( ( colorAttachmentInfo . TextureSlice . Texture . UsageFlags & TextureUsageFlags . ColorTarget ) = = 0 )
2022-11-17 20:35:21 +00:00
{
throw new System . ArgumentException ( "Render pass color attachment UsageFlags must include TextureUsageFlags.ColorTarget!" ) ;
}
}
2022-11-09 18:49:53 +00:00
2024-01-16 07:11:28 +00:00
private void AssertSameSampleCount ( Texture a , Texture b )
2022-11-17 20:35:21 +00:00
{
2024-01-16 07:11:28 +00:00
if ( a . SampleCount ! = b . SampleCount )
2022-11-17 20:35:21 +00:00
{
2024-01-16 07:11:28 +00:00
throw new System . ArgumentException ( "All attachments in a render pass must have the same SampleCount!" ) ;
2022-11-08 19:29:05 +00:00
}
}
2022-11-09 18:49:53 +00:00
private void AssertValidDepthAttachment ( DepthStencilAttachmentInfo depthStencilAttachmentInfo )
2022-11-08 19:29:05 +00:00
{
2024-03-01 07:53:11 +00:00
if ( depthStencilAttachmentInfo . TextureSlice . Texture = = null | |
depthStencilAttachmentInfo . TextureSlice . Texture . Handle = = IntPtr . Zero )
2022-11-08 19:29:05 +00:00
{
throw new System . ArgumentException ( "Render pass depth stencil attachment Texture cannot be null!" ) ;
}
2024-03-01 07:53:11 +00:00
if ( ( depthStencilAttachmentInfo . TextureSlice . Texture . UsageFlags & TextureUsageFlags . DepthStencilTarget ) = = 0 )
2022-11-08 19:29:05 +00:00
{
throw new System . ArgumentException ( "Render pass depth stencil attachment UsageFlags must include TextureUsageFlags.DepthStencilTarget!" ) ;
}
}
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 AssertTextureBindingUsageFlags ( Texture texture )
{
if ( ( texture . UsageFlags & TextureUsageFlags . Sampler ) = = 0 )
{
throw new System . ArgumentException ( "The bound Texture's UsageFlags must include TextureUsageFlags.Sampler!" ) ;
}
}
2023-08-07 17:12:46 +00:00
private void AssertNonEmptyCopy ( uint dataLengthInBytes )
{
if ( dataLengthInBytes = = 0 )
{
throw new System . InvalidOperationException ( "SetBufferData must have a length greater than 0 bytes!" ) ;
}
}
2024-01-16 06:19:59 +00:00
private void AssertBufferBoundsCheck ( uint bufferLengthInBytes , uint offsetInBytes , uint copyLengthInBytes )
{
if ( copyLengthInBytes > bufferLengthInBytes + offsetInBytes )
{
throw new System . InvalidOperationException ( $"SetBufferData overflow! buffer length {bufferLengthInBytes}, offset {offsetInBytes}, copy length {copyLengthInBytes}" ) ;
}
}
private void AssertTextureBoundsCheck ( uint textureSizeInBytes , uint dataLengthInBytes )
{
if ( dataLengthInBytes > textureSizeInBytes )
{
throw new System . InvalidOperationException ( $"SetTextureData overflow! texture size {textureSizeInBytes}, data size {dataLengthInBytes}" ) ;
}
}
2024-01-18 20:27:34 +00:00
2024-02-23 08:06:04 +00:00
private void AssertNotInPass ( string message )
{
if ( renderPassActive | | copyPassActive | | computePassActive )
{
throw new System . InvalidOperationException ( message ) ;
}
}
private void AssertInRenderPass ( string message )
{
if ( ! renderPassActive )
{
throw new System . InvalidOperationException ( message ) ;
}
}
private void AssertInCopyPass ( string message )
{
if ( ! copyPassActive )
{
throw new System . InvalidOperationException ( message ) ;
}
}
2024-02-23 18:43:39 +00:00
private void AssertInComputePass ( string message )
{
if ( ! computePassActive )
{
throw new System . InvalidOperationException ( message ) ;
}
}
2024-01-18 20:27:34 +00:00
private void AssertNotSubmitted ( )
{
if ( Submitted )
{
throw new System . InvalidOperationException ( "Cannot add commands to a submitted command buffer!" ) ;
}
}
2022-09-07 20:07:17 +00:00
# endif
2022-02-23 05:14:32 +00:00
}
2021-01-20 03:33:27 +00:00
}