diff --git a/lib/RefreshCS b/lib/RefreshCS index 029f191..8f42783 160000 --- a/lib/RefreshCS +++ b/lib/RefreshCS @@ -1 +1 @@ -Subproject commit 029f19196a94e13b8ed98d10f47a701221951f2f +Subproject commit 8f42783fd15cfea57cfae421fd6ab36070df9946 diff --git a/src/Graphics/Font/TextBatch.cs b/src/Graphics/Font/TextBatch.cs index e4286d6..8e20c6e 100644 --- a/src/Graphics/Font/TextBatch.cs +++ b/src/Graphics/Font/TextBatch.cs @@ -35,7 +35,7 @@ namespace MoonWorks.Graphics.Font VertexBuffer = GpuBuffer.Create(GraphicsDevice, BufferUsageFlags.Vertex, INITIAL_VERTEX_COUNT); IndexBuffer = GpuBuffer.Create(GraphicsDevice, BufferUsageFlags.Index, INITIAL_INDEX_COUNT); - TransferBuffer = TransferBuffer.Create(GraphicsDevice, VertexBuffer.Size + IndexBuffer.Size); + TransferBuffer = TransferBuffer.Create(GraphicsDevice, TransferUsage.Buffer, VertexBuffer.Size + IndexBuffer.Size); } // Call this to initialize or reset the batch. @@ -119,7 +119,7 @@ namespace MoonWorks.Graphics.Font if (newTransferBufferNeeded) { TransferBuffer.Dispose(); - TransferBuffer = new TransferBuffer(GraphicsDevice, VertexBuffer.Size + IndexBuffer.Size); + TransferBuffer = new TransferBuffer(GraphicsDevice, TransferUsage.Buffer, VertexBuffer.Size + IndexBuffer.Size); } if (vertexDataLengthInBytes > 0 && indexDataLengthInBytes > 0) diff --git a/src/Graphics/RefreshEnums.cs b/src/Graphics/RefreshEnums.cs index eeb6eaa..0139690 100644 --- a/src/Graphics/RefreshEnums.cs +++ b/src/Graphics/RefreshEnums.cs @@ -297,6 +297,12 @@ namespace MoonWorks.Graphics IntOpaqueWhite } + public enum TransferUsage + { + Buffer, + Texture + } + public enum TransferOptions { Cycle, diff --git a/src/Graphics/ResourceUploader.cs b/src/Graphics/ResourceUploader.cs index 13d0b73..c56fdac 100644 --- a/src/Graphics/ResourceUploader.cs +++ b/src/Graphics/ResourceUploader.cs @@ -15,18 +15,24 @@ namespace MoonWorks.Graphics /// public unsafe class ResourceUploader : GraphicsResource { - TransferBuffer TransferBuffer; + TransferBuffer BufferTransferBuffer; + TransferBuffer TextureTransferBuffer; - byte* data; - uint dataOffset = 0; - uint dataSize = 1024; + byte* bufferData; + uint bufferDataOffset = 0; + uint bufferDataSize = 1024; + + byte* textureData; + 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)>(); public ResourceUploader(GraphicsDevice device) : base(device) { - data = (byte*) NativeMemory.Alloc(dataSize); + bufferData = (byte*) NativeMemory.Alloc(bufferDataSize); + textureData = (byte*) NativeMemory.Alloc(textureDataSize); } // Buffers @@ -56,7 +62,7 @@ namespace MoonWorks.Graphics uint resourceOffset; fixed (void* spanPtr = data) { - resourceOffset = CopyData(spanPtr, lengthInBytes); + resourceOffset = CopyBufferData(spanPtr, lengthInBytes); } var bufferCopyParams = new BufferCopy(resourceOffset, offsetInBytes, lengthInBytes); @@ -213,7 +219,7 @@ namespace MoonWorks.Graphics uint resourceOffset; fixed (T* dataPtr = data) { - resourceOffset = CopyDataAligned(dataPtr, dataLengthInBytes, Texture.TexelSize(textureRegion.TextureSlice.Texture.Format)); + resourceOffset = CopyTextureData(dataPtr, dataLengthInBytes, Texture.TexelSize(textureRegion.TextureSlice.Texture.Format)); } TextureUploads.Add((textureRegion, resourceOffset, option)); @@ -252,14 +258,30 @@ namespace MoonWorks.Graphics private void CopyToTransferBuffer() { - if (TransferBuffer == null || TransferBuffer.Size < dataSize) + if (BufferUploads.Count > 0) { - TransferBuffer?.Dispose(); - TransferBuffer = new TransferBuffer(Device, dataSize); + if (BufferTransferBuffer == null || BufferTransferBuffer.Size < bufferDataSize) + { + BufferTransferBuffer?.Dispose(); + BufferTransferBuffer = new TransferBuffer(Device, TransferUsage.Buffer, bufferDataSize); + } + + var dataSpan = new Span(bufferData, (int) bufferDataSize); + BufferTransferBuffer.SetData(dataSpan, TransferOptions.Cycle); } - var dataSpan = new Span(data, (int) dataSize); - TransferBuffer.SetData(dataSpan, TransferOptions.Cycle); + + if (TextureUploads.Count > 0) + { + if (TextureTransferBuffer == null || TextureTransferBuffer.Size < textureDataSize) + { + TextureTransferBuffer?.Dispose(); + TextureTransferBuffer = new TransferBuffer(Device, TransferUsage.Texture, textureDataSize); + } + + var dataSpan = new Span(textureData, (int) textureDataSize); + TextureTransferBuffer.SetData(dataSpan, TransferOptions.Cycle); + } } private void RecordUploadCommands(CommandBuffer commandBuffer) @@ -269,7 +291,7 @@ namespace MoonWorks.Graphics foreach (var (gpuBuffer, bufferCopyParams, option) in BufferUploads) { commandBuffer.UploadToBuffer( - TransferBuffer, + BufferTransferBuffer, gpuBuffer, bufferCopyParams, option @@ -279,7 +301,7 @@ namespace MoonWorks.Graphics foreach (var (textureRegion, offset, option) in TextureUploads) { commandBuffer.UploadToTexture( - TransferBuffer, + TextureTransferBuffer, textureRegion, new BufferImageCopy( offset, @@ -294,29 +316,41 @@ namespace MoonWorks.Graphics BufferUploads.Clear(); TextureUploads.Clear(); - dataOffset = 0; + bufferDataOffset = 0; } - private uint CopyData(void* ptr, uint lengthInBytes) + private uint CopyBufferData(void* ptr, uint lengthInBytes) { - if (dataOffset + lengthInBytes >= dataSize) + if (bufferDataOffset + lengthInBytes >= bufferDataSize) { - dataSize = dataOffset + lengthInBytes; - data = (byte*) NativeMemory.Realloc(data, dataSize); + bufferDataSize = bufferDataOffset + lengthInBytes; + bufferData = (byte*) NativeMemory.Realloc(bufferData, bufferDataSize); } - var resourceOffset = dataOffset; + var resourceOffset = bufferDataOffset; - NativeMemory.Copy(ptr, data + dataOffset, lengthInBytes); - dataOffset += lengthInBytes; + NativeMemory.Copy(ptr, bufferData + bufferDataOffset, lengthInBytes); + bufferDataOffset += lengthInBytes; return resourceOffset; } - private uint CopyDataAligned(void* ptr, uint lengthInBytes, uint alignment) + private uint CopyTextureData(void* ptr, uint lengthInBytes, uint alignment) { - dataOffset = RoundToAlignment(dataOffset, alignment); - return CopyData(ptr, lengthInBytes); + textureDataOffset = RoundToAlignment(textureDataOffset, alignment); + + if (textureDataOffset + lengthInBytes >= textureDataSize) + { + textureDataSize = textureDataOffset + lengthInBytes; + textureData = (byte*) NativeMemory.Realloc(textureData, textureDataSize); + } + + var resourceOffset = textureDataOffset; + + NativeMemory.Copy(ptr, textureData + textureDataOffset, lengthInBytes); + textureDataOffset += lengthInBytes; + + return resourceOffset; } private uint RoundToAlignment(uint value, uint alignment) @@ -335,10 +369,11 @@ namespace MoonWorks.Graphics { if (disposing) { - TransferBuffer?.Dispose(); + BufferTransferBuffer?.Dispose(); + TextureTransferBuffer?.Dispose(); } - NativeMemory.Free(data); + NativeMemory.Free(bufferData); } base.Dispose(disposing); } diff --git a/src/Graphics/Resources/TransferBuffer.cs b/src/Graphics/Resources/TransferBuffer.cs index 54398d3..a58d3c3 100644 --- a/src/Graphics/Resources/TransferBuffer.cs +++ b/src/Graphics/Resources/TransferBuffer.cs @@ -22,11 +22,13 @@ namespace MoonWorks.Graphics /// public unsafe static TransferBuffer Create( GraphicsDevice device, + TransferUsage usage, uint elementCount ) where T : unmanaged { return new TransferBuffer( device, + usage, (uint) Marshal.SizeOf() * elementCount ); } @@ -36,13 +38,16 @@ namespace MoonWorks.Graphics /// /// An initialized GraphicsDevice. /// The length of the buffer. Cannot be resized. + /// Whether this will be used to upload buffers or textures. public TransferBuffer( GraphicsDevice device, + TransferUsage usage, uint sizeInBytes ) : base(device) { Handle = Refresh.Refresh_CreateTransferBuffer( device.Handle, + (Refresh.TransferUsage) usage, sizeInBytes ); Size = sizeInBytes; diff --git a/src/Video/VideoPlayer.cs b/src/Video/VideoPlayer.cs index ea2d0f1..ffebace 100644 --- a/src/Video/VideoPlayer.cs +++ b/src/Video/VideoPlayer.cs @@ -241,7 +241,7 @@ namespace MoonWorks.Video if (TransferBuffer == null || TransferBuffer.Size < ySpan.Length + uSpan.Length + vSpan.Length) { TransferBuffer?.Dispose(); - TransferBuffer = new TransferBuffer(Device, (uint) (ySpan.Length + uSpan.Length + vSpan.Length)); + TransferBuffer = new TransferBuffer(Device, TransferUsage.Texture, (uint) (ySpan.Length + uSpan.Length + vSpan.Length)); } TransferBuffer.SetData(ySpan, 0, TransferOptions.Cycle); TransferBuffer.SetData(uSpan, (uint) ySpan.Length, TransferOptions.Overwrite);