Created
December 10, 2018 01:37
-
-
Save mlfarrell/1e7f771673619cc2c83773577bde5fc6 to your computer and use it in GitHub Desktop.
Vulkan async resource handles
This file contains hidden or 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
struct VulkanAsyncResourceHandle | |
{ | |
union | |
{ | |
VkFence fence; | |
VkBuffer buffer; | |
VkImage image; | |
VkSampler sampler; | |
VkCommandBuffer commandBuffer; | |
}; | |
union | |
{ | |
VkImageView imageView; | |
VkCommandPool commandPool; | |
}; | |
VulkanMemoryManager::Suballocation alloc; | |
VkDevice device; | |
enum Type | |
{ | |
FENCE, BUFFER, IMAGE, SAMPLER, COMMAND_BUFFER | |
}; | |
VulkanAsyncResourceHandle(VulkanAsyncResourceMonitor *monitor, Type type, VkDevice device); | |
static VulkanAsyncResourceHandle *newBuffer(VulkanAsyncResourceMonitor *monitor, VkDevice device, VkBuffer buffer, VulkanMemoryManager::Suballocation alloc); | |
static VulkanAsyncResourceHandle *newImage(VulkanAsyncResourceMonitor *monitor, VkDevice device, VkImage image, VkImageView imageView, VulkanMemoryManager::Suballocation alloc); | |
static VulkanAsyncResourceHandle *newSampler(VulkanAsyncResourceMonitor *monitor, VkDevice device, VkSampler sampler); | |
static VulkanAsyncResourceHandle *newCommandBuffer(VulkanAsyncResourceMonitor *monitor, VkDevice device, VkCommandBuffer commandBuffer, VkCommandPool pool); | |
static VulkanAsyncResourceHandle *newFence(VulkanAsyncResourceMonitor *monitor, VkDevice device, VkFence fence); | |
void retain(); | |
bool release(); | |
void dealloc(); | |
VulkanAsyncResourceMonitor *monitor; | |
Type type; | |
std::atomic_int refCount; | |
}; | |
void VulkanAsyncResourceHandle::dealloc() | |
{ | |
switch(type) | |
{ | |
case FENCE: | |
vkDestroyFence(device, fence, nullptr); | |
break; | |
case BUFFER: | |
vkDestroyBuffer(device, buffer, nullptr); | |
break; | |
case IMAGE: | |
vkDestroyImage(device, image, nullptr); | |
if(imageView) | |
vkDestroyImageView(device, imageView, nullptr); | |
break; | |
case SAMPLER: | |
vkDestroySampler(device, sampler, nullptr); | |
break; | |
case COMMAND_BUFFER: | |
vkFreeCommandBuffers(device, commandPool, 1, &commandBuffer); //you may need to schedule this out to the alloc'ing thread | |
break; | |
} | |
if(alloc) | |
{ | |
monitor->memoryManager->free(alloc); | |
} | |
} | |
////////////// Usage examples //////////////////////////////////////////////////////////////////////////////// | |
//Creating resource handles/////////////////////////////////////////////////////////////////////////////////////// | |
auto fenceHandle = VulkanAsyncResourceHandle::newFence(resourceMonitor, device, transferFence); | |
auto cmdBufHandle = VulkanAsyncResourceHandle::newCommandBuffer(resourceMonitor, device, currentTransferCommandBuffer.first, transferCommandPool); | |
VulkanAsyncResourceCollection transferResources(resourceMonitor, fenceHandle, { | |
cmdBufHandle, fenceHandle | |
}); | |
resourceMonitor->append(move(transferResources), true); | |
fenceHandle->release(); | |
cmdBufHandle->release(); | |
/////////// | |
imageHandle = VulkanAsyncResourceHandle::newImage(instance->getResourceMonitor(), device, image, imageView, imageAllocation); | |
auto resourceMonitor = instance->getResourceMonitor(); | |
auto fenceHandle = VulkanAsyncResourceHandle::newFence(resourceMonitor, device, transferFence); | |
auto cmdBufHandle = VulkanAsyncResourceHandle::newCommandBuffer(resourceMonitor, device, commandBuffer, commandPool); | |
VulkanAsyncResourceCollection transferResources(resourceMonitor, fenceHandle, { | |
stagingBufferHandle, imageHandle, | |
cmdBufHandle, fenceHandle | |
}); | |
resourceMonitor->append(move(transferResources)); | |
fenceHandle->release(); | |
cmdBufHandle->release(); | |
//Polling for and releasing resource handles (done in resource monitoring bg thread)//////////////////////////////////// | |
bool VulkanAsyncResourceCollection::check(VkDevice device) | |
{ | |
VkResult status = VK_SUCCESS; | |
if(!frame) | |
{ | |
if(!fence) | |
{ | |
return false; | |
} | |
status = vkGetFenceStatus(device, fence->fence); | |
} | |
else | |
{ | |
status = (monitor->completedFrame.load() > frameId) ? VK_SUCCESS : VK_NOT_READY; | |
} | |
if(status == VK_SUCCESS) | |
{ | |
for(auto &handle : handles) if(handle) | |
{ | |
if(handle->release()) | |
{ | |
delete handle; | |
handle = nullptr; | |
} | |
} | |
if(!frame) | |
{ | |
if(fence->release()) | |
{ | |
delete fence; | |
fence = nullptr; | |
} | |
} | |
return true; | |
} | |
else if(status == VK_ERROR_DEVICE_LOST) | |
{ | |
throw std::runtime_error("VulkanAsyncResourceFence::checkFence encountered VK_ERROR_DEVICE_LOST"); | |
} | |
return false; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment