664 lines
31 KiB
C
664 lines
31 KiB
C
|
|
|
|
#include "description_parser.h"
|
|
#include "processor.h"
|
|
|
|
#if 0
|
|
#include "gfx/gfx.h"
|
|
#include "runtime/buffer_manager.h"
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
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;
|
|
|
|
/* ~~~~ 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);
|
|
framegraph->names_size += 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;
|
|
}
|
|
|
|
/* ~~~~ 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;
|
|
}
|
|
|
|
framegraph->names_size += pass_stmt->attribute.length + 1;
|
|
|
|
passes[i].id =
|
|
rtCalculateRenderPassID(pass_stmt->attribute.start, pass_stmt->attribute.length);
|
|
passes[i].type = RT_RENDER_PASS_TYPE_GRAPHICS;
|
|
const rt_parsed_stmt *type_stmt = rtFindStatement(&state, pass_stmt->list_index, "type");
|
|
if (type_stmt) {
|
|
if (type_stmt->form != RT_STMT_FORM_VALUE) {
|
|
rtLog("AC",
|
|
"Expected GRAPHICS or COMPUTE as the value of \"passes.%.*s.type\" in %s",
|
|
pass_stmt->attribute.length,
|
|
pass_stmt->attribute.start,
|
|
file_path);
|
|
return RT_INVALID_VALUE;
|
|
}
|
|
if (rtCompareSpanToString(type_stmt->value, "GRAPHICS") == 0) {
|
|
passes[i].type = RT_RENDER_PASS_TYPE_GRAPHICS;
|
|
} else if (rtCompareSpanToString(type_stmt->value, "COMPUTE") == 0) {
|
|
passes[i].type = RT_RENDER_PASS_TYPE_COMPUTE;
|
|
} else {
|
|
rtLog("AC",
|
|
"Expected GRAPHICS or COMPUTE as the value of \"passes.%.*s.type\" in %s",
|
|
pass_stmt->attribute.length,
|
|
pass_stmt->attribute.start,
|
|
file_path);
|
|
return RT_INVALID_VALUE;
|
|
}
|
|
}
|
|
|
|
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, "DIRECT") == 0) {
|
|
read->mode = RT_RENDER_TARGET_READ_DIRECT;
|
|
} else {
|
|
rtLog("AC",
|
|
"Expected SAMPLED or DIRECT 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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* ~~~~ Names ~~~~ */
|
|
char *names = rtArenaPush(arena, framegraph->names_size);
|
|
rtSetRelptr(&framegraph->names, names);
|
|
char *names_at = names;
|
|
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 (names) {
|
|
memcpy(names_at, pass_stmt->attribute.start, pass_stmt->attribute.length);
|
|
names_at[pass_stmt->attribute.length] = '\0';
|
|
rtSetRelptr(&passes[i].name, names_at);
|
|
passes[i].name_len = pass_stmt->attribute.length + 1;
|
|
names_at += pass_stmt->attribute.length + 1;
|
|
} else {
|
|
rtSetRelptr(&passes[i].name, NULL);
|
|
passes[i].name_len = 0;
|
|
}
|
|
}
|
|
|
|
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 (names) {
|
|
memcpy(names_at,
|
|
rendertarget_stmt->attribute.start,
|
|
rendertarget_stmt->attribute.length);
|
|
names_at[rendertarget_stmt->attribute.length] = '\0';
|
|
rtSetRelptr(&render_targets[i].name, names_at);
|
|
render_targets[i].name_len = rendertarget_stmt->attribute.length + 1;
|
|
names_at += rendertarget_stmt->attribute.length + 1;
|
|
} else {
|
|
rtSetRelptr(&render_targets[i].name, NULL);
|
|
render_targets[i].name_len = 0;
|
|
}
|
|
}
|
|
|
|
*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;
|
|
}
|
|
#endif
|