Load framegraphs from resource files
This commit is contained in:
parent
bdd3db98bb
commit
cc49a017f9
64
assets/test.framegraph
Normal file
64
assets/test.framegraph
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
render_targets {
|
||||||
|
color0 {
|
||||||
|
format R8G8B8A8_SRGB;
|
||||||
|
width 1024;
|
||||||
|
height 768;
|
||||||
|
sample_count 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
swapchain_out {
|
||||||
|
format SWAPCHAIN;
|
||||||
|
width SWAPCHAIN;
|
||||||
|
height SWAPCHAIN;
|
||||||
|
sample_count 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
depth0 {
|
||||||
|
format DEPTH24_STENCIL8;
|
||||||
|
width 512;
|
||||||
|
height 384;
|
||||||
|
sample_count 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
passes {
|
||||||
|
pass0 {
|
||||||
|
writes {
|
||||||
|
color0 {
|
||||||
|
clear_value {
|
||||||
|
r 1.0;
|
||||||
|
g 1.0;
|
||||||
|
b 1.0;
|
||||||
|
a 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
clear YES;
|
||||||
|
discard NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
depth0 {
|
||||||
|
clear_value {
|
||||||
|
d 0.0;
|
||||||
|
s 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
clear YES;
|
||||||
|
discard YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pass1 {
|
||||||
|
reads {
|
||||||
|
color0 {
|
||||||
|
mode SAMPLED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
writes {
|
||||||
|
swapchain_out {
|
||||||
|
clear NO;
|
||||||
|
discard NO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -28,6 +28,8 @@ elif compiler.get_argument_syntax() == 'msvc'
|
|||||||
if buildtype == 'debug'
|
if buildtype == 'debug'
|
||||||
add_project_arguments(['/RTCsu'], language : ['c', 'cpp'])
|
add_project_arguments(['/RTCsu'], language : ['c', 'cpp'])
|
||||||
endif
|
endif
|
||||||
|
# Allow nameless struct/unions (standard in C11)
|
||||||
|
add_project_arguments(['/wd4201'], language : 'cpp')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if get_option('default_library') == 'static'
|
if get_option('default_library') == 'static'
|
||||||
@ -98,6 +100,7 @@ if get_option('build_asset_compiler')
|
|||||||
|
|
||||||
'src/runtime/asset_compiler.c',
|
'src/runtime/asset_compiler.c',
|
||||||
'src/runtime/description_parser.c',
|
'src/runtime/description_parser.c',
|
||||||
|
'src/runtime/framegraph_processor.c',
|
||||||
'src/runtime/pipeline_processor.c',
|
'src/runtime/pipeline_processor.c',
|
||||||
'src/runtime/shader_compiler.c',
|
'src/runtime/shader_compiler.c',
|
||||||
]
|
]
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
#include "runtime/gfx.h"
|
#include "runtime/gfx.h"
|
||||||
|
#include "runtime/resources.h"
|
||||||
|
#include "runtime/mem_arena.h"
|
||||||
|
|
||||||
static rt_framegraph *_framegraph;
|
static rt_framegraph *_framegraph;
|
||||||
|
|
||||||
@ -6,6 +8,7 @@ static rt_framegraph *_framegraph;
|
|||||||
void Init(void) {
|
void Init(void) {
|
||||||
rtLog("GAME", "Init");
|
rtLog("GAME", "Init");
|
||||||
|
|
||||||
|
#if 0
|
||||||
rt_render_target_id rt_ids[4] = {rtCalculateRenderTargetID("rt0", sizeof("rt0")),
|
rt_render_target_id rt_ids[4] = {rtCalculateRenderTargetID("rt0", sizeof("rt0")),
|
||||||
rtCalculateRenderTargetID("rt1", sizeof("rt1")),
|
rtCalculateRenderTargetID("rt1", sizeof("rt1")),
|
||||||
rtCalculateRenderTargetID("rt2", sizeof("rt2")),
|
rtCalculateRenderTargetID("rt2", sizeof("rt2")),
|
||||||
@ -54,8 +57,16 @@ void Init(void) {
|
|||||||
};
|
};
|
||||||
rtSetRelptr(&info.render_passes, passes);
|
rtSetRelptr(&info.render_passes, passes);
|
||||||
rtSetRelptr(&info.render_targets, rts);
|
rtSetRelptr(&info.render_targets, rts);
|
||||||
|
#endif
|
||||||
|
|
||||||
_framegraph = rtCreateFramegraph(&info);
|
rt_resource_id id = rtGetResourceID("assets/test.framegraph");
|
||||||
|
rt_temp_arena temp = rtGetTemporaryArena(NULL, 0);
|
||||||
|
rt_resource *resource =
|
||||||
|
rtArenaPush(temp.arena, rtGetResourceSize(id));
|
||||||
|
|
||||||
|
rtGetResource(id, resource);
|
||||||
|
|
||||||
|
_framegraph = rtCreateFramegraph(resource->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Called after exiting the main-loop and before the runtime starts its shutdown */
|
/* Called after exiting the main-loop and before the runtime starts its shutdown */
|
||||||
|
@ -2,10 +2,26 @@
|
|||||||
|
|
||||||
VkFormat rtPixelFormatToVkFormat(rt_pixel_format format) {
|
VkFormat rtPixelFormatToVkFormat(rt_pixel_format format) {
|
||||||
switch (format) {
|
switch (format) {
|
||||||
|
case RT_PIXEL_FORMAT_R8G8B8A8_UNORM:
|
||||||
|
return VK_FORMAT_R8G8B8A8_UNORM;
|
||||||
|
case RT_PIXEL_FORMAT_B8G8R8A8_UNORM:
|
||||||
|
return VK_FORMAT_B8G8R8A8_UNORM;
|
||||||
case RT_PIXEL_FORMAT_R8G8B8A8_SRGB:
|
case RT_PIXEL_FORMAT_R8G8B8A8_SRGB:
|
||||||
return VK_FORMAT_R8G8B8A8_SRGB;
|
return VK_FORMAT_R8G8B8A8_SRGB;
|
||||||
|
case RT_PIXEL_FORMAT_B8G8R8A8_SRGB:
|
||||||
|
return VK_FORMAT_B8G8R8A8_SRGB;
|
||||||
|
case RT_PIXEL_FORMAT_R8G8B8_UNORM:
|
||||||
|
return VK_FORMAT_R8G8B8_UNORM;
|
||||||
|
case RT_PIXEL_FORMAT_B8G8R8_UNORM:
|
||||||
|
return VK_FORMAT_B8G8R8_UNORM;
|
||||||
|
case RT_PIXEL_FORMAT_R8G8B8_SRGB:
|
||||||
|
return VK_FORMAT_R8G8B8_SRGB;
|
||||||
|
case RT_PIXEL_FORMAT_B8G8R8_SRGB:
|
||||||
|
return VK_FORMAT_B8G8R8_SRGB;
|
||||||
case RT_PIXEL_FORMAT_DEPTH24_STENCIL8:
|
case RT_PIXEL_FORMAT_DEPTH24_STENCIL8:
|
||||||
return VK_FORMAT_D24_UNORM_S8_UINT;
|
return VK_FORMAT_D24_UNORM_S8_UINT;
|
||||||
|
case RT_PIXEL_FORMAT_DEPTH32:
|
||||||
|
return VK_FORMAT_D32_SFLOAT;
|
||||||
default:
|
default:
|
||||||
return VK_FORMAT_UNDEFINED;
|
return VK_FORMAT_UNDEFINED;
|
||||||
}
|
}
|
||||||
@ -20,6 +36,8 @@ VkSampleCountFlagBits rtSampleCountToFlags(unsigned int count) {
|
|||||||
while (count > 1) {
|
while (count > 1) {
|
||||||
if ((counts & count) == 0)
|
if ((counts & count) == 0)
|
||||||
count >>= 1;
|
count >>= 1;
|
||||||
|
else
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return (VkSampleCountFlagBits)count;
|
return (VkSampleCountFlagBits)count;
|
||||||
}
|
}
|
@ -175,7 +175,7 @@ rt_render_target_handle RT_RENDERER_API_FN(CreateRenderTarget)(const rt_render_t
|
|||||||
slot->render_target.format = g_swapchain.format;
|
slot->render_target.format = g_swapchain.format;
|
||||||
slot->render_target.match_swapchain |= RT_RENDER_TARGET_MATCH_SWAPCHAIN_FORMAT;
|
slot->render_target.match_swapchain |= RT_RENDER_TARGET_MATCH_SWAPCHAIN_FORMAT;
|
||||||
}
|
}
|
||||||
if (info->format == RT_PIXEL_FORMAT_DEPTH24_STENCIL8) {
|
if (info->format == RT_PIXEL_FORMAT_DEPTH24_STENCIL8 || info->format == RT_PIXEL_FORMAT_DEPTH32) {
|
||||||
slot->render_target.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT |
|
slot->render_target.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT |
|
||||||
VK_IMAGE_USAGE_SAMPLED_BIT |
|
VK_IMAGE_USAGE_SAMPLED_BIT |
|
||||||
VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
|
VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
|
||||||
|
@ -65,9 +65,11 @@ static rt_asset_db _asset_db;
|
|||||||
static rt_processing_queue _processing_queue;
|
static rt_processing_queue _processing_queue;
|
||||||
|
|
||||||
extern RT_ASSET_PROCESSOR_FN(PipelineProcessor);
|
extern RT_ASSET_PROCESSOR_FN(PipelineProcessor);
|
||||||
|
extern RT_ASSET_PROCESSOR_FN(FramegraphProcessor);
|
||||||
|
|
||||||
static rt_asset_processor _processors[] = {
|
static rt_asset_processor _processors[] = {
|
||||||
{.file_ext = ".pipeline", .proc = PipelineProcessor}
|
{.file_ext = ".pipeline", .proc = PipelineProcessor},
|
||||||
|
{.file_ext = ".framegraph", .proc = FramegraphProcessor},
|
||||||
};
|
};
|
||||||
|
|
||||||
static void ProcessorThreadEntry(void *);
|
static void ProcessorThreadEntry(void *);
|
||||||
|
@ -17,10 +17,34 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
float v[4];
|
||||||
|
struct {
|
||||||
|
float r;
|
||||||
|
float g;
|
||||||
|
float b;
|
||||||
|
float a;
|
||||||
|
};
|
||||||
|
} rt_color;
|
||||||
|
|
||||||
|
/* NOTE(kevin): When you add a value here, you need to handle them in
|
||||||
|
* framegraph_processor.c : ParseFramegraph
|
||||||
|
* and in the render target and texture functions of all renderers. */
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
RT_PIXEL_FORMAT_INVALID,
|
RT_PIXEL_FORMAT_INVALID,
|
||||||
|
|
||||||
|
RT_PIXEL_FORMAT_R8G8B8A8_UNORM,
|
||||||
|
RT_PIXEL_FORMAT_B8G8R8A8_UNORM,
|
||||||
RT_PIXEL_FORMAT_R8G8B8A8_SRGB,
|
RT_PIXEL_FORMAT_R8G8B8A8_SRGB,
|
||||||
|
RT_PIXEL_FORMAT_B8G8R8A8_SRGB,
|
||||||
|
RT_PIXEL_FORMAT_R8G8B8_UNORM,
|
||||||
|
RT_PIXEL_FORMAT_B8G8R8_UNORM,
|
||||||
|
RT_PIXEL_FORMAT_R8G8B8_SRGB,
|
||||||
|
RT_PIXEL_FORMAT_B8G8R8_SRGB,
|
||||||
|
|
||||||
RT_PIXEL_FORMAT_DEPTH24_STENCIL8,
|
RT_PIXEL_FORMAT_DEPTH24_STENCIL8,
|
||||||
|
RT_PIXEL_FORMAT_DEPTH32,
|
||||||
|
|
||||||
/* Special value indicating whichever format the swapchain uses */
|
/* Special value indicating whichever format the swapchain uses */
|
||||||
RT_PIXEL_FORMAT_SWAPCHAIN,
|
RT_PIXEL_FORMAT_SWAPCHAIN,
|
||||||
@ -28,6 +52,21 @@ typedef enum {
|
|||||||
RT_PIXEL_FORMAT_count,
|
RT_PIXEL_FORMAT_count,
|
||||||
} rt_pixel_format;
|
} rt_pixel_format;
|
||||||
|
|
||||||
|
/* In renderer_api.h -> Not necessary for almost all gfx usage */
|
||||||
|
typedef struct rt_renderer_init_info_s rt_renderer_init_info;
|
||||||
|
|
||||||
|
RT_DLLEXPORT void rtRegisterRendererCVars(void);
|
||||||
|
|
||||||
|
RT_DLLEXPORT rt_result rtInitGFX(rt_renderer_init_info *renderer_info);
|
||||||
|
|
||||||
|
RT_DLLEXPORT void rtShutdownGFX(void);
|
||||||
|
|
||||||
|
/* *********************************************************************
|
||||||
|
* Framegraph API
|
||||||
|
*
|
||||||
|
* The framegraph is used to organize and schedule the work for a frame.
|
||||||
|
* *********************************************************************/
|
||||||
|
|
||||||
/* Special value for the .width and .height fields of rt_render_target_info
|
/* Special value for the .width and .height fields of rt_render_target_info
|
||||||
* to indicate that these should be set to the width or height of the swapchain, respectively. */
|
* to indicate that these should be set to the width or height of the swapchain, respectively. */
|
||||||
#define RT_RENDER_TARGET_SIZE_SWAPCHAIN 0
|
#define RT_RENDER_TARGET_SIZE_SWAPCHAIN 0
|
||||||
@ -44,8 +83,8 @@ typedef struct {
|
|||||||
} rt_render_target_info;
|
} rt_render_target_info;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
RT_RENDER_TARGET_READ_INPUT_ATTACHMENT,
|
|
||||||
RT_RENDER_TARGET_READ_SAMPLED,
|
RT_RENDER_TARGET_READ_SAMPLED,
|
||||||
|
RT_RENDER_TARGET_READ_INPUT_ATTACHMENT,
|
||||||
|
|
||||||
RT_RENDER_TARGET_READ_count,
|
RT_RENDER_TARGET_READ_count,
|
||||||
} rt_render_target_read_mode;
|
} rt_render_target_read_mode;
|
||||||
@ -66,7 +105,7 @@ typedef enum {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
rt_render_target_id render_target;
|
rt_render_target_id render_target;
|
||||||
union {
|
union {
|
||||||
float color[4];
|
rt_color color;
|
||||||
struct {
|
struct {
|
||||||
float depth;
|
float depth;
|
||||||
int32_t stencil;
|
int32_t stencil;
|
||||||
@ -102,20 +141,6 @@ typedef struct {
|
|||||||
rt_render_pass_finalize_fn *Finalize;
|
rt_render_pass_finalize_fn *Finalize;
|
||||||
} rt_render_pass_bind_fns;
|
} rt_render_pass_bind_fns;
|
||||||
|
|
||||||
/* In renderer_api.h -> Not necessary for almost all gfx usage */
|
|
||||||
typedef struct rt_renderer_init_info_s rt_renderer_init_info;
|
|
||||||
|
|
||||||
RT_DLLEXPORT void rtRegisterRendererCVars(void);
|
|
||||||
|
|
||||||
RT_DLLEXPORT rt_result rtInitGFX(rt_renderer_init_info *renderer_info);
|
|
||||||
|
|
||||||
RT_DLLEXPORT void rtShutdownGFX(void);
|
|
||||||
|
|
||||||
|
|
||||||
/* Framegraph API
|
|
||||||
*
|
|
||||||
* The framegraph is used to organize and schedule the work for a frame.
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct rt_framegraph_s rt_framegraph;
|
typedef struct rt_framegraph_s rt_framegraph;
|
||||||
|
|
||||||
|
@ -310,6 +310,7 @@ static bool ValidateInfo(const rt_framegraph_info *info) {
|
|||||||
rtReportError(
|
rtReportError(
|
||||||
"GFX",
|
"GFX",
|
||||||
"Framegraph pass %u reads too many rendertargets: %u (maximum allowed is %u)",
|
"Framegraph pass %u reads too many rendertargets: %u (maximum allowed is %u)",
|
||||||
|
i,
|
||||||
passes[i].read_render_target_count,
|
passes[i].read_render_target_count,
|
||||||
RT_RENDERPASS_MAX_READS);
|
RT_RENDERPASS_MAX_READS);
|
||||||
return false;
|
return false;
|
||||||
@ -317,6 +318,7 @@ static bool ValidateInfo(const rt_framegraph_info *info) {
|
|||||||
rtReportError(
|
rtReportError(
|
||||||
"GFX",
|
"GFX",
|
||||||
"Framegraph pass %u writes too many rendertargets: %u (maximum allowed is %u)",
|
"Framegraph pass %u writes too many rendertargets: %u (maximum allowed is %u)",
|
||||||
|
i,
|
||||||
passes[i].write_render_target_count,
|
passes[i].write_render_target_count,
|
||||||
RT_RENDERPASS_MAX_WRITES);
|
RT_RENDERPASS_MAX_WRITES);
|
||||||
return false;
|
return false;
|
||||||
|
@ -98,6 +98,16 @@ static size_t GetResourceDataSize(const rt_resource *resource) {
|
|||||||
const rt_shader_info *info = resource->data;
|
const rt_shader_info *info = resource->data;
|
||||||
return sizeof(rt_shader_info) + (info) ? info->bytecode_length : 0;
|
return sizeof(rt_shader_info) + (info) ? info->bytecode_length : 0;
|
||||||
} break;
|
} break;
|
||||||
|
case RT_RESOURCE_FRAMEGRAPH: {
|
||||||
|
const rt_framegraph_info *info = resource->data;
|
||||||
|
size_t size = sizeof(*info) + sizeof(rt_render_target_info) * info->render_target_count +
|
||||||
|
sizeof(rt_render_pass_info) * info->render_pass_count;
|
||||||
|
const rt_render_pass_info *passes = rtResolveConstRelptr(&info->render_passes);
|
||||||
|
for (uint32_t i = 0; i < info->render_pass_count; ++i) {
|
||||||
|
size += passes[i].read_render_target_count * sizeof(rt_render_target_read) +
|
||||||
|
passes[i].write_render_target_count * sizeof(rt_render_target_write);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
default:
|
default:
|
||||||
rtLog("RESMGR", "Tried to get size of an invalid resource type %u", resource->type);
|
rtLog("RESMGR", "Tried to get size of an invalid resource type %u", resource->type);
|
||||||
}
|
}
|
||||||
@ -117,8 +127,38 @@ static void CopyResourceData(const rt_resource *resource, void *dest) {
|
|||||||
memcpy(dest_info + 1, rtResolveConstRelptr(&info->bytecode), info->bytecode_length);
|
memcpy(dest_info + 1, rtResolveConstRelptr(&info->bytecode), info->bytecode_length);
|
||||||
rtSetRelptr(&dest_info->bytecode, (void *)(dest_info + 1));
|
rtSetRelptr(&dest_info->bytecode, (void *)(dest_info + 1));
|
||||||
} break;
|
} break;
|
||||||
|
case RT_RESOURCE_FRAMEGRAPH: {
|
||||||
|
const rt_framegraph_info *info = resource->data;
|
||||||
|
rt_framegraph_info *dest_info = dest;
|
||||||
|
memcpy(dest_info, info, sizeof(*info));
|
||||||
|
memcpy(dest_info + 1,
|
||||||
|
rtResolveConstRelptr(&info->render_targets),
|
||||||
|
info->render_target_count * sizeof(rt_render_target_info));
|
||||||
|
rtSetRelptr(&dest_info->render_targets, (void *)(dest_info + 1));
|
||||||
|
char *passes_begin =
|
||||||
|
(char *)(dest_info + 1) + info->render_target_count * sizeof(rt_render_target_info);
|
||||||
|
memcpy(passes_begin,
|
||||||
|
rtResolveConstRelptr(&info->render_passes),
|
||||||
|
info->render_pass_count * sizeof(rt_render_pass_info));
|
||||||
|
char *read_write_dest = passes_begin + info->render_pass_count * sizeof(rt_render_pass_info);
|
||||||
|
rt_render_pass_info *passes_dest = (rt_render_pass_info *)passes_begin;
|
||||||
|
const rt_render_pass_info *passes =
|
||||||
|
(const rt_render_pass_info *)rtResolveConstRelptr(&info->render_passes);
|
||||||
|
for (uint32_t i = 0; i < info->render_pass_count; ++i) {
|
||||||
|
rtSetRelptr(&passes_dest[i].read_render_targets, read_write_dest);
|
||||||
|
memcpy(read_write_dest,
|
||||||
|
rtResolveConstRelptr(&passes[i].read_render_targets),
|
||||||
|
sizeof(rt_render_target_read) * passes[i].read_render_target_count);
|
||||||
|
read_write_dest += sizeof(rt_render_target_read) * passes[i].read_render_target_count;
|
||||||
|
rtSetRelptr(&passes_dest[i].write_render_targets, read_write_dest);
|
||||||
|
memcpy(read_write_dest,
|
||||||
|
rtResolveConstRelptr(&passes[i].write_render_targets),
|
||||||
|
sizeof(rt_render_target_write) * passes[i].write_render_target_count);
|
||||||
|
read_write_dest += sizeof(rt_render_target_write) * passes[i].write_render_target_count;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
default:
|
default:
|
||||||
rtLog("RESMGR", "Tried to get copy a resource of invalid type %u", resource->type);
|
rtLog("RESMGR", "Tried to copy a resource of invalid type %u", resource->type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -749,6 +789,15 @@ RT_DLLEXPORT void rtPrefetchResources(const rt_resource_id *ids, uint32_t count)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RT_DLLEXPORT rt_resource_id rtGetResourceID(const char *name) {
|
||||||
|
size_t name_len = strlen(name);
|
||||||
|
rt_resource_id id = (rt_resource_id)rtHashBytes(name, name_len);
|
||||||
|
if (id == RT_INVALID_RESOURCE_ID || id == RT_TOMBSTONE_ID)
|
||||||
|
id = ~id;
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
RT_DLLEXPORT rt_result rtCreateResources(uint32_t count,
|
RT_DLLEXPORT rt_result rtCreateResources(uint32_t count,
|
||||||
const char **names,
|
const char **names,
|
||||||
const rt_resource *resources,
|
const rt_resource *resources,
|
||||||
@ -764,11 +813,7 @@ RT_DLLEXPORT rt_result rtCreateResources(uint32_t count,
|
|||||||
|
|
||||||
rtLockWrite(&_namespace.lock);
|
rtLockWrite(&_namespace.lock);
|
||||||
for (uint32_t i = 0; i < count; ++i) {
|
for (uint32_t i = 0; i < count; ++i) {
|
||||||
size_t name_len = strlen(names[i]);
|
rt_resource_id id = rtGetResourceID(names[i]);
|
||||||
rt_resource_id id = (rt_resource_id)rtHashBytes(names[i], name_len);
|
|
||||||
if (id == RT_INVALID_RESOURCE_ID || id == RT_TOMBSTONE_ID)
|
|
||||||
id = ~id;
|
|
||||||
|
|
||||||
bool inserted = false;
|
bool inserted = false;
|
||||||
for (size_t j = 0; j < ns_size; ++j) {
|
for (size_t j = 0; j < ns_size; ++j) {
|
||||||
size_t at = (id + j) % ns_size;
|
size_t at = (id + j) % ns_size;
|
||||||
|
@ -35,6 +35,8 @@ typedef enum {
|
|||||||
/* A pipeline state object */
|
/* A pipeline state object */
|
||||||
RT_RESOURCE_PIPELINE,
|
RT_RESOURCE_PIPELINE,
|
||||||
|
|
||||||
|
RT_RESOURCE_FRAMEGRAPH,
|
||||||
|
|
||||||
RT_RESOURCE_TYPE_count,
|
RT_RESOURCE_TYPE_count,
|
||||||
} rt_resource_type;
|
} rt_resource_type;
|
||||||
|
|
||||||
@ -74,6 +76,10 @@ RT_DLLEXPORT void rtPrefetchResources(const rt_resource_id *ids, uint32_t count)
|
|||||||
/* Returns the size of a resource in bytes, or 0 if the resource id is invalid. */
|
/* Returns the size of a resource in bytes, or 0 if the resource id is invalid. */
|
||||||
RT_DLLEXPORT size_t rtGetResourceSize(rt_resource_id id);
|
RT_DLLEXPORT size_t rtGetResourceSize(rt_resource_id id);
|
||||||
|
|
||||||
|
/* Returns the resource id that maps to a given name.
|
||||||
|
* Does not check if a resource with that id does exist. */
|
||||||
|
RT_DLLEXPORT rt_resource_id rtGetResourceID(const char *name);
|
||||||
|
|
||||||
/* Logs information about a resource. Useful for debugging */
|
/* Logs information about a resource. Useful for debugging */
|
||||||
RT_DLLEXPORT void rDebugLogResource(rt_resource_id id, const rt_resource *resource);
|
RT_DLLEXPORT void rDebugLogResource(rt_resource_id id, const rt_resource *resource);
|
||||||
|
|
||||||
|
@ -61,6 +61,26 @@ RT_DLLEXPORT void rtLockWrite(rt_rwlock *lock);
|
|||||||
|
|
||||||
RT_DLLEXPORT void rtUnlockWrite(rt_rwlock *lock);
|
RT_DLLEXPORT void rtUnlockWrite(rt_rwlock *lock);
|
||||||
|
|
||||||
|
/* Semaphore */
|
||||||
|
typedef struct {
|
||||||
|
volatile int counter;
|
||||||
|
int max;
|
||||||
|
rt_condition_var *cond;
|
||||||
|
} rt_semaphore;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
bool ok;
|
||||||
|
rt_semaphore semaphore;
|
||||||
|
} rt_create_semaphore_result;
|
||||||
|
|
||||||
|
RT_DLLEXPORT rt_create_semaphore_result rtCreateSemaphore(int initial_value, int max_value);
|
||||||
|
|
||||||
|
RT_DLLEXPORT void rtDestroySemaphore(rt_semaphore *sem);
|
||||||
|
|
||||||
|
RT_DLLEXPORT void rtSignalSemaphore(rt_semaphore *sem);
|
||||||
|
|
||||||
|
RT_DLLEXPORT void rtWaitOnSemaphore(rt_semaphore *sem);
|
||||||
|
|
||||||
/* Threads */
|
/* Threads */
|
||||||
|
|
||||||
typedef struct rt_thread_s rt_thread;
|
typedef struct rt_thread_s rt_thread;
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
#include "threading.h"
|
#include "threading.h"
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
/* Based on: https://eli.thegreenplace.net/2019/implementing-reader-writer-locks/ */
|
/* Based on: https://eli.thegreenplace.net/2019/implementing-reader-writer-locks/ */
|
||||||
|
|
||||||
RT_DLLEXPORT rt_create_rwlock_result rtCreateRWLock(void) {
|
RT_DLLEXPORT rt_create_rwlock_result rtCreateRWLock(void) {
|
||||||
@ -26,7 +24,7 @@ RT_DLLEXPORT void rtLockRead(rt_rwlock *lock) {
|
|||||||
|
|
||||||
RT_DLLEXPORT void rtUnlockRead(rt_rwlock *lock) {
|
RT_DLLEXPORT void rtUnlockRead(rt_rwlock *lock) {
|
||||||
rtLockConditionVar(lock->cond);
|
rtLockConditionVar(lock->cond);
|
||||||
assert(lock->reader_count > 0);
|
RT_ASSERT(lock->reader_count > 0, "Tried to unlock a read-write lock that is not held.");
|
||||||
--lock->reader_count;
|
--lock->reader_count;
|
||||||
bool signal = lock->reader_count == 0;
|
bool signal = lock->reader_count == 0;
|
||||||
rtUnlockConditionVar(lock->cond, signal);
|
rtUnlockConditionVar(lock->cond, signal);
|
||||||
|
Loading…
Reference in New Issue
Block a user