diff --git a/src/renderer/backend_api.h b/src/renderer/backend_api.h index 3ad2e6e..bc9c539 100644 --- a/src/renderer/backend_api.h +++ b/src/renderer/backend_api.h @@ -11,7 +11,7 @@ typedef struct rt_physical_resource_manager_i rt_physical_resource_manager_i; typedef rt_physical_resource_manager_i rt_render_device_get_physical_resource_manager_fn(void *o); -typedef rt_result rt_render_device_submit_command_list_fn(void *o, rt_render_command_list *list); +typedef rt_result rt_render_device_submit_command_list_fn(void *o, const rt_render_command_list *list); /* Interface for the render device. * The device is responsible for executing command lists. */ diff --git a/src/renderer/command_list.c b/src/renderer/command_list.c index 85057e6..654aa73 100644 --- a/src/renderer/command_list.c +++ b/src/renderer/command_list.c @@ -49,7 +49,7 @@ void CommandListsOnBeginFrame(void) { #define COMMAND_LIST_MAX_LENGTH (COMMAND_LIST_CAPACITY / AVERAGE_COMMAND_DATA_SIZE) /* Get a new render command list. */ -RT_DLLEXPORT rt_begin_render_command_list_result rtBeginRenderCommandList(void) { +RT_DLLEXPORT rt_begin_render_command_list_result rtBeginRenderCommandList(rt_render_queue queue) { size_t mem_required = COMMAND_LIST_MAX_LENGTH * sizeof(rt_render_command_header) + COMMAND_LIST_CAPACITY; rtLockMutex(_mutex); void *mem = rtArenaPush(_current_arena, mem_required); @@ -60,6 +60,7 @@ RT_DLLEXPORT rt_begin_render_command_list_result rtBeginRenderCommandList(void) } rt_render_command_list list = { .headers = mem, + .target_queue = queue, .data = (void *)((rt_render_command_header *)mem + COMMAND_LIST_MAX_LENGTH), .length = 0u, .data_capacity = COMMAND_LIST_CAPACITY, @@ -72,7 +73,7 @@ RT_DLLEXPORT rt_begin_render_command_list_result rtBeginRenderCommandList(void) } /* Lowlevel function that writes the data to the queue. */ -RT_DLLEXPORT rt_result rtEncodeRenderCommand(rt_render_command_list *list, rt_render_command_type type, rt_render_queue queue, const void *data) { +RT_DLLEXPORT rt_result rtEncodeRenderCommand(rt_render_command_list *list, rt_render_command_type type, const void *data) { size_t data_size = 0u; switch (type) { case RT_RENDER_COMMAND_DRAW_INDIRECT: @@ -87,9 +88,7 @@ RT_DLLEXPORT rt_result rtEncodeRenderCommand(rt_render_command_list *list, rt_re rtReportError("RENDERER", "Reached maximum lenght or capacity of command list."); return RT_OUT_OF_MEMORY; } - list->headers[list->length].type = type; - list->headers[list->length].target_queue = queue; ++list->length; char *dest = (char *)list->data + list->data_end; memcpy(dest, data, data_size); @@ -97,7 +96,7 @@ RT_DLLEXPORT rt_result rtEncodeRenderCommand(rt_render_command_list *list, rt_re return RT_SUCCESS; } -/* Submit a finished command list to the graphics device. The list will not be usable after this function is done. */ -RT_DLLEXPORT rt_result rtSubmitCommandList(rt_render_command_list *list) { +/* Submit a finished command list to the graphics device. */ +RT_DLLEXPORT rt_result rtSubmitCommandList(const rt_render_command_list *list) { return g_device_i.SubmitCommandList(g_device_i.o, list); } diff --git a/src/renderer/command_list.h b/src/renderer/command_list.h index ae672e9..7ad180f 100644 --- a/src/renderer/command_list.h +++ b/src/renderer/command_list.h @@ -8,6 +8,9 @@ /* Types of render commands */ typedef enum { RT_RENDER_COMMAND_DRAW_INDIRECT, + + + RT_RENDER_COMMAND_COUNT, } rt_render_command_type; typedef enum { @@ -27,15 +30,21 @@ typedef struct { typedef struct { uint32_t type; - uint32_t target_queue; } rt_render_command_header; typedef struct { + /* One header per command */ rt_render_command_header *headers; + + /* Contains the command data */ void *data; + /* Number of encoded commands */ uint32_t length; + /* Tne device queue to which this list should be submitted*/ + uint32_t target_queue; + /* Information used while encoding. * In the future, it would be possible to move this to another struct that is discarded after * encoding is finished. @@ -57,20 +66,20 @@ typedef struct { } rt_begin_render_command_list_result; /* Get a new render command list. */ -RT_DLLEXPORT rt_begin_render_command_list_result rtBeginRenderCommandList(void); +RT_DLLEXPORT rt_begin_render_command_list_result rtBeginRenderCommandList(rt_render_queue queue); /* Lowlevel function that writes the data to the queue. */ -RT_DLLEXPORT rt_result rtEncodeRenderCommand(rt_render_command_list *list, rt_render_command_type type, rt_render_queue queue, const void *data); +RT_DLLEXPORT rt_result rtEncodeRenderCommand(rt_render_command_list *list, rt_render_command_type type, const void *data); /* Helper functions for specific commands */ RT_INLINE rt_result rtEncodeDrawIndirect(rt_render_command_list *list, const rt_draw_indirect_data *draw_indirect_data) { - return rtEncodeRenderCommand(list, RT_RENDER_COMMAND_DRAW_INDIRECT, RT_RENDER_QUEUE_GRAPHICS, draw_indirect_data); + return rtEncodeRenderCommand(list, RT_RENDER_COMMAND_DRAW_INDIRECT, draw_indirect_data); } /* *** Submission *** */ -/* Submit a finished command list to the graphics device. The list will not be usable after this function is done. */ -RT_DLLEXPORT rt_result rtSubmitCommandList(rt_render_command_list *list); +/* Submit a finished command list to the graphics device. */ +RT_DLLEXPORT rt_result rtSubmitCommandList(const rt_render_command_list *list); #ifdef __cplusplus diff --git a/src/renderer/vk/command_buffers.c b/src/renderer/vk/command_buffers.c new file mode 100644 index 0000000..00f6082 --- /dev/null +++ b/src/renderer/vk/command_buffers.c @@ -0,0 +1,196 @@ +#include "command_buffers.h" +#include "device.h" + +/* We need one command pool per frame per thread. */ +#include +#include +#include +#include + +struct rt_vk_command_pool_set { + VkCommandPool graphics; + VkCommandPool compute; + VkCommandPool transfer; +} ; + +typedef struct { + long indices[3]; +} rt_thread_pool_indices; + +static RT_THREAD_LOCAL rt_thread_pool_indices t_pool_indices; +static RT_THREAD_LOCAL bool t_are_indices_initialized[3] = {false, false, false}; + +rt_vk_command_pool_array rtReserveCommandPoolArray(long max_threads) { + rt_vk_command_pool_array array; + array.next_unused = 0; + array.capacity = 0; + array.pools = calloc(max_threads, sizeof(rt_vk_command_pool_set)); + if (!array.pools) + return array; + array.capacity = max_threads; + return array; +} + +void rtReleaseCommandPoolArray(rt_vk_command_pool_array *array) { + free(array->pools); + array->pools = NULL; + array->capacity = 0; + array->next_unused = 0; +} + +static rt_vk_command_pool_set *GetThreadsPoolSet(rt_vk_device *dev, uint32_t frame_id) { + uint32_t slot = frame_id % dev->max_frames_in_flight; + if (!t_are_indices_initialized[slot]) { + /* Alloc the set */ + rt_vk_command_pool_set *set = NULL; + long index = rtAtomic32Inc(&dev->frames[slot].command_pools.next_unused) - 1; /* Inc returns the new value */ + if (index >= dev->frames[slot].command_pools.capacity) { + rtReportError("VK", "Ran out of space for per-thread command buffers. Try to increase r_VkMaxThreads"); + return NULL; + } + set = &dev->frames[slot].command_pools.pools[index]; + + /* Create the pools */ + { + VkCommandPoolCreateInfo pool_info = { + .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, + .flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, + .queueFamilyIndex = dev->graphics_family, + }; + if (vkCreateCommandPool(dev->device, &pool_info, dev->alloc_cb, &set->graphics) != VK_SUCCESS) { + rtReportError("VK", "vkCreateCommandPool failed."); + return NULL; + } +#ifdef RT_DEBUG + uint32_t thread_id = rtGetCurrentThreadId(); + char name[128]; + rtSPrint(name, 128, "Graphics Command Pool (FrameSlot %u, Thread %u)", slot, thread_id); + VkDebugUtilsObjectNameInfoEXT name_info = { + .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT, + .objectHandle = (uint64_t)set->graphics, + .objectType = VK_OBJECT_TYPE_COMMAND_POOL, + .pObjectName = name, + }; + vkSetDebugUtilsObjectNameEXT(dev->device, &name_info); +#endif + } + if (dev->compute_family != dev->graphics_family) { + VkCommandPoolCreateInfo pool_info = { + .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, + .flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, + .queueFamilyIndex = dev->compute_family, + }; + if (vkCreateCommandPool(dev->device, &pool_info, dev->alloc_cb, &set->compute) != VK_SUCCESS) { + rtReportError("VK", "vkCreateCommandPool failed."); + return NULL; + } +#ifdef RT_DEBUG + uint32_t thread_id = rtGetCurrentThreadId(); + char name[128]; + rtSPrint(name, 128, "Compute Command Pool (FrameSlot %u, Thread %u)", slot, thread_id); + VkDebugUtilsObjectNameInfoEXT name_info = { + .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT, + .objectHandle = (uint64_t)set->compute, + .objectType = VK_OBJECT_TYPE_COMMAND_POOL, + .pObjectName = name, + }; + vkSetDebugUtilsObjectNameEXT(dev->device, &name_info); +#endif + } else { + set->compute = set->graphics; + } + if (dev->transfer_family != dev->graphics_family && dev->transfer_family != dev->compute_family) { + VkCommandPoolCreateInfo pool_info = { + .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, + .flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, + .queueFamilyIndex = dev->transfer_family, + }; + if (vkCreateCommandPool(dev->device, &pool_info, dev->alloc_cb, &set->transfer) != VK_SUCCESS) { + rtReportError("VK", "vkCreateCommandPool failed."); + return NULL; + } +#ifdef RT_DEBUG + uint32_t thread_id = rtGetCurrentThreadId(); + char name[128]; + rtSPrint(name, 128, "Transfer Command Pool (FrameSlot %u, Thread %u)", slot, thread_id); + VkDebugUtilsObjectNameInfoEXT name_info = { + .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT, + .objectHandle = (uint64_t)set->transfer, + .objectType = VK_OBJECT_TYPE_COMMAND_POOL, + .pObjectName = name, + }; + vkSetDebugUtilsObjectNameEXT(dev->device, &name_info); +#endif + } + else if (dev->transfer_family == dev->graphics_family) { + set->transfer = set->graphics; + } else { + RT_ASSERT(dev->transfer_family == dev->compute_family, ""); + set->transfer = set->compute; + } + + t_pool_indices.indices[slot] = index; + t_are_indices_initialized[slot] = true; + } + + long index = t_pool_indices.indices[slot]; +#ifdef RT_DEBUG + if (index >= dev->frames[slot].command_pools.next_unused) + return NULL; +#endif + return &dev->frames[slot].command_pools.pools[index]; +} + +VkCommandPool rtGetGraphicsCommandPool(rt_vk_device *dev) { + rt_vk_command_pool_set *set = GetThreadsPoolSet(dev, dev->current_frame_id); + return RT_VERIFY(set)->graphics; +} + +VkCommandPool rtGetComputeCommandPool(rt_vk_device *dev) { + rt_vk_command_pool_set *set = GetThreadsPoolSet(dev, dev->current_frame_id); + return RT_VERIFY(set)->compute; +} + +VkCommandPool rtGetTransferCommandPool(rt_vk_device *dev) { + rt_vk_command_pool_set *set = GetThreadsPoolSet(dev, dev->current_frame_id); + return RT_VERIFY(set)->transfer; +} + +VkCommandBuffer rtAllocateGraphicsCommandBuffer(rt_vk_device *dev) { + VkCommandPool pool = rtGetGraphicsCommandPool(dev); + VkCommandBufferAllocateInfo alloc_info = { + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, + .commandPool = pool, + .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, + .commandBufferCount = 1, + }; + VkCommandBuffer cmdbuf = VK_NULL_HANDLE; + vkAllocateCommandBuffers(dev->device, &alloc_info, &cmdbuf); + return cmdbuf; +} + +VkCommandBuffer rtAllocateComputeCommandBuffer(rt_vk_device *dev) { + VkCommandPool pool = rtGetComputeCommandPool(dev); + VkCommandBufferAllocateInfo alloc_info = { + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, + .commandPool = pool, + .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, + .commandBufferCount = 1, + }; + VkCommandBuffer cmdbuf = VK_NULL_HANDLE; + vkAllocateCommandBuffers(dev->device, &alloc_info, &cmdbuf); + return cmdbuf; +} + +VkCommandBuffer rtAllocateTransferCommandBuffer(rt_vk_device *dev) { + VkCommandPool pool = rtGetTransferCommandPool(dev); + VkCommandBufferAllocateInfo alloc_info = { + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, + .commandPool = pool, + .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, + .commandBufferCount = 1, + }; + VkCommandBuffer cmdbuf = VK_NULL_HANDLE; + vkAllocateCommandBuffers(dev->device, &alloc_info, &cmdbuf); + return cmdbuf; +} \ No newline at end of file diff --git a/src/renderer/vk/command_buffers.h b/src/renderer/vk/command_buffers.h new file mode 100644 index 0000000..ce97b1b --- /dev/null +++ b/src/renderer/vk/command_buffers.h @@ -0,0 +1,29 @@ +#ifndef RT_VK_COMMAND_LISTS_H +#define RT_VK_COMMAND_LISTS_H + +#include + +struct rt_vk_device; + +typedef struct rt_vk_command_pool_set rt_vk_command_pool_set; + +/* Contains an array of command pools. Threads safe an index into the array + * to access their own command pool set. */ +typedef struct { + rt_vk_command_pool_set *pools; + long capacity; + long next_unused; +} rt_vk_command_pool_array; + +rt_vk_command_pool_array rtReserveCommandPoolArray(long max_threads); +void rtReleaseCommandPoolArray(rt_vk_command_pool_array *array); + +VkCommandPool rtGetGraphicsCommandPool(struct rt_vk_device *dev); +VkCommandPool rtGetComputeCommandPool(struct rt_vk_device *dev); +VkCommandPool rtGetTransferCommandPool(struct rt_vk_device *dev); + +VkCommandBuffer rtAllocateGraphicsCommandBuffer(struct rt_vk_device *dev); +VkCommandBuffer rtAllocateComputeCommandBuffer(struct rt_vk_device *dev); +VkCommandBuffer rtAllocateTransferCommandBuffer(struct rt_vk_device *dev); + +#endif diff --git a/src/renderer/vk/device.c b/src/renderer/vk/device.c index 309776d..f9616cd 100644 --- a/src/renderer/vk/device.c +++ b/src/renderer/vk/device.c @@ -19,6 +19,7 @@ RT_CVAR_I(r_VkEnableAPIAllocTracking, RT_CVAR_S(r_VkPhysDeviceName, "Name of the selected physical device. Default: \"\"", ""); RT_CVAR_I(r_VkMaxFramesInFlight, "Maximum number of frames in flight. [2/3] Default: 2", 2); +RT_CVAR_UI(r_VkMaxThreads, "Maximum number of threads used. (Default: 128)", 128); static VkAllocationCallbacks _tracking_alloc_cbs; @@ -564,6 +565,8 @@ static rt_result CreatePerFrameObjects(rt_vk_device *dev) { name_info.objectHandle = (uint64_t)dev->frames[i].swapchain_transitioned; vkSetDebugUtilsObjectNameEXT(dev->device, &name_info); #endif + + dev->frames[i].command_pools = rtReserveCommandPoolArray(r_VkMaxThreads.ui); } return RT_SUCCESS; } @@ -627,6 +630,10 @@ rt_create_vk_device_result rtCreateVkDevice(const rt_renderer_window_info *info) goto out; dev.bindless_registry = bindless_registry_result.bindless_registry; + dev.created_pools = calloc(128 * 9, sizeof(VkCommandPool)); + dev.created_pool_count = 0; + dev.max_created_pools = 128 * 9; + rt_time_delta initTime = rtTimeBetween(initBegin, rtTimeNow()); rtLog("VK", "Init complete. Took %lf seconds.", initTime); @@ -637,6 +644,7 @@ out: void rtDestroyVkDevice(rt_vk_device *dev) { rtLog("VK", "Shutdown"); vkDeviceWaitIdle(dev->device); + free(dev->created_pools); rtDestroyVkBindlessRegistry(&dev->bindless_registry); rtDestroyVkPhysicalResourceManager(&dev->phys_res_mgr); DestroySwapchain(dev); @@ -662,25 +670,98 @@ rt_physical_resource_manager_i rtVkDevGetPhysicalResourceManager(void *o) { return iface; } -rt_result rtVkDevSubmitCommandList(void *o, rt_render_command_list *list) { - /* Dummy implementation */ - RT_UNUSED(o); - size_t data_off = 0; - for (uint32_t i = 0; i < list->length; ++i) { - if (list->headers[i].type != RT_RENDER_COMMAND_DRAW_INDIRECT) - break; - rtLog("VK", "DrawIndirect %u", i); - rtLog("VK", "Target queue: %u", list->headers[i].target_queue); - - RT_VERIFY(data_off < list->data_end); - rt_draw_indirect_data *data = (rt_draw_indirect_data *)((char *)list->data + data_off); - rtLog("VK", "buffer %u draw_count %u offset %u stride %u", - data->buffer.value, - data->draw_count, - data->offset, - data->stride); - data_off += sizeof(rt_draw_indirect_data); +/* Commands */ +static rt_result DrawIndirectImpl(rt_vk_device *dev, VkCommandBuffer cmdbuf, const void *_data) { + const rt_draw_indirect_data *data = _data; + const rt_vk_physical_resource *buffer_resource = rtGetVkPhysicalResource(&dev->phys_res_mgr, data->buffer); + if (!buffer_resource) { + rtLog("VK", "Invalid buffer in draw indirect data"); + return RT_INVALID_VALUE; } + RT_ASSERT(buffer_resource->type == RT_RENDER_RESOURCE_TYPE_BUFFER, + "Buffer handle in draw indirect data does not reference a buffer object"); + vkCmdDrawIndirect(cmdbuf, buffer_resource->buffer, data->offset, data->draw_count, data->stride); return RT_SUCCESS; +} + +typedef rt_result rt_vk_render_command_impl_fn(rt_vk_device *dev, VkCommandBuffer cmdbuf, const void *data); + +static size_t _command_data_sizes[RT_RENDER_COMMAND_COUNT] = { + sizeof(rt_draw_indirect_data), +}; + +static rt_vk_render_command_impl_fn *_command_impls[RT_RENDER_COMMAND_COUNT] = { + DrawIndirectImpl, +}; + +rt_result rtVkDevSubmitCommandList(void *o, const rt_render_command_list *list) { + rt_vk_device *dev = o; + size_t data_off = 0; + rt_result res = RT_SUCCESS; + + /* Prepare command buffer */ + VkQueue queue = VK_NULL_HANDLE; + VkCommandBuffer cmdbuf = VK_NULL_HANDLE; + if (list->target_queue == RT_RENDER_QUEUE_GRAPHICS) { + cmdbuf = rtAllocateComputeCommandBuffer(dev); + queue = dev->graphics_queue; + } + else if (list->target_queue == RT_RENDER_QUEUE_COMPUTE) { + cmdbuf = rtAllocateComputeCommandBuffer(dev); + queue = dev->compute_queue; + } + else if (list->target_queue == RT_RENDER_QUEUE_TRANSFER) { + cmdbuf = rtAllocateTransferCommandBuffer(dev); + queue = dev->transfer_queue; + } + else { + RT_ASSERT("VK", "Invalid target queue"); + return RT_INVALID_VALUE; + } + VkCommandBufferBeginInfo begin_info = {.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, + .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT}; + if (vkBeginCommandBuffer(cmdbuf, &begin_info) != VK_SUCCESS) { + rtLog("VK", "vkBeginCommandBuffer failed"); + return RT_UNKNOWN_ERROR; + } + + /* Iterate over all commands and decode them */ + for (uint32_t i = 0; i < list->length; ++i) { + rt_render_command_header header = list->headers[i]; + RT_ASSERT(header.type < RT_RENDER_COMMAND_COUNT, + "Invalid render command type."); + const void *data = (const char *)list->data + data_off; + res = _command_impls[header.type](dev, cmdbuf, data); + if (res != RT_SUCCESS) + break; + data_off += _command_data_sizes[header.type]; + } + if (res != RT_SUCCESS) { + return res; + } + + /* End the command buffers and create submit info */ + vkEndCommandBuffer(cmdbuf); + + /* Submit it! */ + VkCommandBufferSubmitInfo cmdbuf_info = { + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO, + .commandBuffer = cmdbuf + }; + + VkSubmitInfo2 submit_info = { + .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO_2, + .commandBufferInfoCount = 1, + .pCommandBufferInfos = &cmdbuf_info, + .waitSemaphoreInfoCount = 0, + .pWaitSemaphoreInfos = NULL, + .signalSemaphoreInfoCount = 0, + .pSignalSemaphoreInfos = NULL, + }; + if (vkQueueSubmit2(queue, 1, &submit_info, VK_NULL_HANDLE) != VK_SUCCESS) { + rtLog("VK"," vkQueueSubmit2 failed"); + res = RT_UNKNOWN_ERROR; + } + return res; } \ No newline at end of file diff --git a/src/renderer/vk/device.h b/src/renderer/vk/device.h index d74dd1f..6cd66d0 100644 --- a/src/renderer/vk/device.h +++ b/src/renderer/vk/device.h @@ -8,6 +8,7 @@ #include "physical_resource_manager.h" #include "bindless_registry.h" +#include "command_buffers.h" #ifdef _WIN32 struct HINSTANCE__; @@ -31,6 +32,8 @@ typedef struct { VkSemaphore render_finished; VkSemaphore image_available; VkSemaphore swapchain_transitioned; + + rt_vk_command_pool_array command_pools; } rt_vk_frame_data; typedef struct rt_vk_device { @@ -76,6 +79,11 @@ typedef struct rt_vk_device { rt_vk_physical_resource_manager phys_res_mgr; rt_vk_bindless_registry bindless_registry; + /* *** Save created command pools in a list to clean them up at exit */ + VkCommandPool *created_pools; + long created_pool_count; + long max_created_pools; + /* *** Debug utils *** */ #ifdef RT_DEBUG VkDebugUtilsMessengerEXT messenger; @@ -93,6 +101,6 @@ void rtDestroyVkDevice(rt_vk_device *dev); /* rt_render_device_i functions */ rt_physical_resource_manager_i rtVkDevGetPhysicalResourceManager(void *o); -rt_result rtVkDevSubmitCommandList(void *o, rt_render_command_list *list); +rt_result rtVkDevSubmitCommandList(void *o, const rt_render_command_list *list); #endif diff --git a/src/renderer/vk/init.c b/src/renderer/vk/init.c index 35c52e4..e0cf05d 100644 --- a/src/renderer/vk/init.c +++ b/src/renderer/vk/init.c @@ -7,6 +7,7 @@ extern rt_cvar r_VkEnableAPIAllocTracking; extern rt_cvar r_VkPhysDeviceName; extern rt_cvar r_VkMaxFramesInFlight; +extern rt_cvar r_VkMaxThreads; extern rt_cvar r_VkPreferMailboxMode; extern rt_cvar r_VkPreferRelaxedMode; extern rt_cvar r_VkEnableVSync; @@ -21,6 +22,7 @@ void VkRegisterCVARs(void) { rtRegisterCVAR(&r_VkEnableAPIAllocTracking); rtRegisterCVAR(&r_VkPhysDeviceName); rtRegisterCVAR(&r_VkMaxFramesInFlight); + rtRegisterCVAR(&r_VkMaxThreads); rtRegisterCVAR(&r_VkPreferMailboxMode); rtRegisterCVAR(&r_VkPreferRelaxedMode); rtRegisterCVAR(&r_VkEnableVSync); diff --git a/src/renderer/vk/meson.build b/src/renderer/vk/meson.build index 558c6ed..c5421f9 100644 --- a/src/renderer/vk/meson.build +++ b/src/renderer/vk/meson.build @@ -14,10 +14,12 @@ if get_option('build_vk') vk_renderer_lib = library('rtvk', 'bindless_registry.h', + 'command_buffers.h', 'device.h', 'physical_resource_manager.h', 'bindless_registry.c', + 'command_buffers.c', 'device.c', 'init.c', 'physical_resource_manager.c', diff --git a/src/renderer/vk/physical_resource_manager.c b/src/renderer/vk/physical_resource_manager.c index 8b1682e..5a08784 100644 --- a/src/renderer/vk/physical_resource_manager.c +++ b/src/renderer/vk/physical_resource_manager.c @@ -147,6 +147,17 @@ void rtVkPhysicalResourceManagerDestroy(void *o, rt_render_resource_handle handl rtUnlockWrite(&phys_res_mgr->lock); } +rt_vk_physical_resource *rtGetVkPhysicalResource(rt_vk_physical_resource_manager *phys_res_mgr, rt_render_resource_handle handle) { + rt_vk_physical_resource *resource = NULL; + rtLockRead(&phys_res_mgr->lock); + uint32_t slot = rtHashtableLookup(&phys_res_mgr->resource_lut, handle.value, UINT32_MAX); + if (slot != UINT32_MAX) { + resource = &phys_res_mgr->resources[slot]; + } + rtUnlockRead(&phys_res_mgr->lock); + return resource; +} + /* Call this with a held write lock! */ static uint32_t AllocStorageSlot(rt_vk_physical_resource_manager *phys_res_mgr, rt_render_resource_handle h) { if (phys_res_mgr->free_slot_count > 0u) { diff --git a/src/renderer/vk/physical_resource_manager.h b/src/renderer/vk/physical_resource_manager.h index 8b0a43c..ed7ae91 100644 --- a/src/renderer/vk/physical_resource_manager.h +++ b/src/renderer/vk/physical_resource_manager.h @@ -52,6 +52,8 @@ rt_create_vk_physical_resource_manager_result rtCreateVkPhysicalResourceManager( void rtDestroyVkPhysicalResourceManager(rt_vk_physical_resource_manager *phys_res_mgr); +rt_vk_physical_resource *rtGetVkPhysicalResource(rt_vk_physical_resource_manager *phys_res_mgr, rt_render_resource_handle handle); + /* rt_physical_resource_manager_i functions */ bool rtVkPhysicalResourceManagerIsPresent(void *o, rt_render_resource_handle handle); void rtVkPhysicalResourceManagerDestroy(void *o, rt_render_resource_handle handle);