Some checks failed
Ubuntu Cross to Win64 / Cross Compile with ming64 (1.4.0, ubuntu-latest) (push) Failing after 1m41s
104 lines
3.6 KiB
C
104 lines
3.6 KiB
C
#include "command_list.h"
|
|
#include "backend_api.h"
|
|
|
|
#include <runtime/config.h>
|
|
#include <runtime/mem_arena.h>
|
|
#include <runtime/threading.h>
|
|
#include <string.h>
|
|
|
|
RT_CVAR_SZ(r_PerFrameCommandListMemory, "Amount of memory to allocate for single frame command list management."
|
|
" The total amount of memory will be this times the maximum number of frames in flight. (Default: 16 MB)",
|
|
RT_MB(16));
|
|
|
|
static rt_arena _list_arenas[3];
|
|
static rt_arena *_current_arena = &_list_arenas[0];
|
|
static unsigned int _current_arena_idx = 0;
|
|
static rt_mutex *_mutex;
|
|
|
|
rt_result InitCommandLists(void) {
|
|
_mutex = rtCreateMutex();
|
|
if (!_mutex)
|
|
return RT_UNKNOWN_ERROR;
|
|
|
|
for (unsigned int i = 0; i < RT_ARRAY_COUNT(_list_arenas); ++i) {
|
|
rt_create_arena_result arena_res = rtCreateArena(NULL, r_PerFrameCommandListMemory.sz);
|
|
if (!arena_res.ok) {
|
|
rtDestroyMutex(_mutex);
|
|
return RT_OUT_OF_MEMORY;
|
|
}
|
|
_list_arenas[i] = arena_res.arena;
|
|
}
|
|
return RT_SUCCESS;
|
|
}
|
|
|
|
void ShutdownCommandLists(void) {
|
|
for (unsigned int i = 0; i < RT_ARRAY_COUNT(_list_arenas); ++i) {
|
|
rtReleaseArena(&_list_arenas[i]);
|
|
}
|
|
rtDestroyMutex(_mutex);
|
|
}
|
|
|
|
void CommandListsOnBeginFrame(void) {
|
|
_current_arena_idx = (_current_arena_idx + 1) % RT_ARRAY_COUNT(_list_arenas);
|
|
_current_arena = &_list_arenas[_current_arena_idx];
|
|
rtArenaClear(_current_arena);
|
|
}
|
|
|
|
#define COMMAND_LIST_CAPACITY RT_KB(512)
|
|
#define AVERAGE_COMMAND_DATA_SIZE sizeof(rt_draw_indirect_data)
|
|
#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) {
|
|
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);
|
|
rtUnlockMutex(_mutex);
|
|
if (!mem) {
|
|
rtReportError("RENDERER", "Ran out of memory for command lists.");
|
|
return (rt_begin_render_command_list_result){.result = RT_OUT_OF_MEMORY};
|
|
}
|
|
rt_render_command_list list = {
|
|
.headers = mem,
|
|
.data = (void *)((rt_render_command_header *)mem + COMMAND_LIST_MAX_LENGTH),
|
|
.length = 0u,
|
|
.data_capacity = COMMAND_LIST_CAPACITY,
|
|
.data_end = 0u
|
|
};
|
|
return (rt_begin_render_command_list_result){
|
|
.result = RT_SUCCESS,
|
|
.list = list
|
|
};
|
|
}
|
|
|
|
/* 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) {
|
|
size_t data_size = 0u;
|
|
switch (type) {
|
|
case RT_RENDER_COMMAND_DRAW_INDIRECT:
|
|
data_size = sizeof(rt_draw_indirect_data);
|
|
break;
|
|
default:
|
|
rtReportError("RENDERER", "Invalid render command type %u", type);
|
|
return RT_INVALID_VALUE;
|
|
}
|
|
|
|
if (list->length == COMMAND_LIST_MAX_LENGTH || (list->data_end + data_size) > list->data_capacity) {
|
|
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);
|
|
list->data_end += data_size;
|
|
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) {
|
|
return g_device_i.SubmitCommandList(g_device_i.o, list);
|
|
}
|