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