Creating timed semaphores
- Similar to Dx12 fences. - More flexible than VK 1 binary semaphores.
This commit is contained in:
		
							parent
							
								
									9b162379d4
								
							
						
					
					
						commit
						e989c2b406
					
				@ -1,4 +1,5 @@
 | 
			
		||||
#include "gpu.h"
 | 
			
		||||
#include "gpu_sync.h"
 | 
			
		||||
#include "swapchain.h"
 | 
			
		||||
 | 
			
		||||
#include "runtime/atomics.h"
 | 
			
		||||
@ -75,7 +76,7 @@ void rtResetCommandPools(unsigned int frame_id) {
 | 
			
		||||
    unsigned int pool_idx = frame_id % g_gpu.max_frames_in_flight;
 | 
			
		||||
    for (uint32_t i = 1; i < _next_pools; ++i) {
 | 
			
		||||
        if (vkResetCommandPool(g_gpu.device,
 | 
			
		||||
                           _pools[i].graphics_pools[pool_idx],
 | 
			
		||||
                               _pools[i].graphics_pools[pool_idx],
 | 
			
		||||
                               VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT) != VK_SUCCESS) {
 | 
			
		||||
            rtLog("vk", "Failed to reset graphics pool slot %u index %u", i, pool_idx);
 | 
			
		||||
        }
 | 
			
		||||
@ -233,12 +234,48 @@ rt_result RT_RENDERER_API_FN(SubmitCommandBuffers)(rt_gpu_queue queue,
 | 
			
		||||
    rt_result result     = RT_SUCCESS;
 | 
			
		||||
    VkQueue target_queue = rtGetQueue(queue);
 | 
			
		||||
 | 
			
		||||
    VkCommandBuffer *command_buffers = RT_ARENA_PUSH_ARRAY(temp.arena, VkCommandBuffer, count);
 | 
			
		||||
    VkCommandBufferSubmitInfo *command_buffers =
 | 
			
		||||
        RT_ARENA_PUSH_ARRAY(temp.arena, VkCommandBufferSubmitInfo, count);
 | 
			
		||||
    if (!command_buffers) {
 | 
			
		||||
        result = RT_OUT_OF_MEMORY;
 | 
			
		||||
        goto out;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    VkSemaphoreSubmitInfo *wait_semaphores =
 | 
			
		||||
        RT_ARENA_PUSH_ARRAY(temp.arena, VkSemaphoreSubmitInfo, info->wait_semaphore_count);
 | 
			
		||||
    if (!wait_semaphores) {
 | 
			
		||||
        result = RT_OUT_OF_MEMORY;
 | 
			
		||||
        goto out;
 | 
			
		||||
    }
 | 
			
		||||
    VkSemaphoreSubmitInfo *signal_semaphores =
 | 
			
		||||
        RT_ARENA_PUSH_ARRAY(temp.arena, VkSemaphoreSubmitInfo, info->signal_semaphore_count);
 | 
			
		||||
    if (!signal_semaphores) {
 | 
			
		||||
        result = RT_OUT_OF_MEMORY;
 | 
			
		||||
        goto out;
 | 
			
		||||
    }
 | 
			
		||||
    uint32_t wait_count   = info->wait_semaphore_count;
 | 
			
		||||
    uint32_t signal_count = info->signal_semaphore_count;
 | 
			
		||||
    for (uint32_t i = 0; i < wait_count; ++i) {
 | 
			
		||||
        VkSemaphoreSubmitInfo semaphore_info = {
 | 
			
		||||
            .sType       = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
 | 
			
		||||
            .semaphore   = rtGetSemaphore(info->wait_semaphores[i]),
 | 
			
		||||
            .value       = info->wait_values[i],
 | 
			
		||||
            .stageMask   = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
 | 
			
		||||
            .deviceIndex = 0,
 | 
			
		||||
        };
 | 
			
		||||
        wait_semaphores[i] = semaphore_info;
 | 
			
		||||
    }
 | 
			
		||||
    for (uint32_t i = 0; i < signal_count; ++i) {
 | 
			
		||||
        VkSemaphoreSubmitInfo semaphore_info = {
 | 
			
		||||
            .sType       = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
 | 
			
		||||
            .semaphore   = rtGetSemaphore(info->signal_semaphores[i]),
 | 
			
		||||
            .value       = info->signal_values[i],
 | 
			
		||||
            .stageMask   = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
 | 
			
		||||
            .deviceIndex = 0,
 | 
			
		||||
        };
 | 
			
		||||
        wait_semaphores[i] = semaphore_info;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (uint32_t i = 0; i < count; ++i) {
 | 
			
		||||
        uint32_t slot = info->command_buffers[i].index;
 | 
			
		||||
        if (_command_buffers[slot].version != info->command_buffers[i].version) {
 | 
			
		||||
@ -253,27 +290,23 @@ rt_result RT_RENDERER_API_FN(SubmitCommandBuffers)(rt_gpu_queue queue,
 | 
			
		||||
            result = RT_INVALID_VALUE;
 | 
			
		||||
            goto out;
 | 
			
		||||
        }
 | 
			
		||||
        command_buffers[i] = _command_buffers[slot].command_buffer;
 | 
			
		||||
        command_buffers[i].sType         = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO;
 | 
			
		||||
        command_buffers[i].pNext         = NULL;
 | 
			
		||||
        command_buffers[i].deviceMask    = 0;
 | 
			
		||||
        command_buffers[i].commandBuffer = _command_buffers[slot].command_buffer;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* TODO(Kevin): Retrieve semaphores */
 | 
			
		||||
    VkSemaphore *wait_semaphores   = NULL;
 | 
			
		||||
    VkSemaphore *signal_semaphores = NULL;
 | 
			
		||||
    uint32_t wait_count            = 0;
 | 
			
		||||
    uint32_t signal_count          = 0;
 | 
			
		||||
 | 
			
		||||
    VkSubmitInfo submit_info = {
 | 
			
		||||
        .sType                = VK_STRUCTURE_TYPE_SUBMIT_INFO,
 | 
			
		||||
        .pCommandBuffers      = command_buffers,
 | 
			
		||||
        .commandBufferCount   = count,
 | 
			
		||||
        .pWaitSemaphores      = wait_semaphores,
 | 
			
		||||
        .pWaitDstStageMask    = NULL,
 | 
			
		||||
        .waitSemaphoreCount   = wait_count,
 | 
			
		||||
        .pSignalSemaphores    = signal_semaphores,
 | 
			
		||||
        .signalSemaphoreCount = signal_count,
 | 
			
		||||
    VkSubmitInfo2 submit_info = {
 | 
			
		||||
        .sType                    = VK_STRUCTURE_TYPE_SUBMIT_INFO_2,
 | 
			
		||||
        .waitSemaphoreInfoCount   = wait_count,
 | 
			
		||||
        .signalSemaphoreInfoCount = signal_count,
 | 
			
		||||
        .pWaitSemaphoreInfos      = wait_semaphores,
 | 
			
		||||
        .pSignalSemaphoreInfos    = signal_semaphores,
 | 
			
		||||
        .commandBufferInfoCount   = count,
 | 
			
		||||
        .pCommandBufferInfos      = command_buffers,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    if (vkQueueSubmit(target_queue, 1, &submit_info, VK_NULL_HANDLE) != VK_SUCCESS) {
 | 
			
		||||
    if (vkQueueSubmit2(target_queue, 1, &submit_info, VK_NULL_HANDLE) != VK_SUCCESS) {
 | 
			
		||||
        rtLog("vk", "vkQueueSubmit failed.");
 | 
			
		||||
        result = RT_UNKNOWN_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -5,4 +5,5 @@
 | 
			
		||||
 | 
			
		||||
void rtResetCommandPools(unsigned int frame_id);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										139
									
								
								src/renderer/vk/gpu_sync.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										139
									
								
								src/renderer/vk/gpu_sync.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,139 @@
 | 
			
		||||
#include "gpu.h"
 | 
			
		||||
 | 
			
		||||
#include "runtime/renderer_api.h"
 | 
			
		||||
#include "runtime/config.h"
 | 
			
		||||
#include "runtime/threading.h"
 | 
			
		||||
#include "runtime/handles.h"
 | 
			
		||||
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
 | 
			
		||||
RT_CVAR_I(rt_VkMaxSemaphores, "Maximum number of semaphores. Default: 1024", 1024);
 | 
			
		||||
 | 
			
		||||
typedef struct rt_gpu_semaphore_s {
 | 
			
		||||
    uint32_t version;
 | 
			
		||||
    VkSemaphore semaphore;
 | 
			
		||||
    uint64_t current_value;
 | 
			
		||||
    /* TODO: State tracking. We want to ensure that we don't introduce gpu hangs by waiting on a not-signaled semaphore. */
 | 
			
		||||
 | 
			
		||||
    struct rt_gpu_semaphore_s *next_free;
 | 
			
		||||
} rt_gpu_semaphore;
 | 
			
		||||
 | 
			
		||||
static rt_gpu_semaphore *_semaphores;
 | 
			
		||||
static rt_gpu_semaphore *_first_free;
 | 
			
		||||
static rt_mutex *_lock;
 | 
			
		||||
 | 
			
		||||
static void DestroySemaphore(rt_gpu_semaphore *s) {
 | 
			
		||||
    vkDestroySemaphore(g_gpu.device, s->semaphore, g_gpu.alloc_cb);
 | 
			
		||||
    s->semaphore = VK_NULL_HANDLE;
 | 
			
		||||
    rtLockMutex(_lock);
 | 
			
		||||
    s->next_free = _first_free;
 | 
			
		||||
    _first_free  = s;
 | 
			
		||||
    rtUnlockMutex(_lock);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
rt_result InitializeSempahoreManagement(void) {
 | 
			
		||||
    _semaphores = calloc(rt_VkMaxSemaphores.i, sizeof(rt_gpu_semaphore));
 | 
			
		||||
    if (!_semaphores)
 | 
			
		||||
        return RT_OUT_OF_MEMORY;
 | 
			
		||||
 | 
			
		||||
    _lock = rtCreateMutex();
 | 
			
		||||
    if (!_lock) {
 | 
			
		||||
        free(_semaphores);
 | 
			
		||||
        return RT_UNKNOWN_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Keep 0 unused for the invalid handle */
 | 
			
		||||
    _first_free = &_semaphores[1];
 | 
			
		||||
    for (int i = 1; i < rt_VkMaxSemaphores.i - 1; ++i)
 | 
			
		||||
        _semaphores[i].next_free = &_semaphores[i + 1];
 | 
			
		||||
    _semaphores[rt_VkMaxSemaphores.i - 1].next_free = NULL;
 | 
			
		||||
 | 
			
		||||
    return RT_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ShutdownSemaphoreManagement(void) {
 | 
			
		||||
    for (int i = 1; i < rt_VkMaxSemaphores.i; ++i) {
 | 
			
		||||
        vkDestroySemaphore(g_gpu.device, _semaphores[i].semaphore, g_gpu.alloc_cb);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
rt_result RT_RENDERER_API_FN(CreateSemaphores)(uint32_t count, const rt_gpu_semaphore_info *info, rt_gpu_semaphore_handle *p_semaphores) {
 | 
			
		||||
    for (uint32_t i = 0; i < count; ++i) {
 | 
			
		||||
        rtLockMutex(_lock);
 | 
			
		||||
        rt_gpu_semaphore *sem = _first_free;
 | 
			
		||||
        if (sem)
 | 
			
		||||
            _first_free = sem->next_free;
 | 
			
		||||
        rtUnlockMutex(_lock);
 | 
			
		||||
 | 
			
		||||
        if (!sem) {
 | 
			
		||||
            for (uint32_t j = 0; j < i; ++j) {
 | 
			
		||||
                uint32_t index = p_semaphores[j].index;
 | 
			
		||||
                DestroySemaphore(&_semaphores[index]);
 | 
			
		||||
            }
 | 
			
		||||
            return RT_OUT_OF_MEMORY;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        sem->version = (sem->version + 1) % RT_RENDER_BACKEND_HANDLE_MAX_VERSION;
 | 
			
		||||
        
 | 
			
		||||
        VkSemaphoreTypeCreateInfo type_info = {
 | 
			
		||||
            .sType         = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO,
 | 
			
		||||
            .semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE,
 | 
			
		||||
            .initialValue  = info[i].initial_value,
 | 
			
		||||
        };
 | 
			
		||||
        VkSemaphoreCreateInfo semaphore_info = {
 | 
			
		||||
            .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
 | 
			
		||||
            .pNext = &type_info,
 | 
			
		||||
        };
 | 
			
		||||
        
 | 
			
		||||
        if (vkCreateSemaphore(g_gpu.device, &semaphore_info, g_gpu.alloc_cb, &sem->semaphore) !=
 | 
			
		||||
            VK_SUCCESS) {
 | 
			
		||||
            for (uint32_t j = 0; j < i; ++j) {
 | 
			
		||||
                uint32_t index = p_semaphores[j].index;
 | 
			
		||||
                DestroySemaphore(&_semaphores[index]);
 | 
			
		||||
            }
 | 
			
		||||
            return RT_UNKNOWN_ERROR;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        p_semaphores[i].version = sem->version;
 | 
			
		||||
        p_semaphores[i].index   = (uint32_t)(sem - _semaphores);
 | 
			
		||||
    }
 | 
			
		||||
    return RT_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RT_RENDERER_API_FN(DestroySemaphores)(uint32_t count, rt_gpu_semaphore_handle *semaphores) {
 | 
			
		||||
    for (uint32_t i = 0; i < count; ++i) {
 | 
			
		||||
        uint32_t index = semaphores[i].index;
 | 
			
		||||
        if (index >= (uint32_t)rt_VkMaxSemaphores.i)
 | 
			
		||||
            continue;
 | 
			
		||||
        if (semaphores[i].version != _semaphores[index].version) {
 | 
			
		||||
            rtLog("vk",
 | 
			
		||||
                  "Tried to destroy semaphore %u with version %u, but the semaphore has version %u",
 | 
			
		||||
                  index,
 | 
			
		||||
                  semaphores[i].version,
 | 
			
		||||
                  _semaphores[index].version);
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
        DestroySemaphore(&_semaphores[index]);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VkSemaphore rtGetSemaphore(rt_gpu_semaphore_handle handle) {
 | 
			
		||||
    uint32_t index = handle.index;
 | 
			
		||||
    if (!RT_IS_HANDLE_VALID(handle) || index >= (uint32_t)rt_VkMaxSemaphores.i)
 | 
			
		||||
        return VK_NULL_HANDLE;
 | 
			
		||||
    if (_semaphores[index].version != handle.version)
 | 
			
		||||
        return VK_NULL_HANDLE;
 | 
			
		||||
    return _semaphores[index].semaphore;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint64_t RT_RENDERER_API_FN(GetSemaphoreValue)(rt_gpu_semaphore_handle semaphore) {
 | 
			
		||||
    uint32_t index = semaphore.index;
 | 
			
		||||
    if (!RT_IS_HANDLE_VALID(semaphore) || index >= (uint32_t)rt_VkMaxSemaphores.i)
 | 
			
		||||
        return 0;
 | 
			
		||||
    if (_semaphores[index].version != semaphore.version)
 | 
			
		||||
        return 0;
 | 
			
		||||
    vkGetSemaphoreCounterValue(g_gpu.device,
 | 
			
		||||
                               _semaphores[index].semaphore,
 | 
			
		||||
                               &_semaphores[index].current_value);
 | 
			
		||||
    return _semaphores[index].current_value;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										10
									
								
								src/renderer/vk/gpu_sync.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/renderer/vk/gpu_sync.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,10 @@
 | 
			
		||||
#ifndef RT_VK_GPU_SYNC_H
 | 
			
		||||
#define RT_VK_GPU_SYNC_H
 | 
			
		||||
 | 
			
		||||
#include <volk/volk.h>
 | 
			
		||||
 | 
			
		||||
#include "runtime/renderer_api.h"
 | 
			
		||||
 | 
			
		||||
VkSemaphore rtGetSemaphore(rt_gpu_semaphore_handle handle);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@ -549,6 +549,8 @@ extern rt_result InitRenderTargetManagement(void);
 | 
			
		||||
extern void ShutdownRenderTargetManagement(void);
 | 
			
		||||
extern rt_result InitCommandBufferManagement(void);
 | 
			
		||||
extern void ShutdownCommandBufferManagement(void);
 | 
			
		||||
extern rt_result InitializeSempahoreManagement(void);
 | 
			
		||||
extern void ShutdownSemaphoreManagement(void);
 | 
			
		||||
 | 
			
		||||
rt_result RT_RENDERER_API_FN(Init)(const rt_renderer_init_info *info) {
 | 
			
		||||
    rtLog("vk", "Init");
 | 
			
		||||
@ -586,6 +588,9 @@ rt_result RT_RENDERER_API_FN(Init)(const rt_renderer_init_info *info) {
 | 
			
		||||
    if (res != RT_SUCCESS)
 | 
			
		||||
        return res;
 | 
			
		||||
    res = InitRenderTargetManagement();
 | 
			
		||||
    if (res != RT_SUCCESS)
 | 
			
		||||
        return res;
 | 
			
		||||
    res = InitializeSempahoreManagement();
 | 
			
		||||
    if (res != RT_SUCCESS)
 | 
			
		||||
        return res;
 | 
			
		||||
    res = InitCommandBufferManagement();
 | 
			
		||||
@ -603,6 +608,7 @@ void RT_RENDERER_API_FN(Shutdown)(void) {
 | 
			
		||||
    vkDeviceWaitIdle(g_gpu.device);
 | 
			
		||||
    rtDestroySwapchain();
 | 
			
		||||
    ShutdownCommandBufferManagement();
 | 
			
		||||
    ShutdownSemaphoreManagement();
 | 
			
		||||
    ShutdownRenderTargetManagement();
 | 
			
		||||
    ShutdownPipelineManagement();
 | 
			
		||||
    DestroyAllocator();
 | 
			
		||||
 | 
			
		||||
@ -11,12 +11,14 @@ if vk_dep.found()
 | 
			
		||||
    # Project Sources
 | 
			
		||||
    'command_buffers.h',
 | 
			
		||||
    'gpu.h',
 | 
			
		||||
    'gpu_sync.h',
 | 
			
		||||
    'pipelines.h',
 | 
			
		||||
    'render_targets.h',
 | 
			
		||||
    'swapchain.h',
 | 
			
		||||
 | 
			
		||||
    'command_buffers.c',
 | 
			
		||||
    'frame.c',
 | 
			
		||||
    'gpu_sync.c',
 | 
			
		||||
    'helper.c',
 | 
			
		||||
    'init.c',
 | 
			
		||||
    'pipelines.c',
 | 
			
		||||
 | 
			
		||||
@ -36,9 +36,14 @@ extern rt_result RT_RENDERER_API_FN(AllocCommandBuffers)(uint32_t,
 | 
			
		||||
                                                         rt_command_buffer_handle *);
 | 
			
		||||
extern rt_result RT_RENDERER_API_FN(SubmitCommandBuffers)(rt_gpu_queue,
 | 
			
		||||
                                                          const rt_submit_command_buffers_info *);
 | 
			
		||||
extern rt_result RT_RENDERER_API_FN(CreateSemaphores)(uint32_t,
 | 
			
		||||
                                                      const rt_gpu_semaphore_info *,
 | 
			
		||||
                                                      rt_gpu_semaphore_handle *);
 | 
			
		||||
extern void RT_RENDERER_API_FN(DestroySemaphores)(uint32_t count, rt_gpu_semaphore_handle *);
 | 
			
		||||
extern uint64_t RT_RENDERER_API_FN(GetSemaphoreValue)(rt_gpu_semaphore_handle);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
extern rt_result InitFramegraphManager(void);
 | 
			
		||||
    extern rt_result InitFramegraphManager(void);
 | 
			
		||||
extern void ShutdownFramegraphManager(void);
 | 
			
		||||
 | 
			
		||||
static bool LoadRenderer(void) {
 | 
			
		||||
@ -69,6 +74,9 @@ static bool LoadRenderer(void) {
 | 
			
		||||
        RETRIEVE_SYMBOL(DestroyRenderTarget, rt_destroy_render_target_fn);
 | 
			
		||||
        RETRIEVE_SYMBOL(AllocCommandBuffers, rt_alloc_command_buffers_fn);
 | 
			
		||||
        RETRIEVE_SYMBOL(SubmitCommandBuffers, rt_submit_command_buffers_fn);
 | 
			
		||||
        RETRIEVE_SYMBOL(CreateSemaphores, rt_create_gpu_semaphores_fn);
 | 
			
		||||
        RETRIEVE_SYMBOL(DestroySemaphores, rt_destroy_gpu_semaphores_fn);
 | 
			
		||||
        RETRIEVE_SYMBOL(GetSemaphoreValue, rt_get_gpu_semaphore_value_fn);
 | 
			
		||||
    } else {
 | 
			
		||||
        rtReportError("GFX",
 | 
			
		||||
                      "Unsupported renderer backend: (%s) %s",
 | 
			
		||||
@ -88,6 +96,9 @@ static bool LoadRenderer(void) {
 | 
			
		||||
    g_renderer.DestroyRenderTarget  = &rtRenDestroyRenderTarget;
 | 
			
		||||
    g_renderer.AllocCommandBuffers  = &rtRenAllocCommandBuffers;
 | 
			
		||||
    g_renderer.SubmitCommandBuffers = &rtRenSubmitCommandBuffers;
 | 
			
		||||
    g_renderer.CreateSemaphores     = &rtRenCreateSemaphores;
 | 
			
		||||
    g_renderer.DestroySemaphores    = &rtRenDestroySemaphores;
 | 
			
		||||
    g_renderer.GetSemaphoreValue    = &rtRenGetSemaphoreValue;
 | 
			
		||||
#endif
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -120,12 +120,20 @@ typedef struct {
 | 
			
		||||
typedef struct {
 | 
			
		||||
    const rt_command_buffer_handle *command_buffers;
 | 
			
		||||
    const rt_gpu_semaphore_handle *wait_semaphores;
 | 
			
		||||
    const uint64_t *wait_values;
 | 
			
		||||
    const rt_gpu_semaphore_handle *signal_semaphores;
 | 
			
		||||
    const uint64_t *signal_values;
 | 
			
		||||
    uint32_t command_buffer_count;
 | 
			
		||||
    uint32_t wait_semaphore_count;
 | 
			
		||||
    uint32_t signal_semaphore_count;
 | 
			
		||||
} rt_submit_command_buffers_info;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    /* Optional, for debug purposes */
 | 
			
		||||
    const char *name;
 | 
			
		||||
    uint64_t initial_value;
 | 
			
		||||
} rt_gpu_semaphore_info;
 | 
			
		||||
 | 
			
		||||
/* Renderer API */
 | 
			
		||||
 | 
			
		||||
typedef void rt_register_renderer_cvars_fn(void);
 | 
			
		||||
@ -139,7 +147,13 @@ typedef void rt_destroy_render_target_fn(rt_render_target_handle handle);
 | 
			
		||||
typedef rt_result rt_alloc_command_buffers_fn(uint32_t count,
 | 
			
		||||
                                              const rt_alloc_command_buffer_info *info,
 | 
			
		||||
                                              rt_command_buffer_handle *p_command_buffers);
 | 
			
		||||
typedef rt_result rt_submit_command_buffers_fn(rt_gpu_queue queue, const rt_submit_command_buffers_info *info);
 | 
			
		||||
typedef rt_result rt_submit_command_buffers_fn(rt_gpu_queue queue,
 | 
			
		||||
                                               const rt_submit_command_buffers_info *info);
 | 
			
		||||
typedef rt_result rt_create_gpu_semaphores_fn(uint32_t count,
 | 
			
		||||
                                              const rt_gpu_semaphore_info *info,
 | 
			
		||||
                                              rt_gpu_semaphore_handle *p_semaphores);
 | 
			
		||||
typedef void rt_destroy_gpu_semaphores_fn(uint32_t count, rt_gpu_semaphore_handle *semaphores);
 | 
			
		||||
typedef uint64_t rt_get_gpu_semaphore_value_fn(rt_gpu_semaphore_handle semaphore);
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    rt_register_renderer_cvars_fn *RegisterCVars;
 | 
			
		||||
@ -152,6 +166,9 @@ typedef struct {
 | 
			
		||||
    rt_destroy_render_target_fn *DestroyRenderTarget;
 | 
			
		||||
    rt_alloc_command_buffers_fn *AllocCommandBuffers;
 | 
			
		||||
    rt_submit_command_buffers_fn *SubmitCommandBuffers;
 | 
			
		||||
    rt_create_gpu_semaphores_fn *CreateSemaphores;
 | 
			
		||||
    rt_destroy_gpu_semaphores_fn *DestroySemaphores;
 | 
			
		||||
    rt_get_gpu_semaphore_value_fn *GetSemaphoreValue;
 | 
			
		||||
} rt_renderer_api;
 | 
			
		||||
 | 
			
		||||
#define RT_RENDERER_API_FN(name) RT_DLLEXPORT rtRen##name
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user