Skip to content

Instantly share code, notes, and snippets.

@ibd1279
Created October 25, 2021 19:59
Show Gist options
  • Save ibd1279/ba12f012b20a839f8aca3afa0cfe64bc to your computer and use it in GitHub Desktop.
Save ibd1279/ba12f012b20a839f8aca3afa0cfe64bc to your computer and use it in GitHub Desktop.
Explaining the idea of pushing a Vulkan command queue onto a dedicated thread via goroutine.
// CommandPoolThread
type CommandPoolThreadRequest struct {
backChan chan<- CommandPoolThreadResponse
Alloc vk.CommandBufferAllocateInfo
Buffers []vk.CommandBuffer
Commands func(int, vk.CommandBuffer) error
}
type CommandPoolThreadResponse struct {
Alloc vk.Result
Commands []error
Buffers []vk.CommandBuffer
}
type CommandPoolThread struct {
sfChan chan<- chan<- struct{}
rChan chan<- CommandPoolThreadRequest
}
func NewCommandPoolThread(device vk.Device, createInfo *vk.CommandPoolCreateInfo, allocator *vk.AllocationCallbacks) (*CommandPoolThread, vk.Result) {
signalFinishedChan := make(chan chan<- struct{}, 0)
requestChan := make(chan CommandPoolThreadRequest, 0)
createResultChan := make(chan vk.Result, 0)
defer close(createResultChan)
go func() {
defer close(signalFinishedChan)
defer close(requestChan)
runtime.LockOSThread()
defer runtime.UnlockOSThread()
var cmdPool vk.CommandPool
ret := vk.CreateCommandPool(
device,
createInfo,
allocator,
&cmdPool,
)
createResultChan <- ret
var loop bool
if ret == vk.Success {
loop = true
}
var finishedChan chan<- struct{}
for loop {
select {
case finishedChan = <-signalFinishedChan:
loop = false
case request := <-requestChan:
// Do something.
// Free buffers in the request.
if len(request.Buffers) > 0 {
vk.FreeCommandBuffers(
device,
cmdPool,
uint32(len(request.Buffers)),
request.Buffers,
)
}
// Allocate new buffers.
if request.Alloc.CommandBufferCount > 0 {
response := CommandPoolThreadResponse{}
response.Buffers = make(
[]vk.CommandBuffer,
request.Alloc.CommandBufferCount,
)
request.Alloc.CommandPool = cmdPool
response.Alloc = vk.AllocateCommandBuffers(
device,
&request.Alloc,
response.Buffers,
)
if response.Alloc != vk.Success {
request.backChan <- response
} else {
response.Commands = make([]error, len(response.Buffers))
for k, cmdBuffer := range response.Buffers {
response.Commands[k] = request.Commands(k, cmdBuffer)
}
request.backChan <- response
}
}
// Send the response back.
request.backChan <- CommandPoolThreadResponse{}
close(request.backChan)
}
}
if ret == vk.Success {
vk.DestroyCommandPool(device, cmdPool, allocator)
}
if finishedChan != nil {
finishedChan <- struct{}{}
close(finishedChan)
}
}()
ret := <-createResultChan
var cpt *CommandPoolThread
if ret == vk.Success {
cpt = &CommandPoolThread{
sfChan: signalFinishedChan,
rChan: requestChan,
}
}
return cpt, ret
}
func (cpt *CommandPoolThread) Destroy() <-chan struct{} {
c := make(chan struct{}, 0)
cpt.sfChan <- c
return c
}
func (cpt *CommandPoolThread) Submit(req CommandPoolThreadRequest) <-chan CommandPoolThreadResponse {
c := make(chan CommandPoolThreadResponse, 1)
req.backChan = c
cpt.rChan <- req
return c
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment