TransferUsage change

what_if_no_video_threads
cosmonaut 2024-03-08 15:29:44 -08:00
parent 9195e445b2
commit 69d2c9cc31
6 changed files with 77 additions and 31 deletions

@ -1 +1 @@
Subproject commit 029f19196a94e13b8ed98d10f47a701221951f2f Subproject commit 8f42783fd15cfea57cfae421fd6ab36070df9946

View File

@ -35,7 +35,7 @@ namespace MoonWorks.Graphics.Font
VertexBuffer = GpuBuffer.Create<Vertex>(GraphicsDevice, BufferUsageFlags.Vertex, INITIAL_VERTEX_COUNT); VertexBuffer = GpuBuffer.Create<Vertex>(GraphicsDevice, BufferUsageFlags.Vertex, INITIAL_VERTEX_COUNT);
IndexBuffer = GpuBuffer.Create<uint>(GraphicsDevice, BufferUsageFlags.Index, INITIAL_INDEX_COUNT); IndexBuffer = GpuBuffer.Create<uint>(GraphicsDevice, BufferUsageFlags.Index, INITIAL_INDEX_COUNT);
TransferBuffer = TransferBuffer.Create<byte>(GraphicsDevice, VertexBuffer.Size + IndexBuffer.Size); TransferBuffer = TransferBuffer.Create<byte>(GraphicsDevice, TransferUsage.Buffer, VertexBuffer.Size + IndexBuffer.Size);
} }
// Call this to initialize or reset the batch. // Call this to initialize or reset the batch.
@ -119,7 +119,7 @@ namespace MoonWorks.Graphics.Font
if (newTransferBufferNeeded) if (newTransferBufferNeeded)
{ {
TransferBuffer.Dispose(); 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) if (vertexDataLengthInBytes > 0 && indexDataLengthInBytes > 0)

View File

@ -297,6 +297,12 @@ namespace MoonWorks.Graphics
IntOpaqueWhite IntOpaqueWhite
} }
public enum TransferUsage
{
Buffer,
Texture
}
public enum TransferOptions public enum TransferOptions
{ {
Cycle, Cycle,

View File

@ -15,18 +15,24 @@ namespace MoonWorks.Graphics
/// </summary> /// </summary>
public unsafe class ResourceUploader : GraphicsResource public unsafe class ResourceUploader : GraphicsResource
{ {
TransferBuffer TransferBuffer; TransferBuffer BufferTransferBuffer;
TransferBuffer TextureTransferBuffer;
byte* data; byte* bufferData;
uint dataOffset = 0; uint bufferDataOffset = 0;
uint dataSize = 1024; uint bufferDataSize = 1024;
byte* textureData;
uint textureDataOffset = 0;
uint textureDataSize = 1024;
List<(GpuBuffer, BufferCopy, WriteOptions)> BufferUploads = new List<(GpuBuffer, BufferCopy, WriteOptions)>(); List<(GpuBuffer, BufferCopy, WriteOptions)> BufferUploads = new List<(GpuBuffer, BufferCopy, WriteOptions)>();
List<(TextureRegion, uint, WriteOptions)> TextureUploads = new List<(TextureRegion, uint, WriteOptions)>(); List<(TextureRegion, uint, WriteOptions)> TextureUploads = new List<(TextureRegion, uint, WriteOptions)>();
public ResourceUploader(GraphicsDevice device) : base(device) public ResourceUploader(GraphicsDevice device) : base(device)
{ {
data = (byte*) NativeMemory.Alloc(dataSize); bufferData = (byte*) NativeMemory.Alloc(bufferDataSize);
textureData = (byte*) NativeMemory.Alloc(textureDataSize);
} }
// Buffers // Buffers
@ -56,7 +62,7 @@ namespace MoonWorks.Graphics
uint resourceOffset; uint resourceOffset;
fixed (void* spanPtr = data) fixed (void* spanPtr = data)
{ {
resourceOffset = CopyData(spanPtr, lengthInBytes); resourceOffset = CopyBufferData(spanPtr, lengthInBytes);
} }
var bufferCopyParams = new BufferCopy(resourceOffset, offsetInBytes, lengthInBytes); var bufferCopyParams = new BufferCopy(resourceOffset, offsetInBytes, lengthInBytes);
@ -213,7 +219,7 @@ namespace MoonWorks.Graphics
uint resourceOffset; uint resourceOffset;
fixed (T* dataPtr = data) 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)); TextureUploads.Add((textureRegion, resourceOffset, option));
@ -252,14 +258,30 @@ namespace MoonWorks.Graphics
private void CopyToTransferBuffer() private void CopyToTransferBuffer()
{ {
if (TransferBuffer == null || TransferBuffer.Size < dataSize) if (BufferUploads.Count > 0)
{ {
TransferBuffer?.Dispose(); if (BufferTransferBuffer == null || BufferTransferBuffer.Size < bufferDataSize)
TransferBuffer = new TransferBuffer(Device, dataSize); {
BufferTransferBuffer?.Dispose();
BufferTransferBuffer = new TransferBuffer(Device, TransferUsage.Buffer, bufferDataSize);
} }
var dataSpan = new Span<byte>(data, (int) dataSize); var dataSpan = new Span<byte>(bufferData, (int) bufferDataSize);
TransferBuffer.SetData(dataSpan, TransferOptions.Cycle); BufferTransferBuffer.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<byte>(textureData, (int) textureDataSize);
TextureTransferBuffer.SetData(dataSpan, TransferOptions.Cycle);
}
} }
private void RecordUploadCommands(CommandBuffer commandBuffer) private void RecordUploadCommands(CommandBuffer commandBuffer)
@ -269,7 +291,7 @@ namespace MoonWorks.Graphics
foreach (var (gpuBuffer, bufferCopyParams, option) in BufferUploads) foreach (var (gpuBuffer, bufferCopyParams, option) in BufferUploads)
{ {
commandBuffer.UploadToBuffer( commandBuffer.UploadToBuffer(
TransferBuffer, BufferTransferBuffer,
gpuBuffer, gpuBuffer,
bufferCopyParams, bufferCopyParams,
option option
@ -279,7 +301,7 @@ namespace MoonWorks.Graphics
foreach (var (textureRegion, offset, option) in TextureUploads) foreach (var (textureRegion, offset, option) in TextureUploads)
{ {
commandBuffer.UploadToTexture( commandBuffer.UploadToTexture(
TransferBuffer, TextureTransferBuffer,
textureRegion, textureRegion,
new BufferImageCopy( new BufferImageCopy(
offset, offset,
@ -294,29 +316,41 @@ namespace MoonWorks.Graphics
BufferUploads.Clear(); BufferUploads.Clear();
TextureUploads.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; bufferDataSize = bufferDataOffset + lengthInBytes;
data = (byte*) NativeMemory.Realloc(data, dataSize); bufferData = (byte*) NativeMemory.Realloc(bufferData, bufferDataSize);
} }
var resourceOffset = dataOffset; var resourceOffset = bufferDataOffset;
NativeMemory.Copy(ptr, data + dataOffset, lengthInBytes); NativeMemory.Copy(ptr, bufferData + bufferDataOffset, lengthInBytes);
dataOffset += lengthInBytes; bufferDataOffset += lengthInBytes;
return resourceOffset; return resourceOffset;
} }
private uint CopyDataAligned(void* ptr, uint lengthInBytes, uint alignment) private uint CopyTextureData(void* ptr, uint lengthInBytes, uint alignment)
{ {
dataOffset = RoundToAlignment(dataOffset, alignment); textureDataOffset = RoundToAlignment(textureDataOffset, alignment);
return CopyData(ptr, lengthInBytes);
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) private uint RoundToAlignment(uint value, uint alignment)
@ -335,10 +369,11 @@ namespace MoonWorks.Graphics
{ {
if (disposing) if (disposing)
{ {
TransferBuffer?.Dispose(); BufferTransferBuffer?.Dispose();
TextureTransferBuffer?.Dispose();
} }
NativeMemory.Free(data); NativeMemory.Free(bufferData);
} }
base.Dispose(disposing); base.Dispose(disposing);
} }

View File

@ -22,11 +22,13 @@ namespace MoonWorks.Graphics
/// <returns></returns> /// <returns></returns>
public unsafe static TransferBuffer Create<T>( public unsafe static TransferBuffer Create<T>(
GraphicsDevice device, GraphicsDevice device,
TransferUsage usage,
uint elementCount uint elementCount
) where T : unmanaged ) where T : unmanaged
{ {
return new TransferBuffer( return new TransferBuffer(
device, device,
usage,
(uint) Marshal.SizeOf<T>() * elementCount (uint) Marshal.SizeOf<T>() * elementCount
); );
} }
@ -36,13 +38,16 @@ namespace MoonWorks.Graphics
/// </summary> /// </summary>
/// <param name="device">An initialized GraphicsDevice.</param> /// <param name="device">An initialized GraphicsDevice.</param>
/// <param name="sizeInBytes">The length of the buffer. Cannot be resized.</param> /// <param name="sizeInBytes">The length of the buffer. Cannot be resized.</param>
/// <param name="usage">Whether this will be used to upload buffers or textures.</param>
public TransferBuffer( public TransferBuffer(
GraphicsDevice device, GraphicsDevice device,
TransferUsage usage,
uint sizeInBytes uint sizeInBytes
) : base(device) ) : base(device)
{ {
Handle = Refresh.Refresh_CreateTransferBuffer( Handle = Refresh.Refresh_CreateTransferBuffer(
device.Handle, device.Handle,
(Refresh.TransferUsage) usage,
sizeInBytes sizeInBytes
); );
Size = sizeInBytes; Size = sizeInBytes;

View File

@ -241,7 +241,7 @@ namespace MoonWorks.Video
if (TransferBuffer == null || TransferBuffer.Size < ySpan.Length + uSpan.Length + vSpan.Length) if (TransferBuffer == null || TransferBuffer.Size < ySpan.Length + uSpan.Length + vSpan.Length)
{ {
TransferBuffer?.Dispose(); 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(ySpan, 0, TransferOptions.Cycle);
TransferBuffer.SetData(uSpan, (uint) ySpan.Length, TransferOptions.Overwrite); TransferBuffer.SetData(uSpan, (uint) ySpan.Length, TransferOptions.Overwrite);