Add a semaphore type
This commit is contained in:
parent
cc49a017f9
commit
a7339ffd53
611
src/runtime/framegraph_processor.c
Normal file
611
src/runtime/framegraph_processor.c
Normal file
@ -0,0 +1,611 @@
|
||||
#include "asset_compiler.h"
|
||||
#include "buffer_manager.h"
|
||||
#include "description_parser.h"
|
||||
#include "gfx.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef struct {
|
||||
rt_render_target_info *render_targets;
|
||||
rt_render_pass_info *render_passes;
|
||||
rt_render_target_read *reads;
|
||||
rt_render_target_write *writes;
|
||||
uint32_t render_target_count;
|
||||
uint32_t render_pass_count;
|
||||
uint32_t read_capacity;
|
||||
uint32_t write_capacity;
|
||||
uint32_t read_count;
|
||||
uint32_t write_count;
|
||||
} rt_parsed_framegraph;
|
||||
|
||||
static int RenderTargetExists(const rt_framegraph_info *framegraph, rt_render_target_id id) {
|
||||
const rt_render_target_info *render_targets = rtResolveConstRelptr(&framegraph->render_targets);
|
||||
for (uint32_t i = 0; i < framegraph->render_target_count; ++i) {
|
||||
if (render_targets[i].id == id)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static rt_result ParseFramegraph(const char *text,
|
||||
size_t size,
|
||||
const char *file_path,
|
||||
rt_framegraph_info **p_framegraph,
|
||||
rt_arena *arena) {
|
||||
rt_parse_state state;
|
||||
unsigned int root_list;
|
||||
rt_result result = rtParseDescription(text, size, file_path, &root_list, &state, arena);
|
||||
if (result != RT_SUCCESS)
|
||||
return result;
|
||||
|
||||
/* Push on the arena to ensure a continous memory layout */
|
||||
rt_framegraph_info *framegraph = RT_ARENA_PUSH_STRUCT_ZERO(arena, rt_framegraph_info);
|
||||
if (!framegraph)
|
||||
return RT_OUT_OF_MEMORY;
|
||||
|
||||
#pragma region Render Targets
|
||||
const rt_parsed_stmt *rt_list_stmt = rtFindStatement(&state, root_list, "render_targets");
|
||||
if (!rt_list_stmt) {
|
||||
rtLog("AC",
|
||||
"Framegraph %s does not contain a list of render targets. (\"render_targets\")",
|
||||
file_path);
|
||||
return RT_INVALID_VALUE;
|
||||
}
|
||||
if (rt_list_stmt->form != RT_STMT_FORM_LIST) {
|
||||
rtLog("AC", "Expected a list as the value of \"render_targets\" in %s", file_path);
|
||||
return RT_INVALID_VALUE;
|
||||
}
|
||||
const rt_parsed_stmt_list *rt_list = &state.statement_lists[rt_list_stmt->list_index];
|
||||
framegraph->render_target_count = rt_list->count;
|
||||
|
||||
rt_render_target_info *render_targets =
|
||||
RT_ARENA_PUSH_ARRAY_ZERO(arena, rt_render_target_info, framegraph->render_target_count);
|
||||
if (!render_targets)
|
||||
return RT_OUT_OF_MEMORY;
|
||||
rtSetRelptr(&framegraph->render_targets, render_targets);
|
||||
const rt_parsed_stmt *rendertarget_stmt = &state.statements[rt_list->first];
|
||||
for (uint32_t i = 0; i < rt_list->count;
|
||||
++i, rendertarget_stmt = &state.statements[rendertarget_stmt->next]) {
|
||||
if (rendertarget_stmt->form != RT_STMT_FORM_LIST) {
|
||||
rtLog("AC",
|
||||
"Expected a list as the value of \"render_targets.%.*s\" in %s",
|
||||
rendertarget_stmt->attribute.length,
|
||||
rendertarget_stmt->attribute.start,
|
||||
file_path);
|
||||
return RT_INVALID_VALUE;
|
||||
}
|
||||
|
||||
rt_render_target_info rt = {0};
|
||||
rt.id = rtCalculateRenderTargetID(rendertarget_stmt->attribute.start,
|
||||
rendertarget_stmt->attribute.length);
|
||||
|
||||
const rt_parsed_stmt *width_stmt =
|
||||
rtFindStatement(&state, rendertarget_stmt->list_index, "width");
|
||||
if (!width_stmt) {
|
||||
rtLog("AC",
|
||||
"Could not find \"render_targets.%.*s.width\" in %s",
|
||||
rendertarget_stmt->attribute.length,
|
||||
rendertarget_stmt->attribute.start,
|
||||
file_path);
|
||||
return RT_INVALID_VALUE;
|
||||
}
|
||||
if (width_stmt->form != RT_STMT_FORM_VALUE) {
|
||||
rtLog("AC",
|
||||
"Expected a simple value for \"render_targets.%.*s.width\" in %s",
|
||||
rendertarget_stmt->attribute.length,
|
||||
rendertarget_stmt->attribute.start,
|
||||
file_path);
|
||||
return RT_INVALID_VALUE;
|
||||
}
|
||||
if (rtCompareSpanToString(width_stmt->value, "SWAPCHAIN") == 0)
|
||||
rt.width = RT_RENDER_TARGET_SIZE_SWAPCHAIN;
|
||||
else
|
||||
sscanf(width_stmt->value.start, "%u", &rt.width);
|
||||
|
||||
const rt_parsed_stmt *height_stmt =
|
||||
rtFindStatement(&state, rendertarget_stmt->list_index, "height");
|
||||
if (!height_stmt) {
|
||||
rtLog("AC",
|
||||
"Could not find \"render_targets.%.*s.height\" in %s",
|
||||
rendertarget_stmt->attribute.length,
|
||||
rendertarget_stmt->attribute.start,
|
||||
file_path);
|
||||
return RT_INVALID_VALUE;
|
||||
}
|
||||
if (height_stmt->form != RT_STMT_FORM_VALUE) {
|
||||
rtLog("AC",
|
||||
"Expected a simple value for \"render_targets.%.*s.height\" in %s",
|
||||
rendertarget_stmt->attribute.length,
|
||||
rendertarget_stmt->attribute.start,
|
||||
file_path);
|
||||
return RT_INVALID_VALUE;
|
||||
}
|
||||
if (rtCompareSpanToString(height_stmt->value, "SWAPCHAIN") == 0)
|
||||
rt.height = RT_RENDER_TARGET_SIZE_SWAPCHAIN;
|
||||
else
|
||||
sscanf(height_stmt->value.start, "%u", &rt.height);
|
||||
|
||||
const rt_parsed_stmt *samples_stmt =
|
||||
rtFindStatement(&state, rendertarget_stmt->list_index, "sample_count");
|
||||
if (!samples_stmt) {
|
||||
rtLog("AC",
|
||||
"Could not find \"render_targets.%.*s.sample_count\" in %s",
|
||||
rendertarget_stmt->attribute.length,
|
||||
rendertarget_stmt->attribute.start,
|
||||
file_path);
|
||||
return RT_INVALID_VALUE;
|
||||
}
|
||||
if (samples_stmt->form != RT_STMT_FORM_VALUE) {
|
||||
rtLog("AC",
|
||||
"Expected a simple value for \"render_targets.%.*s.sample_count\" in %s",
|
||||
rendertarget_stmt->attribute.length,
|
||||
rendertarget_stmt->attribute.start,
|
||||
file_path);
|
||||
return RT_INVALID_VALUE;
|
||||
}
|
||||
sscanf(samples_stmt->value.start, "%u", &rt.sample_count);
|
||||
|
||||
const rt_parsed_stmt *format_stmt =
|
||||
rtFindStatement(&state, rendertarget_stmt->list_index, "format");
|
||||
if (!format_stmt) {
|
||||
rtLog("AC",
|
||||
"Could not find \"render_targets.%.*s.format\" in %s",
|
||||
rendertarget_stmt->attribute.length,
|
||||
rendertarget_stmt->attribute.start,
|
||||
file_path);
|
||||
return RT_INVALID_VALUE;
|
||||
}
|
||||
if (format_stmt->form != RT_STMT_FORM_VALUE) {
|
||||
rtLog("AC",
|
||||
"Expected a simple value for \"render_targets.%.*s.format\" in %s",
|
||||
rendertarget_stmt->attribute.length,
|
||||
rendertarget_stmt->attribute.start,
|
||||
file_path);
|
||||
return RT_INVALID_VALUE;
|
||||
}
|
||||
if (rtCompareSpanToString(format_stmt->value, "R8G8B8A8_UNORM") == 0)
|
||||
rt.format = RT_PIXEL_FORMAT_R8G8B8A8_UNORM;
|
||||
else if (rtCompareSpanToString(format_stmt->value, "B8G8R8A8_UNORM") == 0)
|
||||
rt.format = RT_PIXEL_FORMAT_B8G8R8A8_UNORM;
|
||||
else if (rtCompareSpanToString(format_stmt->value, "R8G8B8A8_SRGB") == 0)
|
||||
rt.format = RT_PIXEL_FORMAT_R8G8B8A8_SRGB;
|
||||
else if (rtCompareSpanToString(format_stmt->value, "B8G8R8A8_SRGB") == 0)
|
||||
rt.format = RT_PIXEL_FORMAT_B8G8R8A8_SRGB;
|
||||
else if (rtCompareSpanToString(format_stmt->value, "R8G8B8_UNORM") == 0)
|
||||
rt.format = RT_PIXEL_FORMAT_R8G8B8_UNORM;
|
||||
else if (rtCompareSpanToString(format_stmt->value, "B8G8R8_UNORM") == 0)
|
||||
rt.format = RT_PIXEL_FORMAT_B8G8R8_UNORM;
|
||||
else if (rtCompareSpanToString(format_stmt->value, "R8G8B8_SRGB") == 0)
|
||||
rt.format = RT_PIXEL_FORMAT_R8G8B8_SRGB;
|
||||
else if (rtCompareSpanToString(format_stmt->value, "B8G8R8_SRGB") == 0)
|
||||
rt.format = RT_PIXEL_FORMAT_B8G8R8_SRGB;
|
||||
else if (rtCompareSpanToString(format_stmt->value, "DEPTH24_STENCIL8") == 0)
|
||||
rt.format = RT_PIXEL_FORMAT_DEPTH24_STENCIL8;
|
||||
else if (rtCompareSpanToString(format_stmt->value, "DEPTH32") == 0)
|
||||
rt.format = RT_PIXEL_FORMAT_DEPTH32;
|
||||
else if (rtCompareSpanToString(format_stmt->value, "SWAPCHAIN") == 0)
|
||||
rt.format = RT_PIXEL_FORMAT_SWAPCHAIN;
|
||||
else {
|
||||
rt.format = RT_PIXEL_FORMAT_INVALID;
|
||||
rtLog("AC",
|
||||
"Invalid format value \"%.*s\" in \"render_targets.%.*s.format\" in %s",
|
||||
format_stmt->value.length,
|
||||
format_stmt->value.start,
|
||||
rendertarget_stmt->attribute.length,
|
||||
rendertarget_stmt->attribute.start,
|
||||
file_path);
|
||||
return RT_INVALID_VALUE;
|
||||
}
|
||||
|
||||
render_targets[i] = rt;
|
||||
}
|
||||
#pragma endregion Render Targets
|
||||
|
||||
#pragma region Render Passes
|
||||
/* First count the total number of reads and writes */
|
||||
uint32_t total_reads = 0, total_writes = 0;
|
||||
const rt_parsed_stmt *pass_list_stmt = rtFindStatement(&state, root_list, "passes");
|
||||
if (!pass_list_stmt) {
|
||||
rtLog("Framegraph %s does not contain a list of passes (\"passes\")", file_path);
|
||||
return RT_INVALID_VALUE;
|
||||
}
|
||||
if (pass_list_stmt->form != RT_STMT_FORM_LIST) {
|
||||
rtLog("AC", "Expected a list as the value of \"passes\" in %s", file_path);
|
||||
return RT_INVALID_VALUE;
|
||||
}
|
||||
const rt_parsed_stmt_list *pass_list = &state.statement_lists[pass_list_stmt->list_index];
|
||||
rt_render_pass_info *passes =
|
||||
RT_ARENA_PUSH_ARRAY_ZERO(arena, rt_render_pass_info, pass_list->count);
|
||||
if (!passes)
|
||||
return RT_OUT_OF_MEMORY;
|
||||
rtSetRelptr(&framegraph->render_passes, passes);
|
||||
framegraph->render_pass_count = pass_list->count;
|
||||
const rt_parsed_stmt *pass_stmt = &state.statements[pass_list->first];
|
||||
for (uint32_t i = 0; i < pass_list->count;
|
||||
++i, pass_stmt = &state.statements[pass_stmt->next]) {
|
||||
if (pass_stmt->form != RT_STMT_FORM_LIST) {
|
||||
rtLog("AC",
|
||||
"Expected a list as the value of \"passes.%.*s\" in %s",
|
||||
pass_stmt->attribute.length,
|
||||
pass_stmt->attribute.start,
|
||||
file_path);
|
||||
return RT_INVALID_VALUE;
|
||||
}
|
||||
|
||||
passes[i].id =
|
||||
rtCalculateRenderPassID(pass_stmt->attribute.start, pass_stmt->attribute.length);
|
||||
|
||||
const rt_parsed_stmt *write_list_stmt =
|
||||
rtFindStatement(&state, pass_stmt->list_index, "writes");
|
||||
if (write_list_stmt) {
|
||||
if (write_list_stmt->form != RT_STMT_FORM_LIST) {
|
||||
rtLog("AC",
|
||||
"Expected a list as the value of \"passes.%.*s.writes\" in %s",
|
||||
pass_stmt->attribute.length,
|
||||
pass_stmt->attribute.start,
|
||||
file_path);
|
||||
return RT_INVALID_VALUE;
|
||||
}
|
||||
const rt_parsed_stmt_list *write_list =
|
||||
&state.statement_lists[write_list_stmt->list_index];
|
||||
passes[i].write_render_target_count = write_list->count;
|
||||
total_writes += write_list->count;
|
||||
} else {
|
||||
passes[i].write_render_target_count = 0;
|
||||
rtSetRelptr(&passes[i].write_render_targets, NULL);
|
||||
}
|
||||
|
||||
const rt_parsed_stmt *read_list_stmt =
|
||||
rtFindStatement(&state, pass_stmt->list_index, "reads");
|
||||
if (read_list_stmt) {
|
||||
if (read_list_stmt->form != RT_STMT_FORM_LIST) {
|
||||
rtLog("AC",
|
||||
"Expected a list as the value of \"passes.%.*s.reads\" in %s",
|
||||
pass_stmt->attribute.length,
|
||||
pass_stmt->attribute.start,
|
||||
file_path);
|
||||
return RT_INVALID_VALUE;
|
||||
}
|
||||
const rt_parsed_stmt_list *read_list =
|
||||
&state.statement_lists[read_list_stmt->list_index];
|
||||
passes[i].read_render_target_count = read_list->count;
|
||||
total_reads += read_list->count;
|
||||
} else {
|
||||
passes[i].read_render_target_count = 0;
|
||||
rtSetRelptr(&passes[i].read_render_targets, NULL);
|
||||
}
|
||||
}
|
||||
/* Now fill the read & write lists */
|
||||
rt_render_target_read *reads =
|
||||
RT_ARENA_PUSH_ARRAY_ZERO(arena, rt_render_target_read, total_reads);
|
||||
rt_render_target_write *writes =
|
||||
RT_ARENA_PUSH_ARRAY_ZERO(arena, rt_render_target_write, total_writes);
|
||||
if (!reads && total_reads != 0)
|
||||
return RT_OUT_OF_MEMORY;
|
||||
if (!writes && total_writes != 0)
|
||||
return RT_OUT_OF_MEMORY;
|
||||
uint32_t reads_at = 0;
|
||||
uint32_t writes_at = 0;
|
||||
|
||||
pass_stmt = &state.statements[pass_list->first];
|
||||
for (uint32_t i = 0; i < pass_list->count;
|
||||
++i, pass_stmt = &state.statements[pass_stmt->next]) {
|
||||
RT_ASSERT(pass_stmt->form == RT_STMT_FORM_LIST, "");
|
||||
const rt_parsed_stmt *write_list_stmt =
|
||||
rtFindStatement(&state, pass_stmt->list_index, "writes");
|
||||
if (write_list_stmt) {
|
||||
RT_ASSERT(write_list_stmt->form == RT_STMT_FORM_LIST, "");
|
||||
const rt_parsed_stmt_list *write_list =
|
||||
&state.statement_lists[write_list_stmt->list_index];
|
||||
|
||||
rtSetRelptr(&passes[i].write_render_targets, &writes[writes_at]);
|
||||
const rt_parsed_stmt *write_stmt = &state.statements[write_list->first];
|
||||
for (uint32_t j = 0; j < write_list->count;
|
||||
++j, write_stmt = &state.statements[write_stmt->next]) {
|
||||
|
||||
if (write_stmt->form != RT_STMT_FORM_LIST) {
|
||||
rtLog("AC",
|
||||
"Expected a list as the value of \"passes.%.*s.writes.%.*s\" in %s",
|
||||
pass_stmt->attribute.length,
|
||||
pass_stmt->attribute.start,
|
||||
write_stmt->attribute.length,
|
||||
write_stmt->attribute.start,
|
||||
file_path);
|
||||
return RT_INVALID_VALUE;
|
||||
}
|
||||
|
||||
rt_render_target_write *write = &writes[writes_at++];
|
||||
memset(write, 0, sizeof(*write));
|
||||
write->render_target = rtCalculateRenderTargetID(write_stmt->attribute.start,
|
||||
write_stmt->attribute.length);
|
||||
if (!RenderTargetExists(framegraph, write->render_target)) {
|
||||
rtLog("AC",
|
||||
"Referenced unknown render target \"%.s\" in \"passes.%.*s.writes.%.*s\" "
|
||||
"in %s",
|
||||
write_stmt->attribute.length,
|
||||
write_stmt->attribute.start,
|
||||
pass_stmt->attribute.length,
|
||||
pass_stmt->attribute.start,
|
||||
file_path);
|
||||
return RT_INVALID_VALUE;
|
||||
}
|
||||
|
||||
const rt_parsed_stmt *clear_value_stmt =
|
||||
rtFindStatement(&state, write_stmt->list_index, "clear_value");
|
||||
if (clear_value_stmt) {
|
||||
if (clear_value_stmt->form != RT_STMT_FORM_LIST) {
|
||||
rtLog("AC",
|
||||
"Expected a list as the value of "
|
||||
"\"passes.%.*s.writes.%.*s.clear_value\" in %s",
|
||||
pass_stmt->attribute.length,
|
||||
pass_stmt->attribute.start,
|
||||
write_stmt->attribute.length,
|
||||
write_stmt->attribute.start,
|
||||
file_path);
|
||||
return RT_INVALID_VALUE;
|
||||
}
|
||||
const rt_parsed_stmt *r_stmt =
|
||||
rtFindStatement(&state, clear_value_stmt->list_index, "r");
|
||||
if (r_stmt) {
|
||||
if (r_stmt->form != RT_STMT_FORM_VALUE) {
|
||||
rtLog("AC",
|
||||
"Expected a float as the value of "
|
||||
"\"passes.%.*s.writes.%.*s.clear_value.r\" in %s",
|
||||
pass_stmt->attribute.length,
|
||||
pass_stmt->attribute.start,
|
||||
write_stmt->attribute.length,
|
||||
write_stmt->attribute.start,
|
||||
file_path);
|
||||
return RT_INVALID_VALUE;
|
||||
}
|
||||
sscanf(r_stmt->value.start, "%f", &write->clear.color.r);
|
||||
}
|
||||
const rt_parsed_stmt *g_stmt =
|
||||
rtFindStatement(&state, clear_value_stmt->list_index, "g");
|
||||
if (g_stmt) {
|
||||
if (g_stmt->form != RT_STMT_FORM_VALUE) {
|
||||
rtLog("AC",
|
||||
"Expected a float as the value of "
|
||||
"\"passes.%.*s.writes.%.*s.clear_value.g\" in %s",
|
||||
pass_stmt->attribute.length,
|
||||
pass_stmt->attribute.start,
|
||||
write_stmt->attribute.length,
|
||||
write_stmt->attribute.start,
|
||||
file_path);
|
||||
return RT_INVALID_VALUE;
|
||||
}
|
||||
sscanf(g_stmt->value.start, "%f", &write->clear.color.g);
|
||||
}
|
||||
const rt_parsed_stmt *b_stmt =
|
||||
rtFindStatement(&state, clear_value_stmt->list_index, "b");
|
||||
if (b_stmt) {
|
||||
if (b_stmt->form != RT_STMT_FORM_VALUE) {
|
||||
rtLog("AC",
|
||||
"Expected a float as the value of "
|
||||
"\"passes.%.*s.writes.%.*s.clear_value.b\" in %s",
|
||||
pass_stmt->attribute.length,
|
||||
pass_stmt->attribute.start,
|
||||
write_stmt->attribute.length,
|
||||
write_stmt->attribute.start,
|
||||
file_path);
|
||||
return RT_INVALID_VALUE;
|
||||
}
|
||||
sscanf(b_stmt->value.start, "%f", &write->clear.color.b);
|
||||
}
|
||||
const rt_parsed_stmt *a_stmt =
|
||||
rtFindStatement(&state, clear_value_stmt->list_index, "a");
|
||||
if (a_stmt) {
|
||||
if (a_stmt->form != RT_STMT_FORM_VALUE) {
|
||||
rtLog("AC",
|
||||
"Expected a float as the value of "
|
||||
"\"passes.%.*s.writes.%.*s.clear_value.a\" in %s",
|
||||
pass_stmt->attribute.length,
|
||||
pass_stmt->attribute.start,
|
||||
write_stmt->attribute.length,
|
||||
write_stmt->attribute.start,
|
||||
file_path);
|
||||
return RT_INVALID_VALUE;
|
||||
}
|
||||
sscanf(a_stmt->value.start, "%f", &write->clear.color.a);
|
||||
}
|
||||
const rt_parsed_stmt *d_stmt =
|
||||
rtFindStatement(&state, clear_value_stmt->list_index, "d");
|
||||
if (d_stmt) {
|
||||
if (d_stmt->form != RT_STMT_FORM_VALUE) {
|
||||
rtLog("AC",
|
||||
"Expected a float as the value of "
|
||||
"\"passes.%.*s.writes.%.*s.clear_value.d\" in %s",
|
||||
pass_stmt->attribute.length,
|
||||
pass_stmt->attribute.start,
|
||||
write_stmt->attribute.length,
|
||||
write_stmt->attribute.start,
|
||||
file_path);
|
||||
return RT_INVALID_VALUE;
|
||||
}
|
||||
sscanf(d_stmt->value.start, "%f", &write->clear.depth_stencil.depth);
|
||||
}
|
||||
const rt_parsed_stmt *s_stmt =
|
||||
rtFindStatement(&state, clear_value_stmt->list_index, "s");
|
||||
if (s_stmt) {
|
||||
if (s_stmt->form != RT_STMT_FORM_VALUE) {
|
||||
rtLog("AC",
|
||||
"Expected an integer as the value of "
|
||||
"\"passes.%.*s.writes.%.*s.clear_value.s\" in %s",
|
||||
pass_stmt->attribute.length,
|
||||
pass_stmt->attribute.start,
|
||||
write_stmt->attribute.length,
|
||||
write_stmt->attribute.start,
|
||||
file_path);
|
||||
return RT_INVALID_VALUE;
|
||||
}
|
||||
sscanf(s_stmt->value.start, "%d", &write->clear.depth_stencil.stencil);
|
||||
}
|
||||
}
|
||||
|
||||
const rt_parsed_stmt *clear_stmt =
|
||||
rtFindStatement(&state, write_stmt->list_index, "clear");
|
||||
if (clear_stmt) {
|
||||
if (clear_stmt->form != RT_STMT_FORM_VALUE) {
|
||||
rtLog("AC",
|
||||
"Expected a YES or NO as the value of "
|
||||
"\"passes.%.*s.writes.%.*s.clear\" in %s",
|
||||
pass_stmt->attribute.length,
|
||||
pass_stmt->attribute.start,
|
||||
write_stmt->attribute.length,
|
||||
write_stmt->attribute.start,
|
||||
file_path);
|
||||
return RT_INVALID_VALUE;
|
||||
}
|
||||
if (rtCompareSpanToString(clear_stmt->value, "YES") == 0) {
|
||||
write->flags |= RT_RENDER_TARGET_WRITE_CLEAR;
|
||||
} else if (rtCompareSpanToString(clear_stmt->value, "NO") != 0) {
|
||||
rtLog("AC",
|
||||
"Expected a YES or NO as the value of "
|
||||
"\"passes.%.*s.writes.%.*s.clear\" in %s",
|
||||
pass_stmt->attribute.length,
|
||||
pass_stmt->attribute.start,
|
||||
write_stmt->attribute.length,
|
||||
write_stmt->attribute.start,
|
||||
file_path);
|
||||
return RT_INVALID_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
const rt_parsed_stmt *discard_stmt =
|
||||
rtFindStatement(&state, write_stmt->list_index, "discard");
|
||||
if (discard_stmt) {
|
||||
if (discard_stmt->form != RT_STMT_FORM_VALUE) {
|
||||
rtLog("AC",
|
||||
"Expected YES or NO as the value of "
|
||||
"\"passes.%.*s.writes.%.*s.clear\" in %s",
|
||||
pass_stmt->attribute.length,
|
||||
pass_stmt->attribute.start,
|
||||
write_stmt->attribute.length,
|
||||
write_stmt->attribute.start,
|
||||
file_path);
|
||||
return RT_INVALID_VALUE;
|
||||
}
|
||||
if (rtCompareSpanToString(discard_stmt->value, "YES") == 0) {
|
||||
write->flags |= RT_RENDER_TARGET_WRITE_DISCARD;
|
||||
} else if (rtCompareSpanToString(discard_stmt->value, "NO") != 0) {
|
||||
rtLog("AC",
|
||||
"Expected YES or NO as the value of "
|
||||
"\"passes.%.*s.writes.%.*s.discard\" in %s",
|
||||
pass_stmt->attribute.length,
|
||||
pass_stmt->attribute.start,
|
||||
write_stmt->attribute.length,
|
||||
write_stmt->attribute.start,
|
||||
file_path);
|
||||
return RT_INVALID_VALUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const rt_parsed_stmt *read_list_stmt =
|
||||
rtFindStatement(&state, pass_stmt->list_index, "reads");
|
||||
if (read_list_stmt) {
|
||||
RT_ASSERT(read_list_stmt->form == RT_STMT_FORM_LIST, "");
|
||||
const rt_parsed_stmt_list *read_list =
|
||||
&state.statement_lists[read_list_stmt->list_index];
|
||||
|
||||
rtSetRelptr(&passes[i].read_render_targets, &reads[reads_at]);
|
||||
const rt_parsed_stmt *read_stmt = &state.statements[read_list->first];
|
||||
for (uint32_t j = 0; j < read_list->count;
|
||||
++j, read_stmt = &state.statements[read_stmt->next]) {
|
||||
|
||||
if (read_stmt->form != RT_STMT_FORM_LIST) {
|
||||
rtLog("AC",
|
||||
"Expected a list as the value of \"passes.%.*s.reads.%.*s\" in %s",
|
||||
pass_stmt->attribute.length,
|
||||
pass_stmt->attribute.start,
|
||||
read_stmt->attribute.length,
|
||||
read_stmt->attribute.start,
|
||||
file_path);
|
||||
return RT_INVALID_VALUE;
|
||||
}
|
||||
|
||||
rt_render_target_read *read = &reads[reads_at++];
|
||||
memset(read, 0, sizeof(*read));
|
||||
read->render_target = rtCalculateRenderTargetID(read_stmt->attribute.start,
|
||||
read_stmt->attribute.length);
|
||||
if (!RenderTargetExists(framegraph, read->render_target)) {
|
||||
rtLog("AC",
|
||||
"Referenced unknown render target \"%.s\" in \"passes.%.*s.reads.%.*s\" "
|
||||
"in %s",
|
||||
read_stmt->attribute.length,
|
||||
read_stmt->attribute.start,
|
||||
pass_stmt->attribute.length,
|
||||
pass_stmt->attribute.start,
|
||||
file_path);
|
||||
return RT_INVALID_VALUE;
|
||||
}
|
||||
|
||||
const rt_parsed_stmt *mode_stmt =
|
||||
rtFindStatement(&state, read_stmt->list_index, "mode");
|
||||
if (mode_stmt) {
|
||||
if (mode_stmt->form != RT_STMT_FORM_VALUE) {
|
||||
rtLog("AC",
|
||||
"Expected SAMPLED or INPUT_ATTACHMENT as the value of "
|
||||
"\"passes.%.*s.writes.%.*s.mode\" in %s",
|
||||
pass_stmt->attribute.length,
|
||||
pass_stmt->attribute.start,
|
||||
read_stmt->attribute.length,
|
||||
read_stmt->attribute.start,
|
||||
file_path);
|
||||
return RT_INVALID_VALUE;
|
||||
}
|
||||
if (rtCompareSpanToString(mode_stmt->value, "SAMPLED") == 0) {
|
||||
read->mode = RT_RENDER_TARGET_READ_SAMPLED;
|
||||
} else if (rtCompareSpanToString(mode_stmt->value, "INPUT_ATTACHMENT") == 0) {
|
||||
read->mode = RT_RENDER_TARGET_READ_INPUT_ATTACHMENT;
|
||||
} else {
|
||||
rtLog("AC",
|
||||
"Expected SAMPLED or INPUT_ATTACHMENT as the value of "
|
||||
"\"passes.%.*s.writes.%.*s.mode\" in %s",
|
||||
pass_stmt->attribute.length,
|
||||
pass_stmt->attribute.start,
|
||||
read_stmt->attribute.length,
|
||||
read_stmt->attribute.start,
|
||||
file_path);
|
||||
return RT_INVALID_VALUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma region
|
||||
|
||||
*p_framegraph = framegraph;
|
||||
return result;
|
||||
}
|
||||
|
||||
RT_ASSET_PROCESSOR_FN(FramegraphProcessor) {
|
||||
rt_loaded_asset asset = LoadAsset(file);
|
||||
if (!asset.buffer)
|
||||
return RT_UNKNOWN_ERROR;
|
||||
|
||||
rt_framegraph_info *framegraph = NULL;
|
||||
rt_result result =
|
||||
ParseFramegraph(asset.buffer, asset.size, rtGetFilePath(file), &framegraph, arena);
|
||||
if (result != RT_SUCCESS)
|
||||
goto out;
|
||||
|
||||
rt_resource resource = {0};
|
||||
resource.type = RT_RESOURCE_FRAMEGRAPH;
|
||||
resource.data = framegraph;
|
||||
|
||||
rt_resource_id id;
|
||||
const char *name = rtGetFilePath(file);
|
||||
result = rtCreateResources(1, &name, &resource, &id);
|
||||
if (result != RT_SUCCESS)
|
||||
goto out;
|
||||
|
||||
new_resources[0] = id;
|
||||
*new_resource_count = 1;
|
||||
|
||||
out:
|
||||
rtReleaseBuffer(asset.buffer, asset.size);
|
||||
return result;
|
||||
}
|
39
src/runtime/threading_semaphore.c
Normal file
39
src/runtime/threading_semaphore.c
Normal file
@ -0,0 +1,39 @@
|
||||
#include "threading.h"
|
||||
|
||||
|
||||
RT_DLLEXPORT rt_create_semaphore_result rtCreateSemaphore(int initial_value, int max_value) {
|
||||
rt_create_semaphore_result res;
|
||||
res.semaphore.cond = rtCreateConditionVar();
|
||||
if (!res.semaphore.cond) {
|
||||
res.ok = false;
|
||||
return res;
|
||||
}
|
||||
res.semaphore.counter = initial_value;
|
||||
res.semaphore.max = max_value;
|
||||
res.ok = true;
|
||||
return res;
|
||||
}
|
||||
|
||||
RT_DLLEXPORT void rtDestroySemaphore(rt_semaphore *sem) {
|
||||
rtDestroyConditionVar(sem->cond);
|
||||
sem->cond = NULL;
|
||||
sem->counter = 0;
|
||||
sem->max = 0;
|
||||
}
|
||||
|
||||
RT_DLLEXPORT void rtSignalSemaphore(rt_semaphore *sem) {
|
||||
rtLockConditionVar(sem->cond);
|
||||
RT_ASSERT(sem->counter < sem->max,
|
||||
"Tried to signal a semaphore that has reached its maximum value.");
|
||||
++sem->counter;
|
||||
rtUnlockConditionVar(sem->cond, true);
|
||||
}
|
||||
|
||||
RT_DLLEXPORT void rtWaitOnSemaphore(rt_semaphore *sem) {
|
||||
rtLockConditionVar(sem->cond);
|
||||
while (sem->counter == 0) {
|
||||
rtWaitOnConditionVar(sem->cond);
|
||||
}
|
||||
--sem->counter;
|
||||
rtUnlockConditionVar(sem->cond, false);
|
||||
}
|
Loading…
Reference in New Issue
Block a user