From 3cfb43438c3dac2be6ad48038333462b6be65c0f Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Tue, 4 Jun 2024 19:35:17 -0700 Subject: [PATCH] refactor CopyPass --- src/Game.cs | 7 +- src/Graphics/CommandBuffer.cs | 298 +++++------------------ src/Graphics/CopyPass.cs | 203 +++++++++++++++ src/Graphics/CopyPassPool.cs | 25 ++ src/Graphics/GraphicsDevice.cs | 1 + src/Graphics/ImageUtils.cs | 1 + src/Graphics/ResourceUploader.cs | 36 +-- src/Graphics/Resources/Fence.cs | 37 ++- src/Graphics/Resources/Sampler.cs | 35 ++- src/Graphics/Resources/TransferBuffer.cs | 56 +++-- src/Graphics/SDL_GpuTypes.cs | 4 +- src/Logger.cs | 14 -- src/WindowCreateInfo.cs | 8 +- 13 files changed, 381 insertions(+), 344 deletions(-) create mode 100644 src/Graphics/CopyPass.cs create mode 100644 src/Graphics/CopyPassPool.cs diff --git a/src/Game.cs b/src/Game.cs index 1876814..2a1bbbf 100644 --- a/src/Game.cs +++ b/src/Game.cs @@ -48,12 +48,13 @@ namespace MoonWorks /// /// The parameters that will be used to create the MainWindow. /// The frame limiter settings. + /// Bitflags of which GPU backends to attempt to initialize. /// How often Game.Update will run in terms of ticks per second. /// If true, enables extra debug checks. Should be turned off for release builds. public Game( WindowCreateInfo windowCreateInfo, FrameLimiterSettings frameLimiterSettings, - Span preferredBackends, + BackendFlags preferredBackends, int targetTimestep = 60, bool debugMode = false ) { @@ -75,8 +76,6 @@ namespace MoonWorks return; } - Logger.Initialize(); - Logger.LogInfo("Initializing input..."); Inputs = new Inputs(); @@ -89,7 +88,7 @@ namespace MoonWorks Logger.LogInfo("Initializing main window..."); MainWindow = new Window(windowCreateInfo, GraphicsDevice.WindowFlags | SDL.SDL_WindowFlags.SDL_WINDOW_HIDDEN); - if (!GraphicsDevice.ClaimWindow(MainWindow, windowCreateInfo.PresentMode)) + if (!GraphicsDevice.ClaimWindow(MainWindow, windowCreateInfo.SwapchainComposition, windowCreateInfo.PresentMode)) { throw new System.SystemException("Could not claim window!"); } diff --git a/src/Graphics/CommandBuffer.cs b/src/Graphics/CommandBuffer.cs index 229abf2..faf187f 100644 --- a/src/Graphics/CommandBuffer.cs +++ b/src/Graphics/CommandBuffer.cs @@ -617,6 +617,7 @@ public class CommandBuffer renderPass.Handle ); + renderPass.SetHandle(nint.Zero); Device.RenderPassPool.Return(renderPass); } @@ -730,6 +731,45 @@ public class CommandBuffer return computePass; } + public unsafe ComputePass BeginComputePass( + Span readWriteTextureBindings, + Span readWriteBufferBindings + ) { +#if DEBUG + AssertNotSubmitted(); + AssertNotInPass("Cannot begin compute pass while in another pass!"); + computePassActive = true; +#endif + + var sdlTextureBindings = NativeMemory.Alloc( + (nuint) (readWriteTextureBindings.Length * Marshal.SizeOf()) + ); + + var sdlBufferBindings = NativeMemory.Alloc( + (nuint) (readWriteBufferBindings.Length * Marshal.SizeOf()) + ); + + var computePassHandle = SDL_Gpu.SDL_GpuBeginComputePass( + Handle, + (SDL_Gpu.StorageTextureReadWriteBinding*) sdlTextureBindings, + (uint) readWriteTextureBindings.Length, + (SDL_Gpu.StorageBufferReadWriteBinding*) sdlBufferBindings, + (uint) readWriteBufferBindings.Length + ); + + var computePass = Device.ComputePassPool.Obtain(); + computePass.SetHandle(computePassHandle); + +#if DEBUG + computePass.active = true; +#endif + + NativeMemory.Free(sdlTextureBindings); + NativeMemory.Free(sdlBufferBindings); + + return computePass; + } + public void EndComputePass(ComputePass computePass) { #if DEBUG @@ -742,6 +782,9 @@ public class CommandBuffer SDL_Gpu.SDL_GpuEndComputePass( computePass.Handle ); + + computePass.SetHandle(nint.Zero); + Device.ComputePassPool.Return(computePass); } // Copy Pass @@ -751,7 +794,7 @@ public class CommandBuffer /// All copy commands must be made within a copy pass. /// It is an error to call this during any kind of pass. /// - public void BeginCopyPass() + public CopyPass BeginCopyPass() { #if DEBUG AssertNotSubmitted(); @@ -759,228 +802,15 @@ public class CommandBuffer copyPassActive = true; #endif - Refresh.Refresh_BeginCopyPass( - Device.Handle, - Handle - ); + var copyPassHandle = SDL_Gpu.SDL_GpuBeginCopyPass(Handle); + + var copyPass = Device.CopyPassPool.Obtain(); + copyPass.SetHandle(copyPassHandle); + + return copyPass; } - - /// - /// Uploads data from a TransferBuffer to a TextureSlice. - /// This copy occurs on the GPU timeline. - /// - /// Overwriting the contents of the TransferBuffer before the command buffer - /// has finished execution will cause undefined behavior. - /// - /// You MAY assume that the copy has finished for subsequent commands. - /// - /// Specifies data dependency behavior. - public void UploadToTexture( - TransferBuffer transferBuffer, - in TextureRegion textureRegion, - in BufferImageCopy copyParams, - WriteOptions writeOption - ) - { -#if DEBUG - AssertNotSubmitted(); - AssertInCopyPass("Cannot upload to texture outside of copy pass!"); - AssertBufferBoundsCheck(transferBuffer.Size, copyParams.BufferOffset, textureRegion.Size); -#endif - - Refresh.Refresh_UploadToTexture( - Device.Handle, - Handle, - transferBuffer.Handle, - textureRegion.ToRefreshTextureRegion(), - copyParams.ToRefresh(), - (Refresh.WriteOptions) writeOption - ); - } - - /// - /// Uploads the contents of an entire buffer to a texture with no mips. - /// - public void UploadToTexture( - TransferBuffer transferBuffer, - Texture texture, - WriteOptions writeOption - ) { - UploadToTexture( - transferBuffer, - new TextureRegion(texture), - new BufferImageCopy(0, 0, 0), - writeOption - ); - } - - /// - /// Uploads data from a TransferBuffer to a GpuBuffer. - /// This copy occurs on the GPU timeline. - /// - /// Overwriting the contents of the TransferBuffer before the command buffer - /// has finished execution will cause undefined behavior. - /// - /// You MAY assume that the copy has finished for subsequent commands. - /// - public void UploadToBuffer( - TransferBuffer transferBuffer, - GpuBuffer gpuBuffer, - in BufferCopy copyParams, - WriteOptions option - ) { -#if DEBUG - AssertNotSubmitted(); - AssertInCopyPass("Cannot upload to texture outside of copy pass!"); - AssertBufferBoundsCheck(transferBuffer.Size, copyParams.SrcOffset, copyParams.Size); - AssertBufferBoundsCheck(gpuBuffer.Size, copyParams.DstOffset, copyParams.Size); -#endif - - Refresh.Refresh_UploadToBuffer( - Device.Handle, - Handle, - transferBuffer.Handle, - gpuBuffer.Handle, - copyParams.ToRefresh(), - (Refresh.WriteOptions) option - ); - } - - /// - /// Copies the entire contents of a TransferBuffer to a GpuBuffer. - /// - public void UploadToBuffer( - TransferBuffer transferBuffer, - GpuBuffer gpuBuffer, - WriteOptions option - ) { - UploadToBuffer( - transferBuffer, - gpuBuffer, - new BufferCopy(0, 0, transferBuffer.Size), - option - ); - } - - /// - /// Copies data element-wise into from a TransferBuffer to a GpuBuffer. - /// - public void UploadToBuffer( - TransferBuffer transferBuffer, - GpuBuffer gpuBuffer, - uint sourceStartElement, - uint destinationStartElement, - uint numElements, - WriteOptions option - ) where T : unmanaged - { - var elementSize = Marshal.SizeOf(); - var dataLengthInBytes = (uint) (elementSize * numElements); - var srcOffsetInBytes = (uint) (elementSize * sourceStartElement); - var dstOffsetInBytes = (uint) (elementSize * destinationStartElement); - - UploadToBuffer( - transferBuffer, - gpuBuffer, - new BufferCopy( - srcOffsetInBytes, - dstOffsetInBytes, - dataLengthInBytes - ), - option - ); - } - - /// - /// 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. - /// - public void CopyTextureToTexture( - in TextureRegion source, - in TextureRegion destination, - WriteOptions option - ) { -#if DEBUG - AssertNotSubmitted(); - AssertInCopyPass("Cannot download from texture outside of copy pass!"); - AssertTextureBoundsCheck(destination.Size, source.Size); -#endif - - Refresh.Refresh_CopyTextureToTexture( - Device.Handle, - Handle, - source.ToRefreshTextureRegion(), - destination.ToRefreshTextureRegion(), - (Refresh.WriteOptions) option - ); - } - - /// - /// Copies the contents of an entire Texture with no mips to another Texture with no mips. - /// The textures must have the same dimensions. - /// - public void CopyTextureToTexture( - Texture source, - Texture destination, - WriteOptions option - ) { - CopyTextureToTexture( - new TextureRegion(source), - new TextureRegion(destination), - option - ); - } - - /// - /// 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. - /// - public void CopyBufferToBuffer( - GpuBuffer source, - GpuBuffer destination, - in BufferCopy copyParams, - WriteOptions option - ) { -#if DEBUG - AssertNotSubmitted(); - AssertInCopyPass("Cannot download from texture outside of copy pass!"); - AssertBufferBoundsCheck(source.Size, copyParams.SrcOffset, copyParams.Size); - AssertBufferBoundsCheck(destination.Size, copyParams.DstOffset, copyParams.Size); -#endif - - Refresh.Refresh_CopyBufferToBuffer( - Device.Handle, - Handle, - source.Handle, - destination.Handle, - copyParams.ToRefresh(), - (Refresh.WriteOptions) option - ); - } - - /// - /// Copies the entire contents of a GpuBuffer to another GpuBuffer. - /// - public void CopyBufferToBuffer( - GpuBuffer source, - GpuBuffer destination, - WriteOptions option - ) { - CopyBufferToBuffer( - source, - destination, - new BufferCopy(0, 0, source.Size), - option - ); - } - - public void EndCopyPass() + public void EndCopyPass(CopyPass copyPass) { #if DEBUG AssertNotSubmitted(); @@ -988,10 +818,12 @@ public class CommandBuffer copyPassActive = false; #endif - Refresh.Refresh_EndCopyPass( - Device.Handle, - Handle + SDL_Gpu.SDL_GpuEndCopyPass( + copyPass.Handle ); + + copyPass.SetHandle(nint.Zero); + Device.CopyPassPool.Return(copyPass); } #if DEBUG @@ -1011,22 +843,6 @@ public class CommandBuffer } } - private void AssertComputeBufferCount(int count) - { - if (currentComputePipeline.ComputeShaderInfo.BufferBindingCount != count) - { - throw new System.InvalidOperationException($"Compute pipeline expects {currentComputePipeline.ComputeShaderInfo.BufferBindingCount} buffers, but received {count}"); - } - } - - private void AssertComputeTextureCount(int count) - { - if (currentComputePipeline.ComputeShaderInfo.ImageBindingCount != count) - { - throw new System.InvalidOperationException($"Compute pipeline expects {currentComputePipeline.ComputeShaderInfo.ImageBindingCount} textures, but received {count}"); - } - } - private void AssertTextureNotNull(ColorAttachmentInfo colorAttachmentInfo) { if (colorAttachmentInfo.TextureSlice.Texture == null || colorAttachmentInfo.TextureSlice.Texture.Handle == IntPtr.Zero) @@ -1059,7 +875,7 @@ public class CommandBuffer throw new System.ArgumentException("Render pass depth stencil attachment Texture cannot be null!"); } - if ((depthStencilAttachmentInfo.TextureSlice.Texture.UsageFlags & TextureUsageFlags.DepthStencilTarget) == 0) + if ((depthStencilAttachmentInfo.TextureSlice.Texture.UsageFlags & TextureUsageFlags.DepthStencil) == 0) { throw new System.ArgumentException("Render pass depth stencil attachment UsageFlags must include TextureUsageFlags.DepthStencilTarget!"); } diff --git a/src/Graphics/CopyPass.cs b/src/Graphics/CopyPass.cs new file mode 100644 index 0000000..de4de7e --- /dev/null +++ b/src/Graphics/CopyPass.cs @@ -0,0 +1,203 @@ +using System.Runtime.InteropServices; +using SDL2_gpuCS; + +namespace MoonWorks.Graphics; + +public class CopyPass +{ + public nint Handle { get; private set; } + + internal void SetHandle(nint handle) + { + Handle = handle; + } + + /// + /// Uploads data from a TransferBuffer to a TextureSlice. + /// This copy occurs on the GPU timeline. + /// + /// Overwriting the contents of the TransferBuffer before the command buffer + /// has finished execution will cause undefined behavior. + /// + /// You MAY assume that the copy has finished for subsequent commands. + /// + /// If true, cycles the texture if the given slice is bound. + public void UploadToTexture( + TransferBuffer transferBuffer, + in TextureRegion textureRegion, + in BufferImageCopy copyParams, + bool cycle + ) { +#if DEBUG + AssertBufferBoundsCheck(transferBuffer.Size, copyParams.BufferOffset, textureRegion.Size); +#endif + + SDL_Gpu.SDL_GpuUploadToTexture( + Handle, + transferBuffer.Handle, + textureRegion.ToSDL(), + copyParams.ToSDL(), + Conversions.BoolToInt(cycle) + ); + } + + /// + /// Uploads the contents of an entire buffer to a 2D texture with no mips. + /// + public void UploadToTexture( + TransferBuffer transferBuffer, + Texture texture, + bool cycle + ) { + UploadToTexture( + transferBuffer, + new TextureRegion(texture), + new BufferImageCopy(0, 0, 0), + cycle + ); + } + + /// + /// Uploads data from a TransferBuffer to a GpuBuffer. + /// This copy occurs on the GPU timeline. + /// + /// Overwriting the contents of the TransferBuffer before the command buffer + /// has finished execution will cause undefined behavior. + /// + /// You MAY assume that the copy has finished for subsequent commands. + /// + /// If true, cycles the buffer if it is bound. + public void UploadToBuffer( + TransferBuffer transferBuffer, + GpuBuffer buffer, + in BufferCopy copyParams, + bool cycle + ) { +#if DEBUG + AssertBufferBoundsCheck(transferBuffer.Size, copyParams.SrcOffset, copyParams.Size); + AssertBufferBoundsCheck(buffer.Size, copyParams.DstOffset, copyParams.Size); +#endif + + SDL_Gpu.SDL_GpuUploadToBuffer( + Handle, + transferBuffer.Handle, + buffer.Handle, + copyParams.ToSDL(), + Conversions.BoolToInt(cycle) + ); + } + + /// + /// Copies the entire contents of a TransferBuffer to a GpuBuffer. + /// + public void UploadToBuffer( + TransferBuffer transferBuffer, + GpuBuffer buffer, + bool cycle + ) { + UploadToBuffer( + transferBuffer, + buffer, + new BufferCopy(0, 0, transferBuffer.Size), + cycle + ); + } + + /// + /// Copies data element-wise into from a TransferBuffer to a GpuBuffer. + /// + public void UploadToBuffer( + TransferBuffer transferBuffer, + GpuBuffer buffer, + uint sourceStartElement, + uint destinationStartElement, + uint numElements, + bool cycle + ) where T : unmanaged + { + var elementSize = Marshal.SizeOf(); + var dataLengthInBytes = (uint) (elementSize * numElements); + var srcOffsetInBytes = (uint) (elementSize * sourceStartElement); + var dstOffsetInBytes = (uint) (elementSize * destinationStartElement); + + UploadToBuffer( + transferBuffer, + buffer, + new BufferCopy(srcOffsetInBytes, dstOffsetInBytes, dataLengthInBytes), + cycle + ); + } + + /// + /// Copies the contents of a TextureRegion to another TextureRegion. + /// The regions must have the same dimensions. + /// This copy occurs on the GPU timeline. + /// + /// You MAY assume that the copy has finished in subsequent commands. + /// + public void CopyTextureToTexture( + in TextureRegion source, + in TextureRegion destination, + bool cycle + ) { +#if DEBUG + AssertTextureBoundsCheck(destination.Size, source.Size); + + if (source.Width != destination.Width || source.Height != destination.Height || source.Depth != destination.Depth) + { + throw new System.InvalidOperationException("Texture copy must have the same dimensions!"); + } +#endif + + SDL_Gpu.SDL_GpuCopyTextureToTexture( + Handle, + source.ToSDL(), + destination.ToSDL(), + Conversions.BoolToInt(cycle) + ); + } + + /// + /// 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. + /// + public void CopyBufferToBuffer( + GpuBuffer source, + GpuBuffer destination, + in BufferCopy copyParams, + bool cycle + ) { +#if DEBUG + AssertBufferBoundsCheck(source.Size, copyParams.SrcOffset, copyParams.Size); + AssertBufferBoundsCheck(destination.Size, copyParams.DstOffset, copyParams.Size); +#endif + + SDL_Gpu.SDL_GpuCopyBufferToBuffer( + Handle, + source.Handle, + destination.Handle, + copyParams.ToSDL(), + Conversions.BoolToInt(cycle) + ); + } + +#if DEBUG + 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}"); + } + } +#endif +} diff --git a/src/Graphics/CopyPassPool.cs b/src/Graphics/CopyPassPool.cs new file mode 100644 index 0000000..fde8097 --- /dev/null +++ b/src/Graphics/CopyPassPool.cs @@ -0,0 +1,25 @@ +using System.Collections.Concurrent; + +namespace MoonWorks.Graphics; + +internal class CopyPassPool +{ + private ConcurrentQueue CopyPasses = new ConcurrentQueue(); + + public CopyPass Obtain() + { + if (CopyPasses.TryDequeue(out var copyPass)) + { + return copyPass; + } + else + { + return new CopyPass(); + } + } + + public void Return(CopyPass copyPass) + { + CopyPasses.Enqueue(copyPass); + } +} diff --git a/src/Graphics/GraphicsDevice.cs b/src/Graphics/GraphicsDevice.cs index 92abfd7..fc01b24 100644 --- a/src/Graphics/GraphicsDevice.cs +++ b/src/Graphics/GraphicsDevice.cs @@ -41,6 +41,7 @@ namespace MoonWorks.Graphics private FencePool FencePool; internal RenderPassPool RenderPassPool; internal ComputePassPool ComputePassPool; + internal CopyPassPool CopyPassPool; internal unsafe GraphicsDevice( BackendFlags preferredBackends, diff --git a/src/Graphics/ImageUtils.cs b/src/Graphics/ImageUtils.cs index 11ee4b7..c97e6da 100644 --- a/src/Graphics/ImageUtils.cs +++ b/src/Graphics/ImageUtils.cs @@ -2,6 +2,7 @@ using System; using System.IO; using System.Runtime.InteropServices; using RefreshCS; +using SDL2; namespace MoonWorks.Graphics { diff --git a/src/Graphics/ResourceUploader.cs b/src/Graphics/ResourceUploader.cs index 0475931..e2564ce 100644 --- a/src/Graphics/ResourceUploader.cs +++ b/src/Graphics/ResourceUploader.cs @@ -26,8 +26,8 @@ namespace MoonWorks.Graphics uint textureDataOffset = 0; uint textureDataSize = 1024; - List<(GpuBuffer, BufferCopy, WriteOptions)> BufferUploads = new List<(GpuBuffer, BufferCopy, WriteOptions)>(); - List<(TextureRegion, uint, WriteOptions)> TextureUploads = new List<(TextureRegion, uint, WriteOptions)>(); + List<(GpuBuffer, BufferCopy, bool)> BufferUploads = new List<(GpuBuffer, BufferCopy, bool)>(); + List<(TextureRegion, uint, bool)> TextureUploads = new List<(TextureRegion, uint, bool)>(); public ResourceUploader(GraphicsDevice device) : base(device) { @@ -45,7 +45,7 @@ namespace MoonWorks.Graphics var lengthInBytes = (uint) (Marshal.SizeOf() * data.Length); var gpuBuffer = new GpuBuffer(Device, usageFlags, lengthInBytes); - SetBufferData(gpuBuffer, 0, data, WriteOptions.Unsafe); + SetBufferData(gpuBuffer, 0, data, false); return gpuBuffer; } @@ -53,7 +53,7 @@ namespace MoonWorks.Graphics /// /// Prepares upload of data into a GpuBuffer. /// - public void SetBufferData(GpuBuffer buffer, uint bufferOffsetInElements, Span data, WriteOptions option) where T : unmanaged + public void SetBufferData(GpuBuffer buffer, uint bufferOffsetInElements, Span data, bool cycle) where T : unmanaged { uint elementSize = (uint) Marshal.SizeOf(); uint offsetInBytes = elementSize * bufferOffsetInElements; @@ -66,7 +66,7 @@ namespace MoonWorks.Graphics } var bufferCopyParams = new BufferCopy(resourceOffset, offsetInBytes, lengthInBytes); - BufferUploads.Add((buffer, bufferCopyParams, option)); + BufferUploads.Add((buffer, bufferCopyParams, cycle)); } // Textures @@ -74,7 +74,7 @@ namespace MoonWorks.Graphics public Texture CreateTexture2D(Span pixelData, uint width, uint height) where T : unmanaged { var texture = Texture.CreateTexture2D(Device, width, height, TextureFormat.R8G8B8A8, TextureUsageFlags.Sampler); - SetTextureData(texture, pixelData, WriteOptions.Unsafe); + SetTextureData(texture, pixelData, false); return texture; } @@ -164,7 +164,7 @@ namespace MoonWorks.Graphics Depth = 1 }; - SetTextureData(textureRegion, byteSpan, WriteOptions.Unsafe); + SetTextureData(textureRegion, byteSpan, false); NativeMemory.Free(byteBuffer); } @@ -187,7 +187,7 @@ namespace MoonWorks.Graphics var pixelData = ImageUtils.GetPixelDataFromBytes(compressedImageData, out var _, out var _, out var sizeInBytes); var pixelSpan = new Span((void*) pixelData, (int) sizeInBytes); - SetTextureData(textureRegion, pixelSpan, WriteOptions.Unsafe); + SetTextureData(textureRegion, pixelSpan, false); ImageUtils.FreePixelData(pixelData); } @@ -211,7 +211,7 @@ namespace MoonWorks.Graphics /// /// Prepares upload of pixel data into a TextureSlice. /// - public void SetTextureData(TextureRegion textureRegion, Span data, WriteOptions option) where T : unmanaged + public void SetTextureData(TextureRegion textureRegion, Span data, bool cycle) where T : unmanaged { var elementSize = Marshal.SizeOf(); var dataLengthInBytes = (uint) (elementSize * data.Length); @@ -222,7 +222,7 @@ namespace MoonWorks.Graphics resourceOffset = CopyTextureData(dataPtr, dataLengthInBytes, Texture.BytesPerPixel(textureRegion.TextureSlice.Texture.Format)); } - TextureUploads.Add((textureRegion, resourceOffset, option)); + TextureUploads.Add((textureRegion, resourceOffset, cycle)); } // Upload @@ -263,11 +263,11 @@ namespace MoonWorks.Graphics if (BufferTransferBuffer == null || BufferTransferBuffer.Size < bufferDataSize) { BufferTransferBuffer?.Dispose(); - BufferTransferBuffer = new TransferBuffer(Device, TransferUsage.Buffer, bufferDataSize); + BufferTransferBuffer = new TransferBuffer(Device, TransferUsage.Buffer, TransferBufferMapFlags.Write, bufferDataSize); } var dataSpan = new Span(bufferData, (int) bufferDataSize); - BufferTransferBuffer.SetData(dataSpan, TransferOptions.Cycle); + BufferTransferBuffer.SetData(dataSpan, true); } @@ -276,21 +276,21 @@ namespace MoonWorks.Graphics if (TextureTransferBuffer == null || TextureTransferBuffer.Size < textureDataSize) { TextureTransferBuffer?.Dispose(); - TextureTransferBuffer = new TransferBuffer(Device, TransferUsage.Texture, textureDataSize); + TextureTransferBuffer = new TransferBuffer(Device, TransferUsage.Texture, TransferBufferMapFlags.Write, textureDataSize); } var dataSpan = new Span(textureData, (int) textureDataSize); - TextureTransferBuffer.SetData(dataSpan, TransferOptions.Cycle); + TextureTransferBuffer.SetData(dataSpan, true); } } private void RecordUploadCommands(CommandBuffer commandBuffer) { - commandBuffer.BeginCopyPass(); + var copyPass = commandBuffer.BeginCopyPass(); foreach (var (gpuBuffer, bufferCopyParams, option) in BufferUploads) { - commandBuffer.UploadToBuffer( + copyPass.UploadToBuffer( BufferTransferBuffer, gpuBuffer, bufferCopyParams, @@ -300,7 +300,7 @@ namespace MoonWorks.Graphics foreach (var (textureRegion, offset, option) in TextureUploads) { - commandBuffer.UploadToTexture( + copyPass.UploadToTexture( TextureTransferBuffer, textureRegion, new BufferImageCopy( @@ -312,7 +312,7 @@ namespace MoonWorks.Graphics ); } - commandBuffer.EndCopyPass(); + commandBuffer.EndCopyPass(copyPass); BufferUploads.Clear(); TextureUploads.Clear(); diff --git a/src/Graphics/Resources/Fence.cs b/src/Graphics/Resources/Fence.cs index 2f61fdf..9f27c74 100644 --- a/src/Graphics/Resources/Fence.cs +++ b/src/Graphics/Resources/Fence.cs @@ -1,26 +1,25 @@ using System; -using RefreshCS; +using SDL2_gpuCS; -namespace MoonWorks.Graphics +namespace MoonWorks.Graphics; + +/// +/// Fences allow you to track the status of a submitted command buffer.
+/// You should only acquire a Fence if you will need to track the command buffer.
+/// You should make sure to call GraphicsDevice.ReleaseFence when done with a Fence to avoid memory growth.
+/// The Fence object itself is basically just a wrapper for the Refresh_Fence.
+/// The internal handle is replaced so that we can pool Fence objects to manage garbage. +///
+public class Fence : SDL_GpuResource { - /// - /// Fences allow you to track the status of a submitted command buffer.
- /// You should only acquire a Fence if you will need to track the command buffer.
- /// You should make sure to call GraphicsDevice.ReleaseFence when done with a Fence to avoid memory growth.
- /// The Fence object itself is basically just a wrapper for the Refresh_Fence.
- /// The internal handle is replaced so that we can pool Fence objects to manage garbage. - ///
- public class Fence : SDL_GpuResource + protected override Action ReleaseFunction => SDL_Gpu.SDL_GpuReleaseFence; + + internal Fence(GraphicsDevice device) : base(device) { - protected override Action ReleaseFunction => Refresh.Refresh_ReleaseFence; + } - internal Fence(GraphicsDevice device) : base(device) - { - } - - internal void SetHandle(nint handle) - { - Handle = handle; - } + internal void SetHandle(nint handle) + { + Handle = handle; } } diff --git a/src/Graphics/Resources/Sampler.cs b/src/Graphics/Resources/Sampler.cs index 2386214..a20dbc7 100644 --- a/src/Graphics/Resources/Sampler.cs +++ b/src/Graphics/Resources/Sampler.cs @@ -1,24 +1,23 @@ using System; -using RefreshCS; +using SDL2_gpuCS; -namespace MoonWorks.Graphics +namespace MoonWorks.Graphics; + +/// +/// A sampler specifies how a texture will be sampled in a shader. +/// +public class Sampler : SDL_GpuResource { - /// - /// A sampler specifies how a texture will be sampled in a shader. - /// - public class Sampler : SDL_GpuResource - { - protected override Action ReleaseFunction => Refresh.Refresh_QueueDestroySampler; + protected override Action ReleaseFunction => SDL_Gpu.SDL_GpuReleaseSampler; - public Sampler( - GraphicsDevice device, - in SamplerCreateInfo samplerCreateInfo - ) : base(device) - { - Handle = Refresh.Refresh_CreateSampler( - device.Handle, - samplerCreateInfo.ToRefreshSamplerStateCreateInfo() - ); - } + public Sampler( + GraphicsDevice device, + in SamplerCreateInfo samplerCreateInfo + ) : base(device) + { + Handle = SDL_Gpu.SDL_GpuCreateSampler( + device.Handle, + samplerCreateInfo.ToSDL() + ); } } diff --git a/src/Graphics/Resources/TransferBuffer.cs b/src/Graphics/Resources/TransferBuffer.cs index 3f2c070..a10bb01 100644 --- a/src/Graphics/Resources/TransferBuffer.cs +++ b/src/Graphics/Resources/TransferBuffer.cs @@ -1,12 +1,12 @@ using System; using System.Runtime.InteropServices; -using RefreshCS; +using SDL2_gpuCS; namespace MoonWorks.Graphics { public unsafe class TransferBuffer : SDL_GpuResource { - protected override Action ReleaseFunction => Refresh.Refresh_QueueDestroyTransferBuffer; + protected override Action ReleaseFunction => SDL_Gpu.SDL_GpuReleaseTransferBuffer; /// /// Size in bytes. @@ -23,12 +23,14 @@ namespace MoonWorks.Graphics public unsafe static TransferBuffer Create( GraphicsDevice device, TransferUsage usage, + TransferBufferMapFlags mapFlags, uint elementCount ) where T : unmanaged { return new TransferBuffer( device, usage, + mapFlags, (uint) Marshal.SizeOf() * elementCount ); } @@ -42,12 +44,14 @@ namespace MoonWorks.Graphics public TransferBuffer( GraphicsDevice device, TransferUsage usage, + TransferBufferMapFlags mapFlags, uint sizeInBytes ) : base(device) { - Handle = Refresh.Refresh_CreateTransferBuffer( + Handle = SDL_Gpu.SDL_GpuCreateTransferBuffer( device.Handle, - (Refresh.TransferUsage) usage, + (SDL_Gpu.TransferUsage) usage, + (SDL_Gpu.TransferBufferMapFlags) mapFlags, sizeInBytes ); Size = sizeInBytes; @@ -57,16 +61,16 @@ namespace MoonWorks.Graphics /// Immediately copies data from a Span to the TransferBuffer. /// Returns the length of the copy in bytes. /// - /// If setDataOption is DISCARD and this TransferBuffer was used in an Upload command, - /// that command will still use the correct data at the cost of increased memory usage. + /// If cycle is set to true and this TransferBuffer was used in an Upload command, + /// that command will still use the corret data at the cost of increased memory usage. /// - /// If setDataOption is OVERWRITE and this TransferBuffer was used in an Upload command, - /// the data will be overwritten immediately, which could cause a data race. + /// If cycle is set to false, the data will be overwritten immediately, + /// which could cause a data race. /// public unsafe uint SetData( Span data, uint bufferOffsetInBytes, - TransferOptions setDataOption + bool cycle ) where T : unmanaged { var elementSize = Marshal.SizeOf(); @@ -78,17 +82,17 @@ namespace MoonWorks.Graphics fixed (T* dataPtr = data) { - Refresh.Refresh_SetTransferData( + SDL_Gpu.SDL_GpuSetTransferData( Device.Handle, (nint) dataPtr, Handle, - new Refresh.BufferCopy + new SDL_Gpu.BufferCopy { - srcOffset = 0, - dstOffset = bufferOffsetInBytes, - size = dataLengthInBytes + SourceOffset = 0, + DestinationOffset = bufferOffsetInBytes, + Size = dataLengthInBytes }, - (Refresh.TransferOptions) setDataOption + Conversions.BoolToInt(cycle) ); } @@ -99,18 +103,18 @@ namespace MoonWorks.Graphics /// Immediately copies data from a Span to the TransferBuffer. /// Returns the length of the copy in bytes. /// - /// If setDataOption is DISCARD and this TransferBuffer was used in an Upload command, - /// that command will still use the correct data at the cost of increased memory usage. + /// If cycle is set to true and this TransferBuffer was used in an Upload command, + /// that command will still use the corret data at the cost of increased memory usage. /// - /// If setDataOption is OVERWRITE and this TransferBuffer was used in an Upload command, - /// the data will be overwritten immediately, which could cause a data race. + /// If cycle is set to false, the data will be overwritten immediately, + /// which could cause a data race. /// public unsafe uint SetData( Span data, - TransferOptions setDataOption + bool cycle ) where T : unmanaged { - return SetData(data, 0, setDataOption); + return SetData(data, 0, cycle); } /// @@ -130,15 +134,15 @@ namespace MoonWorks.Graphics fixed (T* dataPtr = data) { - Refresh.Refresh_GetTransferData( + SDL_Gpu.SDL_GpuGetTransferData( Device.Handle, Handle, (nint) dataPtr, - new Refresh.BufferCopy + new SDL_Gpu.BufferCopy { - srcOffset = bufferOffsetInBytes, - dstOffset = 0, - size = dataLengthInBytes + SourceOffset = bufferOffsetInBytes, + DestinationOffset = 0, + Size = dataLengthInBytes } ); } diff --git a/src/Graphics/SDL_GpuTypes.cs b/src/Graphics/SDL_GpuTypes.cs index d5ac12d..4511226 100644 --- a/src/Graphics/SDL_GpuTypes.cs +++ b/src/Graphics/SDL_GpuTypes.cs @@ -788,7 +788,7 @@ public struct BufferCopy Size = size; } - public SDL_Gpu.BufferCopy ToRefresh() + public SDL_Gpu.BufferCopy ToSDL() { return new SDL_Gpu.BufferCopy { @@ -811,7 +811,7 @@ public readonly record struct BufferImageCopy( uint BufferStride, uint BufferImageHeight ) { - public SDL_Gpu.BufferImageCopy ToRefresh() + public SDL_Gpu.BufferImageCopy ToSDL() { return new SDL_Gpu.BufferImageCopy { diff --git a/src/Logger.cs b/src/Logger.cs index 76821e7..2225e59 100644 --- a/src/Logger.cs +++ b/src/Logger.cs @@ -1,5 +1,4 @@ using System; -using RefreshCS; namespace MoonWorks { @@ -9,19 +8,6 @@ namespace MoonWorks public static Action LogWarn = LogWarnDefault; public static Action LogError = LogErrorDefault; - private static RefreshCS.Refresh.Refresh_LogFunc LogInfoFunc = RefreshLogInfo; - private static RefreshCS.Refresh.Refresh_LogFunc LogWarnFunc = RefreshLogWarn; - private static RefreshCS.Refresh.Refresh_LogFunc LogErrorFunc = RefreshLogError; - - internal static void Initialize() - { - Refresh.Refresh_HookLogFunctions( - LogInfoFunc, - LogWarnFunc, - LogErrorFunc - ); - } - private static void LogInfoDefault(string str) { Console.ForegroundColor = ConsoleColor.Green; diff --git a/src/WindowCreateInfo.cs b/src/WindowCreateInfo.cs index 4439585..cf141d4 100644 --- a/src/WindowCreateInfo.cs +++ b/src/WindowCreateInfo.cs @@ -22,9 +22,13 @@ /// public ScreenMode ScreenMode; /// + /// Specifies the swapchain composition. Use SDR unless you know what you're doing. + /// + public Graphics.SwapchainComposition SwapchainComposition; + /// /// Specifies the presentation mode for the window. Roughly equivalent to V-Sync. /// - public PresentMode PresentMode; + public Graphics.PresentMode PresentMode; /// /// Whether the window can be resized using the operating system's window dragging feature. /// @@ -39,7 +43,7 @@ uint windowWidth, uint windowHeight, ScreenMode screenMode, - PresentMode presentMode, + Graphics.PresentMode presentMode, bool systemResizable = false, bool startMaximized = false ) {