#include "assetmeta.h" #include "processing.h" #include "processing_flags.h" #include "utils.h" #include "runtime/buffer_manager.h" #include #include static shaderc_include_result *ResolveInclude(void *user_data, const char *requested_source, int type, const char *requesting_source, size_t include_depth) { shaderc_include_result *result = NULL; return result; } static void ReleaseIncludeResult(void *user_data, shaderc_include_result *result) { } rt_result rtProcessShaderFile(rt_file_id file, void *buffer, size_t size, uint32_t flags, rt_processor_output *output) { /* If we determine that shader compilation takes too long, we can instead * keep the compiler around */ shaderc_compiler_t compiler = shaderc_compiler_initialize(); if (!compiler) { rtLog("ASSETC", "Failed to initialize the shaderc compiler."); return RT_PROCESSING_FAILED; } const char *path = rtGetFilePath(file); shaderc_compile_options_t options = shaderc_compile_options_initialize(); if (!options) { rtLog("ASSETC", "Failed to initialize shader compile options."); shaderc_compiler_release(compiler); return RT_PROCESSING_FAILED; } shaderc_compile_options_set_include_callbacks(options, ResolveInclude, ReleaseIncludeResult, NULL); uint32_t optimize_from_flags = flags & RT_SHADER_FLAG_OPTIMIZE_MASK; if (optimize_from_flags == RT_SHADER_FLAG_OPTIMIZE_SPEED) shaderc_compile_options_set_optimization_level(options, shaderc_optimization_level_performance); else if (optimize_from_flags == RT_SHADER_FLAG_OPTIMIZE_SIZE) shaderc_compile_options_set_optimization_level(options, shaderc_optimization_level_size); else shaderc_compile_options_set_optimization_level(options, shaderc_optimization_level_zero); uint32_t type_from_flags = flags & RT_SHADER_FLAG_TYPE_MASK; shaderc_shader_kind shaderc_kind; switch (type_from_flags) { case RT_SHADER_FLAG_VERTEX: shaderc_kind = shaderc_glsl_vertex_shader; break; case RT_SHADER_FLAG_FRAGMENT: shaderc_kind = shaderc_glsl_fragment_shader; break; case RT_SHADER_FLAG_COMPUTE: shaderc_kind = shaderc_glsl_compute_shader; break; default: rtLog("ASSETC", "Invalid shader stage flag %u", type_from_flags); shaderc_compile_options_release(options); shaderc_compiler_release(compiler); return RT_PROCESSING_FAILED; } shaderc_compilation_result_t result = shaderc_compile_into_spv(compiler, (const char *)buffer, size, shaderc_kind, path, "main", options); shaderc_compilation_status status = shaderc_result_get_compilation_status(result); if (status != shaderc_compilation_status_success || shaderc_result_get_num_errors(result) > 0) { rtLog("ASSETC", "Compilation of %s failed: %s", path, shaderc_result_get_error_message(result)); shaderc_result_release(result); shaderc_compile_options_release(options); shaderc_compiler_release(compiler); return RT_PROCESSING_FAILED; } size_t output_size = shaderc_result_get_length(result); output->data = rtAllocBuffer(output_size); if (!output->data) { shaderc_result_release(result); shaderc_compile_options_release(options); shaderc_compiler_release(compiler); rtLog("ASSETC", "Failed to allocate %zu bytes for shader compilation output.", output_size); return RT_PROCESSING_FAILED; } const uint32_t *spv_bytes = (uint32_t *)shaderc_result_get_bytes(result); memcpy(output->data, spv_bytes, output_size); output->size = output_size; shaderc_result_release(result); shaderc_compile_options_release(options); shaderc_compiler_release(compiler); output->asset_uid = rtCalculateUID(path); return RT_SUCCESS; }