swift: Move texture uploads into copy pass

This commit is contained in:
2025-06-12 14:17:31 +10:00
parent b0ee1ee4c3
commit 9781c2f01f

View File

@@ -24,7 +24,13 @@ public struct NeHeCopyPass: ~Copyable
// Free transfer buffers // Free transfer buffers
for copy in self.copies.reversed() for copy in self.copies.reversed()
{ {
SDL_ReleaseGPUTransferBuffer(self.device, copy.xferBuffer) switch copy
{
case .buffer(_, let xferBuffer, _):
SDL_ReleaseGPUTransferBuffer(self.device, xferBuffer)
case .texture(_, let xferBuffer, _, _):
SDL_ReleaseGPUTransferBuffer(self.device, xferBuffer)
}
} }
} }
@@ -39,16 +45,37 @@ public struct NeHeCopyPass: ~Copyable
// Begin the copy pass // Begin the copy pass
let pass = SDL_BeginGPUCopyPass(cmd) let pass = SDL_BeginGPUCopyPass(cmd)
// Upload data into the GPU buffer(s) // Upload buffers and textures into the GPU buffer(s)
for copy in self.copies for copy in self.copies
{ {
var vtxSource = SDL_GPUTransferBufferLocation(transfer_buffer: copy.xferBuffer, offset: 0) switch copy
var vtxDestination = SDL_GPUBufferRegion(buffer: copy.buffer, offset: 0, size: copy.size) {
SDL_UploadToGPUBuffer(pass, &vtxSource, &vtxDestination, false) case .buffer(let buffer, let xferBuffer, let size):
var source = SDL_GPUTransferBufferLocation(transfer_buffer: xferBuffer, offset: 0)
var destination = SDL_GPUBufferRegion(buffer: buffer, offset: 0, size: size)
SDL_UploadToGPUBuffer(pass, &source, &destination, false)
case .texture(let texture, let xferBuffer, let size, _):
var source = SDL_GPUTextureTransferInfo()
source.transfer_buffer = xferBuffer
source.offset = 0
var destination = SDL_GPUTextureRegion()
destination.texture = texture
destination.w = size.width
destination.h = size.height
destination.d = 1 // info.layer_count_or_depth
SDL_UploadToGPUTexture(pass, &source, &destination, false)
}
} }
// End & submit the copy pass // End the copy pass
SDL_EndGPUCopyPass(pass) SDL_EndGPUCopyPass(pass)
// Generate mipmaps if needed
for case .texture(let texture, _, _, let genMipmaps) in self.copies where genMipmaps
{
SDL_GenerateMipmapsForGPUTexture(cmd, texture)
}
SDL_SubmitGPUCommandBuffer(cmd) SDL_SubmitGPUCommandBuffer(cmd)
} }
} }
@@ -91,7 +118,7 @@ public extension NeHeCopyPass
} }
SDL_UnmapGPUTransferBuffer(self.device, xferBuffer) SDL_UnmapGPUTransferBuffer(self.device, xferBuffer)
self.copies.append(.init( self.copies.append(.buffer(
buffer: buffer, buffer: buffer,
xferBuffer: xferBuffer, xferBuffer: xferBuffer,
size: size)) size: size))
@@ -199,7 +226,7 @@ public extension NeHeCopyPass
fileprivate extension NeHeCopyPass fileprivate extension NeHeCopyPass
{ {
func createTextureFrom(pixels: UnsafeRawBufferPointer, mutating func createTextureFrom(pixels: UnsafeRawBufferPointer,
createInfo info: inout SDL_GPUTextureCreateInfo, genMipmaps: Bool) createInfo info: inout SDL_GPUTextureCreateInfo, genMipmaps: Bool)
throws(NeHeError) -> OpaquePointer throws(NeHeError) -> OpaquePointer
{ {
@@ -208,7 +235,7 @@ fileprivate extension NeHeCopyPass
throw .sdlError("SDL_CreateGPUTexture", String(cString: SDL_GetError())) throw .sdlError("SDL_CreateGPUTexture", String(cString: SDL_GetError()))
} }
// Create and copy image data to a transfer buffer // Create a transfer buffer to hold the pixel data
var xferInfo = SDL_GPUTransferBufferCreateInfo( var xferInfo = SDL_GPUTransferBufferCreateInfo(
usage: SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD, usage: SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD,
size: UInt32(pixels.count), size: UInt32(pixels.count),
@@ -218,10 +245,11 @@ fileprivate extension NeHeCopyPass
SDL_ReleaseGPUTexture(self.device, texture) SDL_ReleaseGPUTexture(self.device, texture)
throw .sdlError("SDL_CreateGPUTransferBuffer", String(cString: SDL_GetError())) throw .sdlError("SDL_CreateGPUTransferBuffer", String(cString: SDL_GetError()))
} }
defer { SDL_ReleaseGPUTransferBuffer(self.device, xferBuffer) }
// Copy the image pixel data to a transfer buffer
guard let map = SDL_MapGPUTransferBuffer(self.device, xferBuffer, false) else guard let map = SDL_MapGPUTransferBuffer(self.device, xferBuffer, false) else
{ {
SDL_ReleaseGPUTransferBuffer(self.device, xferBuffer)
SDL_ReleaseGPUTexture(self.device, texture) SDL_ReleaseGPUTexture(self.device, texture)
throw .sdlError("SDL_MapGPUTransferBuffer", String(cString: SDL_GetError())) throw .sdlError("SDL_MapGPUTransferBuffer", String(cString: SDL_GetError()))
} }
@@ -230,41 +258,20 @@ fileprivate extension NeHeCopyPass
count: pixels.count) count: pixels.count)
SDL_UnmapGPUTransferBuffer(self.device, xferBuffer) SDL_UnmapGPUTransferBuffer(self.device, xferBuffer)
// Upload the transfer data to the GPU resources self.copies.append(.texture(
guard let cmd = SDL_AcquireGPUCommandBuffer(self.device) else texture: texture,
{ xferBuffer: xferBuffer,
SDL_ReleaseGPUTexture(self.device, texture) size: .init(info.width, info.height),
throw .sdlError("SDL_AcquireGPUCommandBuffer", String(cString: SDL_GetError())) genMipmaps: genMipmaps))
}
let pass = SDL_BeginGPUCopyPass(cmd)
var source = SDL_GPUTextureTransferInfo()
source.transfer_buffer = xferBuffer
source.offset = 0
var destination = SDL_GPUTextureRegion()
destination.texture = texture
destination.w = info.width
destination.h = info.height
destination.d = info.layer_count_or_depth
SDL_UploadToGPUTexture(pass, &source, &destination, false)
SDL_EndGPUCopyPass(pass)
if genMipmaps
{
SDL_GenerateMipmapsForGPUTexture(cmd, texture)
}
SDL_SubmitGPUCommandBuffer(cmd)
return texture return texture
} }
} }
fileprivate extension NeHeCopyPass fileprivate extension NeHeCopyPass
{ {
struct Copy enum Copy
{ {
var buffer: OpaquePointer case buffer(buffer: OpaquePointer, xferBuffer: OpaquePointer, size: UInt32)
var xferBuffer: OpaquePointer case texture(texture: OpaquePointer, xferBuffer: OpaquePointer, size: Size<UInt32>, genMipmaps: Bool)
var size: UInt32
} }
} }