Start work on effect files
Extends pipeline files
This commit is contained in:
		
							parent
							
								
									36e2314f35
								
							
						
					
					
						commit
						41fe5426b8
					
				@ -1,7 +1,9 @@
 | 
				
			|||||||
optimization speed;
 | 
					optimization speed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
vertex {
 | 
					passes {
 | 
				
			||||||
	vk BEGIN
 | 
					    pass0 {
 | 
				
			||||||
 | 
					        vertex {
 | 
				
			||||||
 | 
					            vk BEGIN
 | 
				
			||||||
#include "common.hlsl"
 | 
					#include "common.hlsl"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct VSInput
 | 
					struct VSInput
 | 
				
			||||||
@ -10,29 +12,31 @@ struct VSInput
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
struct VSOutput
 | 
					struct VSOutput
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	float4 Pos : SV_POSITION;
 | 
					    float4 Pos : SV_POSITION;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
VSOutput VsMain(VSInput input, uint vertexIndex : SV_VertexID) {
 | 
					VSOutput VsMain(VSInput input, uint vertexIndex : SV_VertexID) {
 | 
				
			||||||
	VSOutput output = (VSOutput)0;
 | 
					    VSOutput output = (VSOutput)0;
 | 
				
			||||||
	return output;
 | 
					    return output;
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
	END
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					            END
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fragment {
 | 
					        fragment {
 | 
				
			||||||
	vk BEGIN
 | 
					            vk BEGIN
 | 
				
			||||||
struct PSOutput {
 | 
					struct PSOutput {
 | 
				
			||||||
	float4 Color : SV_TARGET0;
 | 
					float4 Color : SV_TARGET0;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PSOutput PsMain(void) {
 | 
					PSOutput PsMain(void) {
 | 
				
			||||||
	PSOutput output = (PSOutput)0;
 | 
					    PSOutput output = (PSOutput)0;
 | 
				
			||||||
	output.Color[0] = 0;
 | 
					    output.Color[0] = 0;
 | 
				
			||||||
	output.Color[1] = 0;
 | 
					    output.Color[1] = 0;
 | 
				
			||||||
	output.Color[2] = 0;
 | 
					    output.Color[2] = 0;
 | 
				
			||||||
	output.Color[3] = 0;
 | 
					    output.Color[3] = 0;
 | 
				
			||||||
	return output;
 | 
					    return output;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
	END
 | 
					            END
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										5
									
								
								assets/test.effect
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								assets/test.effect
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					passes {
 | 
				
			||||||
 | 
					    pass0 {
 | 
				
			||||||
 | 
					        pipeline test/shader/static_object.pipeline;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -15,10 +15,6 @@
 | 
				
			|||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
    rt_attribute_binding *uniform_bindings;
 | 
					 | 
				
			||||||
    rt_attribute_binding *storage_bindings;
 | 
					 | 
				
			||||||
    rt_attribute_binding *texture_bindings;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    rt_resource shaders[3];
 | 
					    rt_resource shaders[3];
 | 
				
			||||||
    char *shader_names[3];
 | 
					    char *shader_names[3];
 | 
				
			||||||
    unsigned int shader_count;
 | 
					    unsigned int shader_count;
 | 
				
			||||||
@ -36,96 +32,17 @@ typedef struct {
 | 
				
			|||||||
    uint16_t texture_binding_count;
 | 
					    uint16_t texture_binding_count;
 | 
				
			||||||
} rt_parsed_pipeline_data;
 | 
					} rt_parsed_pipeline_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct {
 | 
				
			||||||
 | 
					    unsigned int pass_count;
 | 
				
			||||||
 | 
					    rt_parsed_pipeline_data pipelines[RT_MAX_SUBRESOURCES];
 | 
				
			||||||
 | 
					} rt_parsed_effect_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum {
 | 
					enum {
 | 
				
			||||||
    RT_SHADER_NOT_PRESENT = RT_ASSET_PROCESSING_FAILED + 1
 | 
					    RT_SHADER_NOT_PRESENT = RT_ASSET_PROCESSING_FAILED + 1
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern RT_DLLIMPORT rt_cvar rt_Renderer;
 | 
					extern RT_DLLIMPORT rt_cvar rt_Renderer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool ParseBindingIndex(rt_text_span span, unsigned int *index) {
 | 
					 | 
				
			||||||
    if (span.length == 0)
 | 
					 | 
				
			||||||
        return false;
 | 
					 | 
				
			||||||
    int at           = (int)span.length - 1;
 | 
					 | 
				
			||||||
    unsigned int exp = 1;
 | 
					 | 
				
			||||||
    unsigned int n   = 0;
 | 
					 | 
				
			||||||
    while (at >= 0) {
 | 
					 | 
				
			||||||
        if (span.start[at] >= '0' && span.start[at] <= '9') {
 | 
					 | 
				
			||||||
            unsigned int digit = (unsigned int)(span.start[at] - '0');
 | 
					 | 
				
			||||||
            n += digit * exp;
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            rtReportError("GFX", "Unexpected non-digit character in binding index");
 | 
					 | 
				
			||||||
            return false;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        --at;
 | 
					 | 
				
			||||||
        exp *= 10;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    *index = n;
 | 
					 | 
				
			||||||
    return true;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static rt_attribute_value ParseBindingValue(rt_text_span span) {
 | 
					 | 
				
			||||||
    if (rtCompareSpanToString(span, "MATERIAL_ALBEDO") == 0) {
 | 
					 | 
				
			||||||
        return RT_ATTRIBUTE_VALUE_MATERIAL_ALBEDO;
 | 
					 | 
				
			||||||
    } else if (rtCompareSpanToString(span, "MATERIAL_NORMAL") == 0) {
 | 
					 | 
				
			||||||
        return RT_ATTRIBUTE_VALUE_MATERIAL_NORMAL;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    rtReportError("GFX", "Unsupported binding value %*.s", span.length, span.start);
 | 
					 | 
				
			||||||
    return RT_ATTRIBUTE_VALUE_UNDEFINED;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static bool ParseBindings(rt_parse_state *state,
 | 
					 | 
				
			||||||
                          unsigned int root_list,
 | 
					 | 
				
			||||||
                          const char *name,
 | 
					 | 
				
			||||||
                          const char *file_path,
 | 
					 | 
				
			||||||
                          rt_attribute_binding **p_bindings,
 | 
					 | 
				
			||||||
                          uint16_t *p_binding_count) {
 | 
					 | 
				
			||||||
    const rt_parsed_stmt *bindings = rtFindStatement(state, root_list, name);
 | 
					 | 
				
			||||||
    if (bindings) {
 | 
					 | 
				
			||||||
        if (bindings->form != RT_STMT_FORM_LIST) {
 | 
					 | 
				
			||||||
            rtReportError("GFX",
 | 
					 | 
				
			||||||
                          "Expected list of bindings as the value of "
 | 
					 | 
				
			||||||
                          "\"%s\" in %s",
 | 
					 | 
				
			||||||
                          name,
 | 
					 | 
				
			||||||
                          file_path);
 | 
					 | 
				
			||||||
            return false;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        const rt_parsed_stmt_list *binding_list = &state->statement_lists[bindings->list_index];
 | 
					 | 
				
			||||||
        rt_attribute_binding *shader_bindings =
 | 
					 | 
				
			||||||
            rtAllocBuffer(sizeof(rt_attribute_binding) * binding_list->count);
 | 
					 | 
				
			||||||
        if (!bindings) {
 | 
					 | 
				
			||||||
            rtReportError("GFX", "Out of memory");
 | 
					 | 
				
			||||||
            return false;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        unsigned int binding_count = binding_list->count;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        unsigned int stmt_index = binding_list->first;
 | 
					 | 
				
			||||||
        for (unsigned int i = 0; i < binding_list->count; ++i) {
 | 
					 | 
				
			||||||
            const rt_parsed_stmt *stmt = &state->statements[stmt_index];
 | 
					 | 
				
			||||||
            if (!ParseBindingIndex(stmt->attribute, &shader_bindings[i].index)) {
 | 
					 | 
				
			||||||
                rtReleaseBuffer(shader_bindings,
 | 
					 | 
				
			||||||
                                sizeof(rt_attribute_binding) * binding_list->count);
 | 
					 | 
				
			||||||
                return false;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            shader_bindings[i].value = ParseBindingValue(stmt->value);
 | 
					 | 
				
			||||||
            if (shader_bindings[i].value == RT_ATTRIBUTE_VALUE_UNDEFINED) {
 | 
					 | 
				
			||||||
                rtReleaseBuffer(shader_bindings,
 | 
					 | 
				
			||||||
                                sizeof(rt_attribute_binding) * binding_list->count);
 | 
					 | 
				
			||||||
                return false;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            stmt_index = stmt->next;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        *p_bindings      = shader_bindings;
 | 
					 | 
				
			||||||
        *p_binding_count = (uint16_t)binding_count;
 | 
					 | 
				
			||||||
        return true;
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
        *p_bindings      = NULL;
 | 
					 | 
				
			||||||
        *p_binding_count = 0;
 | 
					 | 
				
			||||||
        return true;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static char *GenerateShaderName(rt_shader_type type,
 | 
					static char *GenerateShaderName(rt_shader_type type,
 | 
				
			||||||
                                rt_shader_stage stage,
 | 
					                                rt_shader_stage stage,
 | 
				
			||||||
                                rt_shader_optimization_level optimization,
 | 
					                                rt_shader_optimization_level optimization,
 | 
				
			||||||
@ -300,27 +217,13 @@ ParseOptimizationLevel(rt_parse_state *state, unsigned int root_list, const char
 | 
				
			|||||||
    return optimization_level;
 | 
					    return optimization_level;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static rt_result ParsePipelineFile(rt_file_id fid,
 | 
					static rt_result ParsePipeline(rt_parse_state *state,
 | 
				
			||||||
                                   const char *text,
 | 
					                               unsigned int root_list,
 | 
				
			||||||
                                   size_t length,
 | 
					                               const char *file_path,
 | 
				
			||||||
                                   rt_parsed_pipeline_data *pipeline,
 | 
					                               rt_shader_optimization_level optimization,
 | 
				
			||||||
                                   rt_arena *arena) {
 | 
					                               rt_parsed_pipeline_data *pipeline,
 | 
				
			||||||
    /* This is the grammar for pipeline files:
 | 
					                               rt_arena *arena) {
 | 
				
			||||||
     * <stmt-list> ::= <stmt>*
 | 
					    rt_result result = RT_SUCCESS;
 | 
				
			||||||
     * <stmt> ::= <attribute> ( ( <value> ';' ) | ( '{' <stmt-list> '}' ) )
 | 
					 | 
				
			||||||
     * <attribute> ::= [:alnum:]*
 | 
					 | 
				
			||||||
     * <value>:: = [:alnum:]* */
 | 
					 | 
				
			||||||
    const char *file_path = rtGetFilePath(fid);
 | 
					 | 
				
			||||||
    rt_parse_state state;
 | 
					 | 
				
			||||||
    unsigned int root_list;
 | 
					 | 
				
			||||||
    rt_result result = rtParseDescription(text, length, file_path, &root_list, &state, arena);
 | 
					 | 
				
			||||||
    if (result != RT_SUCCESS) {
 | 
					 | 
				
			||||||
        goto out;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /* We allow the pipeline file to overwrite the optimization level */
 | 
					 | 
				
			||||||
    rt_shader_optimization_level optimization =
 | 
					 | 
				
			||||||
        ParseOptimizationLevel(&state, root_list, file_path);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    rt_shader_type type = RT_SHADER_TYPE_INVALID;
 | 
					    rt_shader_type type = RT_SHADER_TYPE_INVALID;
 | 
				
			||||||
    if (strcmp(rt_Renderer.s, "vk") == 0)
 | 
					    if (strcmp(rt_Renderer.s, "vk") == 0)
 | 
				
			||||||
@ -333,7 +236,7 @@ static rt_result ParsePipelineFile(rt_file_id fid,
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Process shader stages */
 | 
					    /* Process shader stages */
 | 
				
			||||||
    result = ParseShader(&state,
 | 
					    result = ParseShader(state,
 | 
				
			||||||
                         root_list,
 | 
					                         root_list,
 | 
				
			||||||
                         "vertex",
 | 
					                         "vertex",
 | 
				
			||||||
                         file_path,
 | 
					                         file_path,
 | 
				
			||||||
@ -353,7 +256,7 @@ static rt_result ParsePipelineFile(rt_file_id fid,
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    result = RT_SUCCESS;
 | 
					    result = RT_SUCCESS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    result = ParseShader(&state,
 | 
					    result = ParseShader(state,
 | 
				
			||||||
                         root_list,
 | 
					                         root_list,
 | 
				
			||||||
                         "fragment",
 | 
					                         "fragment",
 | 
				
			||||||
                         file_path,
 | 
					                         file_path,
 | 
				
			||||||
@ -373,7 +276,7 @@ static rt_result ParsePipelineFile(rt_file_id fid,
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    result = RT_SUCCESS;
 | 
					    result = RT_SUCCESS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    result = ParseShader(&state,
 | 
					    result = ParseShader(state,
 | 
				
			||||||
                         root_list,
 | 
					                         root_list,
 | 
				
			||||||
                         "compute",
 | 
					                         "compute",
 | 
				
			||||||
                         file_path,
 | 
					                         file_path,
 | 
				
			||||||
@ -393,115 +296,123 @@ static rt_result ParsePipelineFile(rt_file_id fid,
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    result = RT_SUCCESS;
 | 
					    result = RT_SUCCESS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Process bindings */
 | 
					 | 
				
			||||||
    pipeline->texture_bindings      = NULL;
 | 
					 | 
				
			||||||
    pipeline->texture_binding_count = 0;
 | 
					 | 
				
			||||||
    pipeline->uniform_bindings      = NULL;
 | 
					 | 
				
			||||||
    pipeline->uniform_binding_count = 0;
 | 
					 | 
				
			||||||
    pipeline->storage_bindings      = NULL;
 | 
					 | 
				
			||||||
    pipeline->storage_binding_count = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (!ParseBindings(&state,
 | 
					 | 
				
			||||||
                       root_list,
 | 
					 | 
				
			||||||
                       "texture_bindings",
 | 
					 | 
				
			||||||
                       file_path,
 | 
					 | 
				
			||||||
                       &pipeline->texture_bindings,
 | 
					 | 
				
			||||||
                       &pipeline->texture_binding_count)) {
 | 
					 | 
				
			||||||
        result = RT_ASSET_PROCESSING_FAILED;
 | 
					 | 
				
			||||||
        goto out;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (!ParseBindings(&state,
 | 
					 | 
				
			||||||
                       root_list,
 | 
					 | 
				
			||||||
                       "uniform_bindings",
 | 
					 | 
				
			||||||
                       file_path,
 | 
					 | 
				
			||||||
                       &pipeline->uniform_bindings,
 | 
					 | 
				
			||||||
                       &pipeline->uniform_binding_count)) {
 | 
					 | 
				
			||||||
        result = RT_ASSET_PROCESSING_FAILED;
 | 
					 | 
				
			||||||
        goto out;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (!ParseBindings(&state,
 | 
					 | 
				
			||||||
                       root_list,
 | 
					 | 
				
			||||||
                       "storage_bindings",
 | 
					 | 
				
			||||||
                       file_path,
 | 
					 | 
				
			||||||
                       &pipeline->storage_bindings,
 | 
					 | 
				
			||||||
                       &pipeline->storage_binding_count)) {
 | 
					 | 
				
			||||||
        result = RT_ASSET_PROCESSING_FAILED;
 | 
					 | 
				
			||||||
        goto out;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
    return result;
 | 
					    return result;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static rt_result ParseEffect(rt_file_id fid,
 | 
				
			||||||
 | 
					                             const char *text,
 | 
				
			||||||
 | 
					                             size_t length,
 | 
				
			||||||
 | 
					                             rt_parsed_effect_data *effect,
 | 
				
			||||||
 | 
					                             rt_arena *arena) {
 | 
				
			||||||
 | 
					    /* This is the grammar for pipeline files:
 | 
				
			||||||
 | 
					     * <stmt-list> ::= <stmt>*
 | 
				
			||||||
 | 
					     * <stmt> ::= <attribute> ( ( <value> ';' ) | ( '{' <stmt-list> '}' ) )
 | 
				
			||||||
 | 
					     * <attribute> ::= [:alnum:]*
 | 
				
			||||||
 | 
					     * <value>:: = [:alnum:]* */
 | 
				
			||||||
 | 
					    const char *file_path = rtGetFilePath(fid);
 | 
				
			||||||
 | 
					    rt_parse_state state;
 | 
				
			||||||
 | 
					    unsigned int root_list;
 | 
				
			||||||
 | 
					    rt_result result = rtParseDescription(text, length, file_path, &root_list, &state, arena);
 | 
				
			||||||
 | 
					    if (result != RT_SUCCESS) {
 | 
				
			||||||
 | 
					        return result;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    memset(effect, 0, sizeof(*effect));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    rt_shader_optimization_level optimization =
 | 
				
			||||||
 | 
					        ParseOptimizationLevel(&state, root_list, file_path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const rt_parsed_stmt *passes_stmt = rtFindStatement(&state, root_list, "passes");
 | 
				
			||||||
 | 
					    if (!passes_stmt) {
 | 
				
			||||||
 | 
					        rtLog("AC", "Did not find passes list in %s.", file_path);
 | 
				
			||||||
 | 
					        return RT_INVALID_VALUE;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    const rt_parsed_stmt_list *passes_list = &state.statement_lists[passes_stmt->list_index];
 | 
				
			||||||
 | 
					    if (passes_list->count > RT_MAX_SUBRESOURCES) {
 | 
				
			||||||
 | 
					        rtLog("AC",
 | 
				
			||||||
 | 
					              "Too many passes in 'passes'. Maximum supported number is %u. In %s.",
 | 
				
			||||||
 | 
					              RT_MAX_SUBRESOURCES,
 | 
				
			||||||
 | 
					              file_path);
 | 
				
			||||||
 | 
					        return RT_INVALID_VALUE;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    const rt_parsed_stmt *pass_stmt = &state.statements[passes_list->first];
 | 
				
			||||||
 | 
					    for (unsigned int i = 0; i < passes_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;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        result = ParsePipeline(&state,
 | 
				
			||||||
 | 
					                               pass_stmt->list_index,
 | 
				
			||||||
 | 
					                               file_path,
 | 
				
			||||||
 | 
					                               optimization,
 | 
				
			||||||
 | 
					                               &effect->pipelines[i],
 | 
				
			||||||
 | 
					                               arena);
 | 
				
			||||||
 | 
					        if (result != RT_SUCCESS)
 | 
				
			||||||
 | 
					            return result;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
RT_ASSET_PROCESSOR_FN(PipelineProcessor) {
 | 
					RT_ASSET_PROCESSOR_FN(PipelineProcessor) {
 | 
				
			||||||
    rt_loaded_asset asset = LoadAsset(file);
 | 
					    rt_loaded_asset asset = LoadAsset(file);
 | 
				
			||||||
    if (!asset.buffer)
 | 
					    if (!asset.buffer)
 | 
				
			||||||
        return RT_UNKNOWN_ERROR;
 | 
					        return RT_UNKNOWN_ERROR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    rt_parsed_pipeline_data pipeline;
 | 
					    rt_parsed_effect_data effect;
 | 
				
			||||||
    memset(&pipeline, 0, sizeof(pipeline));
 | 
					    memset(&effect, 0, sizeof(effect));
 | 
				
			||||||
    rt_result result = ParsePipelineFile(file, asset.buffer, asset.size, &pipeline, arena);
 | 
					    rt_result result = ParseEffect(file, asset.buffer, asset.size, &effect, arena);
 | 
				
			||||||
    if (result != RT_SUCCESS)
 | 
					    if (result != RT_SUCCESS)
 | 
				
			||||||
        goto out;
 | 
					        goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    rt_resource_id shader_resources[3] = {0};
 | 
					    for (unsigned int i = 0; i < effect.pass_count; ++i) {
 | 
				
			||||||
    result                             = rtCreateResources(pipeline.shader_count,
 | 
					        rt_parsed_pipeline_data pipeline;
 | 
				
			||||||
                               pipeline.shader_names,
 | 
					        memcpy(&pipeline, &effect.pipelines[i], sizeof(pipeline));
 | 
				
			||||||
                               pipeline.shaders,
 | 
					        rt_resource_id shader_resources[3] = {0};
 | 
				
			||||||
                               shader_resources);
 | 
					        result                             = rtCreateResources(pipeline.shader_count,
 | 
				
			||||||
    if (result != RT_SUCCESS)
 | 
					                                   pipeline.shader_names,
 | 
				
			||||||
        goto out;
 | 
					                                   pipeline.shaders,
 | 
				
			||||||
 | 
					                                   shader_resources);
 | 
				
			||||||
 | 
					        if (result != RT_SUCCESS)
 | 
				
			||||||
 | 
					            goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    rt_resource pipeline_resource      = {0};
 | 
					        rt_resource pipeline_resource      = {0};
 | 
				
			||||||
    pipeline_resource.type             = RT_RESOURCE_PIPELINE;
 | 
					        pipeline_resource.type             = RT_RESOURCE_PIPELINE;
 | 
				
			||||||
    pipeline_resource.dependency_count = pipeline.shader_count;
 | 
					        pipeline_resource.dependency_count = pipeline.shader_count;
 | 
				
			||||||
    memcpy(pipeline_resource.dependencies, shader_resources, sizeof(shader_resources));
 | 
					        memcpy(pipeline_resource.dependencies, shader_resources, sizeof(shader_resources));
 | 
				
			||||||
    pipeline_resource.subresource_count = 0;
 | 
					        pipeline_resource.subresource_count = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    size_t data_size =
 | 
					        size_t data_size       = sizeof(rt_pipeline_info);
 | 
				
			||||||
        sizeof(rt_pipeline_info) + sizeof(rt_attribute_binding) * (pipeline.texture_binding_count +
 | 
					        pipeline_resource.data = rtArenaPush(arena, data_size);
 | 
				
			||||||
                                                                   pipeline.uniform_binding_count +
 | 
					        if (!pipeline_resource.data) {
 | 
				
			||||||
                                                                   pipeline.storage_binding_count);
 | 
					            result = RT_OUT_OF_MEMORY;
 | 
				
			||||||
    pipeline_resource.data = rtArenaPush(arena, data_size);
 | 
					            goto out;
 | 
				
			||||||
    if (!pipeline_resource.data) {
 | 
					        }
 | 
				
			||||||
        result = RT_OUT_OF_MEMORY;
 | 
					        rt_pipeline_info *info = pipeline_resource.data;
 | 
				
			||||||
        goto out;
 | 
					        memset(info, 0, sizeof(*info));
 | 
				
			||||||
    }
 | 
					        info->vertex_shader   = (pipeline.vertex_shader != UINT_MAX)
 | 
				
			||||||
    rt_pipeline_info *info = pipeline_resource.data;
 | 
					                                    ? shader_resources[pipeline.vertex_shader]
 | 
				
			||||||
    memset(info, 0, sizeof(*info));
 | 
					                                    : RT_INVALID_RESOURCE_ID;
 | 
				
			||||||
    info->vertex_shader                    = (pipeline.vertex_shader != UINT_MAX)
 | 
					        info->fragment_shader = (pipeline.fragment_shader != UINT_MAX)
 | 
				
			||||||
                                                 ? shader_resources[pipeline.vertex_shader]
 | 
					                                    ? shader_resources[pipeline.fragment_shader]
 | 
				
			||||||
                                                 : RT_INVALID_RESOURCE_ID;
 | 
					                                    : RT_INVALID_RESOURCE_ID;
 | 
				
			||||||
    info->fragment_shader                  = (pipeline.fragment_shader != UINT_MAX)
 | 
					        info->compute_shader  = (pipeline.compute_shader != UINT_MAX)
 | 
				
			||||||
                                                 ? shader_resources[pipeline.fragment_shader]
 | 
					                                    ? shader_resources[pipeline.compute_shader]
 | 
				
			||||||
                                                 : RT_INVALID_RESOURCE_ID;
 | 
					                                    : RT_INVALID_RESOURCE_ID;
 | 
				
			||||||
    info->compute_shader                   = (pipeline.compute_shader != UINT_MAX)
 | 
					        rt_resource_id pipeline_id;
 | 
				
			||||||
                                                 ? shader_resources[pipeline.compute_shader]
 | 
					        const char *name = rtGetFilePath(file);
 | 
				
			||||||
                                                 : RT_INVALID_RESOURCE_ID;
 | 
					        result           = rtCreateResources(1, &name, &pipeline_resource, &pipeline_id);
 | 
				
			||||||
    rt_attribute_binding *uniform_bindings = (rt_attribute_binding *)(info + 1);
 | 
					        if (result == RT_SUCCESS) {
 | 
				
			||||||
    if (pipeline.uniform_binding_count > 0) {
 | 
					            new_resources[0] = pipeline_id;
 | 
				
			||||||
        memcpy(uniform_bindings, pipeline.uniform_bindings, pipeline.uniform_binding_count);
 | 
					            memcpy(&new_resources[1], shader_resources, sizeof(shader_resources));
 | 
				
			||||||
        rtSetRelptr(&info->uniform_bindings, uniform_bindings);
 | 
					            *new_resource_count = 1 + pipeline.shader_count;
 | 
				
			||||||
    }
 | 
					        }
 | 
				
			||||||
    rt_attribute_binding *texture_bindings = (uniform_bindings + pipeline.uniform_binding_count);
 | 
					 | 
				
			||||||
    if (pipeline.texture_binding_count > 0) {
 | 
					 | 
				
			||||||
        memcpy(texture_bindings, pipeline.texture_bindings, pipeline.texture_binding_count);
 | 
					 | 
				
			||||||
        rtSetRelptr(&info->texture_bindings, texture_bindings);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    rt_attribute_binding *storage_bindings = (texture_bindings + pipeline.texture_binding_count);
 | 
					 | 
				
			||||||
    if (pipeline.texture_binding_count > 0) {
 | 
					 | 
				
			||||||
        memcpy(storage_bindings, pipeline.storage_bindings, pipeline.storage_binding_count);
 | 
					 | 
				
			||||||
        rtSetRelptr(&info->storage_bindings, storage_bindings);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    rt_resource_id pipeline_id;
 | 
					 | 
				
			||||||
    const char *name = rtGetFilePath(file);
 | 
					 | 
				
			||||||
    result           = rtCreateResources(1, &name, &pipeline_resource, &pipeline_id);
 | 
					 | 
				
			||||||
    if (result == RT_SUCCESS) {
 | 
					 | 
				
			||||||
        new_resources[0] = pipeline_id;
 | 
					 | 
				
			||||||
        memcpy(&new_resources[1], shader_resources, sizeof(shader_resources));
 | 
					 | 
				
			||||||
        *new_resource_count = 1 + pipeline.shader_count;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
    rtLog("AC", "Released %p", asset.buffer);
 | 
					    rtLog("AC", "Released %p", asset.buffer);
 | 
				
			||||||
@ -33,8 +33,8 @@ asset_compiler = static_library('asset_compiler',
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  'asset_compiler.c',
 | 
					  'asset_compiler.c',
 | 
				
			||||||
  'description_parser.c',
 | 
					  'description_parser.c',
 | 
				
			||||||
 | 
					  'effect_processor.c',
 | 
				
			||||||
  'framegraph_processor.c',
 | 
					  'framegraph_processor.c',
 | 
				
			||||||
  'pipeline_processor.c',
 | 
					 | 
				
			||||||
  'shader_compiler.c',
 | 
					  'shader_compiler.c',
 | 
				
			||||||
  sources : ac_sources,
 | 
					  sources : ac_sources,
 | 
				
			||||||
  include_directories : engine_incdir,
 | 
					  include_directories : engine_incdir,
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										25
									
								
								src/gfx/effect.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/gfx/effect.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					#ifndef RT_GFX_EFFECT_H
 | 
				
			||||||
 | 
					#define RT_GFX_EFFECT_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* A effect lists the passes during which an object needs to be rendered
 | 
				
			||||||
 | 
					 * and a pipeline for each pass.
 | 
				
			||||||
 | 
					 * The effect also defines the required vertex layout per pass.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "gfx.h"
 | 
				
			||||||
 | 
					#include "runtime/resources.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct {
 | 
				
			||||||
 | 
					    /* Id of the render pass during which this effect pass is run. */
 | 
				
			||||||
 | 
					    rt_render_pass_id pass_id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    rt_resource_id vertex_shader;
 | 
				
			||||||
 | 
					    rt_resource_id fragment_shader;
 | 
				
			||||||
 | 
					    rt_resource_id compute_shader;
 | 
				
			||||||
 | 
					} rt_effect_pass_info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct {
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					} rt_effect_info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
@ -1,6 +1,7 @@
 | 
				
			|||||||
gfx_deps = [thread_dep, m_dep]
 | 
					gfx_deps = [thread_dep, m_dep]
 | 
				
			||||||
gfx_lib = library('rtgfx',
 | 
					gfx_lib = library('rtgfx',
 | 
				
			||||||
  # Project Sources
 | 
					  # Project Sources
 | 
				
			||||||
 | 
					  'effect.h',
 | 
				
			||||||
  'gfx.h',
 | 
					  'gfx.h',
 | 
				
			||||||
  'renderer_api.h',
 | 
					  'renderer_api.h',
 | 
				
			||||||
  'render_list.h',
 | 
					  'render_list.h',
 | 
				
			||||||
 | 
				
			|||||||
@ -59,20 +59,14 @@ typedef enum {
 | 
				
			|||||||
    RT_TRANSFER_QUEUE,
 | 
					    RT_TRANSFER_QUEUE,
 | 
				
			||||||
} rt_gpu_queue;
 | 
					} rt_gpu_queue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
    rt_resource_id vertex_shader;
 | 
					    rt_resource_id vertex_shader;
 | 
				
			||||||
    rt_resource_id fragment_shader;
 | 
					    rt_resource_id fragment_shader;
 | 
				
			||||||
    rt_resource_id compute_shader;
 | 
					    rt_resource_id compute_shader;
 | 
				
			||||||
 | 
					 | 
				
			||||||
    rt_relptr texture_bindings;
 | 
					 | 
				
			||||||
    rt_relptr uniform_bindings;
 | 
					 | 
				
			||||||
    rt_relptr storage_bindings;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    uint16_t texture_binding_count;
 | 
					 | 
				
			||||||
    uint16_t uniform_binding_count;
 | 
					 | 
				
			||||||
    uint16_t storage_binding_count;
 | 
					 | 
				
			||||||
} rt_pipeline_info;
 | 
					} rt_pipeline_info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if 0
 | 
				
			||||||
/* Attributes are used to bind buffers (or textures) to symbolic values.
 | 
					/* Attributes are used to bind buffers (or textures) to symbolic values.
 | 
				
			||||||
 * For example, an attribute might be bound to "CELL_GRID", which would be
 | 
					 * For example, an attribute might be bound to "CELL_GRID", which would be
 | 
				
			||||||
 * replaced with the (at the time of the invoke) grid buffer of the current
 | 
					 * replaced with the (at the time of the invoke) grid buffer of the current
 | 
				
			||||||
@ -93,6 +87,8 @@ typedef struct {
 | 
				
			|||||||
    rt_attribute_value value;
 | 
					    rt_attribute_value value;
 | 
				
			||||||
} rt_attribute_binding;
 | 
					} rt_attribute_binding;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef enum {
 | 
					typedef enum {
 | 
				
			||||||
    RT_SHADER_TYPE_INVALID,
 | 
					    RT_SHADER_TYPE_INVALID,
 | 
				
			||||||
    RT_SHADER_TYPE_VULKAN,
 | 
					    RT_SHADER_TYPE_VULKAN,
 | 
				
			||||||
 | 
				
			|||||||
@ -957,47 +957,11 @@ RT_DLLEXPORT void rDebugLogResource(rt_resource_id id, const rt_resource *resour
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    switch (resource->type) {
 | 
					    switch (resource->type) {
 | 
				
			||||||
    case RT_RESOURCE_PIPELINE: {
 | 
					    case RT_RESOURCE_PIPELINE: {
 | 
				
			||||||
        static const char *binding_str[RT_ATTRIBUTE_VALUE_count] = {"<UNDEFINED>",
 | 
					 | 
				
			||||||
                                                                    "MaterialAlbedo",
 | 
					 | 
				
			||||||
                                                                    "MaterialNormal"};
 | 
					 | 
				
			||||||
        const rt_pipeline_info *pipeline                         = resource->data;
 | 
					        const rt_pipeline_info *pipeline                         = resource->data;
 | 
				
			||||||
        rtLog("RESMGR", "  pipeline data:");
 | 
					        rtLog("RESMGR", "  pipeline data:");
 | 
				
			||||||
        rtLog("RESMGR", "    vertex shader:   %llx", pipeline->vertex_shader);
 | 
					        rtLog("RESMGR", "    vertex shader:   %llx", pipeline->vertex_shader);
 | 
				
			||||||
        rtLog("RESMGR", "    fragment shader: %llx", pipeline->fragment_shader);
 | 
					        rtLog("RESMGR", "    fragment shader: %llx", pipeline->fragment_shader);
 | 
				
			||||||
        rtLog("RESMGR", "    compute shader:  %llx", pipeline->compute_shader);
 | 
					        rtLog("RESMGR", "    compute shader:  %llx", pipeline->compute_shader);
 | 
				
			||||||
        rtLog("RESMGR", "    uniform bindings:");
 | 
					 | 
				
			||||||
        const rt_attribute_binding *uniform_bindings =
 | 
					 | 
				
			||||||
            rtResolveConstRelptr(&pipeline->uniform_bindings);
 | 
					 | 
				
			||||||
        for (uint32_t i = 0; i < pipeline->uniform_binding_count; ++i) {
 | 
					 | 
				
			||||||
            rtLog("RESMGR",
 | 
					 | 
				
			||||||
                  "      - %u : %s",
 | 
					 | 
				
			||||||
                  uniform_bindings[i].index,
 | 
					 | 
				
			||||||
                  (uniform_bindings[i].value < RT_ATTRIBUTE_VALUE_count)
 | 
					 | 
				
			||||||
                      ? binding_str[uniform_bindings[i].value]
 | 
					 | 
				
			||||||
                      : "<INVALID>");
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        rtLog("RESMGR", "    texture bindings:");
 | 
					 | 
				
			||||||
        const rt_attribute_binding *texture_bindings =
 | 
					 | 
				
			||||||
            rtResolveConstRelptr(&pipeline->texture_bindings);
 | 
					 | 
				
			||||||
        for (uint32_t i = 0; i < pipeline->texture_binding_count; ++i) {
 | 
					 | 
				
			||||||
            rtLog("RESMGR",
 | 
					 | 
				
			||||||
                  "      - %u : %s",
 | 
					 | 
				
			||||||
                  texture_bindings[i].index,
 | 
					 | 
				
			||||||
                  (texture_bindings[i].value < RT_ATTRIBUTE_VALUE_count)
 | 
					 | 
				
			||||||
                      ? binding_str[texture_bindings[i].value]
 | 
					 | 
				
			||||||
                      : "<INVALID>");
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        rtLog("RESMGR", "    storage bindings:");
 | 
					 | 
				
			||||||
        const rt_attribute_binding *storage_bindings =
 | 
					 | 
				
			||||||
            rtResolveConstRelptr(&pipeline->storage_bindings);
 | 
					 | 
				
			||||||
        for (uint32_t i = 0; i < pipeline->storage_binding_count; ++i) {
 | 
					 | 
				
			||||||
            rtLog("RESMGR",
 | 
					 | 
				
			||||||
                  "      - %u : %s",
 | 
					 | 
				
			||||||
                  storage_bindings[i].index,
 | 
					 | 
				
			||||||
                  (storage_bindings[i].value < RT_ATTRIBUTE_VALUE_count)
 | 
					 | 
				
			||||||
                      ? binding_str[storage_bindings[i].value]
 | 
					 | 
				
			||||||
                      : "<INVALID>");
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    } break;
 | 
					    } break;
 | 
				
			||||||
    case RT_RESOURCE_SHADER: {
 | 
					    case RT_RESOURCE_SHADER: {
 | 
				
			||||||
        static const char *stype_str[RT_SHADER_TYPE_count]  = {"<INVALID>", "Vulkan"};
 | 
					        static const char *stype_str[RT_SHADER_TYPE_count]  = {"<INVALID>", "Vulkan"};
 | 
				
			||||||
 | 
				
			|||||||
@ -37,6 +37,8 @@ typedef enum {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    RT_RESOURCE_FRAMEGRAPH,
 | 
					    RT_RESOURCE_FRAMEGRAPH,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    RT_RESOURCE_EFFECT,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    RT_RESOURCE_TYPE_count,
 | 
					    RT_RESOURCE_TYPE_count,
 | 
				
			||||||
} rt_resource_type;
 | 
					} rt_resource_type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user