-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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