feat(renderer): Virtual resource registry first version
Some checks failed
Ubuntu Cross to Win64 / Cross Compile with ming64 (1.4.0, ubuntu-latest) (push) Failing after 1m37s

This commit is contained in:
Kevin Trogant 2024-07-31 21:23:07 +02:00
parent 3a7bca385c
commit e25dde131a
6 changed files with 288 additions and 2 deletions

View File

@ -1,9 +1,12 @@
#include "renderer.h"
#include "backend_api.h"
#include "runtime/runtime.h"
#include <SDL2/SDL_syswm.h>
#include <runtime/config.h>
RT_CVAR_S(rt_Renderer, "The used renderer. Available options: vk, dx11. (Default: vk)", "vk");
extern rt_cvar r_MaxRenderResources;
RT_DLLEXPORT void rtRegisterRenderCVARs(void) {
rtRegisterCVAR(&rt_Renderer);
@ -13,10 +16,23 @@ RT_DLLEXPORT void rtRegisterRenderBackendCVARs(void) {
g_render_backend.RegisterCVARs();
}
rt_render_device_i g_device_i;
extern rt_result InitVirtualResourceRegistry(void);
extern void ShutdownVirtualResourceRegistry(void);
RT_DLLEXPORT rt_result rtInitRenderer(const rt_renderer_window_info *info) {
rt_render_backend_init_result backend_res = g_render_backend.Init(info);
return backend_res.result;
if (backend_res.result != RT_SUCCESS)
return backend_res.result;
g_device_i = backend_res.device;
rt_result res;
if ((res = InitVirtualResourceRegistry()) != RT_SUCCESS) {
g_render_backend.Shutdown();
return res;
}
return res;
}
RT_DLLEXPORT void rtShutdownRenderer(void) {

View File

@ -19,11 +19,14 @@ renderer_lib = library('renderer',
'backend_api.h',
'renderer.h',
'render_mesh.h',
'render_resource.h',
'virtual_resource_registry.h',
'init.c',
'load_stub.c',
'meshlet_pools.c',
'render_mesh.c',
'virtual_resource_registry.c',
dependencies: [m_dep, thread_dep],
link_with: renderer_link_libs,
include_directories: engine_incdir,

View File

@ -0,0 +1,97 @@
#ifndef RT_RENDERER_RENDER_RESOURCE_H
#define RT_RENDERER_RENDER_RESOURCE_H
#include <stdint.h>
#include <runtime/runtime.h>
#include <runtime/resources.h>
typedef enum {
RT_RENDER_RESOURCE_TYPE_INVALID,
RT_RENDER_RESOURCE_TYPE_BUFFER,
RT_RENDER_RESOURCE_TYPE_TEXTURE2D,
/* Max is 2**6 = 64 */
} rt_render_resource_type;
/* Handle to a render resource.
* The layout is:
* | type : 6 | version : 6 | index : 20 |
* MSB LSB
*/
typedef struct {
uint32_t value;
} rt_render_resource_handle;
#define RT_RENDER_RESOURCE_MAX_VERSION 0x3f
/* Extract the type part of a render resource handle */
static RT_INLINE rt_render_resource_type rtGetRenderResourceHandleType(rt_render_resource_handle h) {
return (rt_render_resource_type)((h.value >> 26) & 0x3f);
}
/* Extract the version part of a render resource handle */
static RT_INLINE uint32_t rtGetRenderResourceHandleVersion(rt_render_resource_handle h) {
return (h.value >> 20) & 0x3f;
}
/* Extract the index part of a render resource handle */
static RT_INLINE uint32_t rtGetRenderResourceHandleIndex(rt_render_resource_handle h) {
return h.value & 0xfffff;
}
/* Create a render resource handle. This only does the required bit-shifting, it does not actually register any resource for the handle. */
static RT_INLINE rt_render_resource_handle rtMakeRenderResourceHandle(rt_render_resource_type type, uint32_t version, uint32_t index) {
rt_render_resource_handle h;
h.value = ((type & 0x3f) << 26u) | ((version & 0x3f) << 20u) | (index & 0xfffff);
return h;
}
/* Resource description structs */
typedef enum {
RT_RENDER_BUFFER_USAGE_NONE = 0,
RT_RENDER_BUFFER_USAGE_VERTEX_BUFFER = 0x01,
RT_RENDER_BUFFER_USAGE_INDEX_BUFFER = 0x02,
RT_RENDER_BUFFER_USAGE_STORAGE_BUFFER = 0x04,
/* The buffer will be used as a source to populate other resources
* with data */
RT_RENDER_BUFFER_USAGE_UPLOAD_BUFFER = 0x10,
} rt_render_buffer_usage_flags;
typedef enum {
/* The buffer can reside in memory that can only be accessed by the GPU */
RT_RENDER_BUFFER_ACCESS_GPU_ONLY = 0x01,
/* The buffer needs to be in CPU accessible memory */
RT_RENDER_BUFFER_ACCESS_CPU_AND_GPU = 0x02,
/* The buffer is short-lived (will be destroyed at the end of the frame) */
RT_RENDER_BUFFER_ACCESS_TRANSIENT = 0x04,
} rt_render_buffer_access_flags;
/* Describes a gpu buffer */
typedef struct {
/* The required size in bytes */
size_t size;
/* Bitmask describing the usage of the buffer */
rt_render_buffer_usage_flags usage;
/* Bitmask describing the access the buffer needs to support */
rt_render_buffer_access_flags access;
/* ResourceID of the resource that will be used to populate this buffer. */
rt_resource_id source_resource;
} rt_render_buffer_desc;
/* Describes a gpu texture */
typedef struct {
/* Width in pixels */
uint32_t width;
/* Height in pixels */
uint32_t height;
} rt_render_texture2d_desc;
#endif

View File

@ -42,7 +42,6 @@ RT_DLLEXPORT rt_result rtLoadRenderBackend(void);
RT_DLLEXPORT void rtRegisterRenderBackendCVARs(void);
RT_DLLEXPORT rt_result rtInitRenderer(const rt_renderer_window_info *window);
RT_DLLEXPORT void rtShutdownRenderer(void);

View File

@ -0,0 +1,138 @@
#include <runtime/config.h>
#include <runtime/threading.h>
#include <runtime/runtime.h>
#include <stdlib.h>
#include <string.h>
#include "virtual_resource_registry.h"
#include "render_resource.h"
RT_CVAR_SZ(r_MaxRenderResources, "Maximum number of render resources that can exist simultaneously. (Default: 16384)", 16384);
typedef struct {
rt_render_resource_handle *handles;
struct {
union {
/* For management */
uint32_t next_free;
rt_render_buffer_desc buffer;
rt_render_texture2d_desc texture2d;
};
} *descs;
uint32_t first_free;
rt_rwlock lock;
} rt_description_table;
static rt_description_table _description_tab;
rt_result InitVirtualResourceRegistry(void) {
_description_tab.handles = calloc(r_MaxRenderResources.sz, sizeof(rt_render_resource_handle));
if (!_description_tab.handles)
return RT_OUT_OF_MEMORY;
_description_tab.descs = calloc(r_MaxRenderResources.sz, sizeof(*_description_tab.descs));
if (!_description_tab.descs) {
free(_description_tab.handles);
return RT_OUT_OF_MEMORY;
}
rt_create_rwlock_result lock_res = rtCreateRWLock();
if (!lock_res.ok) {
free(_description_tab.handles);
free(_description_tab.descs);
return RT_UNKNOWN_ERROR;
}
_description_tab.lock = lock_res.lock;
_description_tab.first_free = 0;
for (uint32_t i = 0; i < r_MaxRenderResources.sz; ++i) {
_description_tab.descs[i].next_free = i + 1;
}
return RT_SUCCESS;
}
void ShutdownVirtualResourceRegistry(void) {
free(_description_tab.handles);
free(_description_tab.descs);
rtDestroyRWLock(&_description_tab.lock);
}
/* Returns true if the handle refers to an existing resource. */
bool rtIsRenderResourceKnown(rt_render_resource_handle h) {
uint32_t idx = rtGetRenderResourceHandleIndex(h);
if (idx >= r_MaxRenderResources.sz)
return false;
rtLockRead(&_description_tab.lock);
bool is_known = _description_tab.handles[idx].value == h.value;
rtUnlockRead(&_description_tab.lock);
return is_known;
}
static const void *GetResourceDescription(rt_render_resource_handle h) {
rt_render_resource_type type = rtGetRenderResourceHandleType(h);
uint32_t idx = rtGetRenderResourceHandleIndex(h);
if (idx >= r_MaxRenderResources.sz)
return false;
const void *desc = NULL;
rtLockRead(&_description_tab.lock);
if (_description_tab.handles[idx].value == h.value) {
switch (type) {
case RT_RENDER_RESOURCE_TYPE_BUFFER:
desc = &_description_tab.descs[idx].buffer;
break;
case RT_RENDER_RESOURCE_TYPE_TEXTURE2D:
desc = &_description_tab.descs[idx].texture2d;
break;
default:
desc = NULL;
break;
}
}
rtUnlockRead(&_description_tab.lock);
return desc;
}
/* Returns a pointer to the resource description or NULL, if the handle does not refer to a valid buffer */
const rt_render_buffer_desc *rtGetRenderBufferDescription(rt_render_resource_handle h) {
return GetResourceDescription(h);
}
/* Returns a pointer to the resource description or NULL, if the handle does not refer to a valid texture2d */
const rt_render_texture2d_desc *rtGetRenderTexture2DDescription(rt_render_resource_handle h) {
return GetResourceDescription(h);
}
static rt_render_resource_handle AllocSlot(rt_render_resource_type type, const void *desc) {
rt_render_resource_handle h = rtMakeRenderResourceHandle(RT_RENDER_RESOURCE_TYPE_INVALID, 0, 0);
rtLockWrite(&_description_tab.lock);
uint32_t slot = _description_tab.first_free;
if (slot < r_MaxRenderResources.sz) {
_description_tab.first_free = _description_tab.descs[slot].next_free;
uint32_t current_version = rtGetRenderResourceHandleVersion(_description_tab.handles[slot]);
uint32_t next_version = (current_version + 1) & RT_RENDER_RESOURCE_MAX_VERSION;
h = rtMakeRenderResourceHandle(type, next_version, slot);
_description_tab.handles[slot] = h;
switch (type) {
case RT_RENDER_RESOURCE_TYPE_BUFFER:
memcpy(&_description_tab.descs[slot].buffer, desc, sizeof(rt_render_buffer_desc));
break;
case RT_RENDER_RESOURCE_TYPE_TEXTURE2D:
memcpy(&_description_tab.descs[slot].texture2d, desc, sizeof(rt_render_texture2d_desc));
break;
default:
rtReportError("RENDERER", "Tried to create a resource with invalid type %u", type);
break;
}
}
rtUnlockWrite(&_description_tab.lock);
return h;
}
/* Stores the render buffer description and returns a handle to the new resource. */
rt_render_resource_handle rtCreateRenderBuffer(const rt_render_buffer_desc *desc) {
return AllocSlot(RT_RENDER_RESOURCE_TYPE_BUFFER, desc);
}
/* Stores the texture2d description and returns a handle to the new resource. */
rt_render_resource_handle rtCreateRenderTexture2D(const rt_render_texture2d_desc *desc) {
return AllocSlot(RT_RENDER_RESOURCE_TYPE_TEXTURE2D, desc);
}

View File

@ -0,0 +1,33 @@
#ifndef RT_RENDERER_VIRTUAL_RESOURCE_REGISTRY_H
#define RT_RENDERER_VIRTUAL_RESOURCE_REGISTRY_H
#include <stdbool.h>
#include <runtime/runtime.h>
#include "render_resource.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Returns true if the handle refers to an existing resource. */
bool rtIsRenderResourceKnown(rt_render_resource_handle h);
/* Returns a pointer to the resource description or NULL, if the handle does not refer to a valid buffer */
const rt_render_buffer_desc *rtGetRenderBufferDescription(rt_render_resource_handle h);
/* Returns a pointer to the resource description or NULL, if the handle does not refer to a valid texture2d */
const rt_render_texture2d_desc *rtGetRenderTexture2DDescription(rt_render_resource_handle h);
/* Stores the render buffer description and returns a handle to the new resource. */
rt_render_resource_handle rtCreateRenderBuffer(const rt_render_buffer_desc *desc);
/* Stores the texture2d description and returns a handle to the new resource. */
rt_render_resource_handle rtCreateRenderTexture2D(const rt_render_texture2d_desc *desc);
#ifdef __cplusplus
}
#endif
#endif