From fe03cb933fe5fa1838da08f74871592d98954a40 Mon Sep 17 00:00:00 2001 From: Robear Selwans Date: Tue, 8 Jun 2021 09:50:34 +0200 Subject: [PATCH] Added ShaderLoader using shaderc (GCC only) Signed-off-by: Robear Selwans --- meson.build | 8 +- meta/evmod.namespaces | 7 ++ meta/evmod.types | 23 ++++ src/loaders/ShaderLoader/ShaderLoader.c | 105 ++++++++++++++++++ src/loaders/ShaderLoader/ShaderLoader.h | 23 ++++ src/mod.c | 28 ++++- .../packagefiles/libshaderc/meson.build | 13 +++ subprojects/shaderc.wrap | 12 ++ 8 files changed, 214 insertions(+), 5 deletions(-) create mode 100644 src/loaders/ShaderLoader/ShaderLoader.c create mode 100644 src/loaders/ShaderLoader/ShaderLoader.h create mode 100644 subprojects/packagefiles/libshaderc/meson.build create mode 100644 subprojects/shaderc.wrap diff --git a/meson.build b/meson.build index 777649b..077b488 100644 --- a/meson.build +++ b/meson.build @@ -1,6 +1,6 @@ -project('evol-mod-assetmanager', 'c', +project('evol-mod-assetmanager', ['c', 'cpp'], version : '0.1', -default_options : ['warning_level=3', 'c_std=c11']) +default_options : ['warning_level=3', 'c_std=c11', 'default_library=shared']) src = subproject('evol').get_variable('evolmod_subdir') + '/meson.build' dst = meson.current_source_dir() + '/import/' @@ -15,6 +15,7 @@ mod_src = [ # Loaders 'src/loaders/TextLoader/TextLoader.c', 'src/loaders/JSONLoader/JSONLoader.c', + 'src/loaders/ShaderLoader/ShaderLoader.c', ] mod_incdir = [ @@ -24,6 +25,9 @@ mod_incdir = [ mod_deps = [ evmod_deps, + dependency('shaderc'), + dependency('threads'), + dependency('assetsys'), dependency('evmod_ecs'), ] diff --git a/meta/evmod.namespaces b/meta/evmod.namespaces index bd45c16..1345778 100644 --- a/meta/evmod.namespaces +++ b/meta/evmod.namespaces @@ -23,3 +23,10 @@ EV_NS_DEF_BEGIN(JSONLoader) EV_NS_DEF_FN(JSONAsset, loadAsset, (AssetHandle, handle)) EV_NS_DEF_END(JSONLoader) + + +EV_NS_DEF_BEGIN(ShaderLoader) + +EV_NS_DEF_FN(ShaderAsset, loadAsset, (AssetHandle, handle), (ShaderAssetStage, stage), (CONST_STR, shader_name), (CONST_STR, entrypoint), (CompiledShaderType, type)) + +EV_NS_DEF_END(ShaderLoader) diff --git a/meta/evmod.types b/meta/evmod.types index 0ac4ae3..80b40ac 100644 --- a/meta/evmod.types +++ b/meta/evmod.types @@ -9,3 +9,26 @@ TYPE(TextAsset, struct { TYPE(JSONAsset, struct { PTR json_data; }) + +TYPE(ShaderAssetStage, enum { + EV_SHADERASSETSTAGE_VERTEX, + EV_SHADERASSETSTAGE_FRAGMENT, + EV_SHADERASSETSTAGE_COMPUTE, + EV_SHADERASSETSTAGE_GEOMETRY, + + EV_SHADERASSETSTAGE_DETECT, + + EV_SHADERASSETSTAGE_COUNT +}) + +TYPE(CompiledShaderType, enum { + EV_SHADER_ASM, + EV_SHADER_BIN +}) + +TYPE(ShaderAsset, struct { + PTR binary; + U64 len; + GenericHandle internal_handle; + CompiledShaderType type; +}) diff --git a/src/loaders/ShaderLoader/ShaderLoader.c b/src/loaders/ShaderLoader/ShaderLoader.c new file mode 100644 index 0000000..cf8cbee --- /dev/null +++ b/src/loaders/ShaderLoader/ShaderLoader.c @@ -0,0 +1,105 @@ +#define TYPE_MODULE evmod_assets +#include +#include + +#include "../LoaderCommon.h" +#include "ShaderLoader.h" + +#include + +struct { + shaderc_compiler_t compiler; + shaderc_compile_options_t compile_options; +} ShaderLoaderData = {NULL,NULL}; + +void +ev_shaderloader_init() +{ + ShaderLoaderData.compiler = shaderc_compiler_initialize(); + ShaderLoaderData.compile_options = shaderc_compile_options_initialize(); +} + +void +ev_shaderloader_deinit() +{ + shaderc_compile_options_release(ShaderLoaderData.compile_options); + shaderc_compiler_release(ShaderLoaderData.compiler); +} + +shaderc_shader_kind +shader_kind_from_ShaderAssetStage( + ShaderAssetStage asset) +{ + switch(asset) { + case EV_SHADERASSETSTAGE_VERTEX: + return shaderc_glsl_vertex_shader; + case EV_SHADERASSETSTAGE_FRAGMENT: + return shaderc_glsl_fragment_shader; + case EV_SHADERASSETSTAGE_COMPUTE: + return shaderc_glsl_compute_shader; + case EV_SHADERASSETSTAGE_GEOMETRY: + return shaderc_glsl_geometry_shader; + case EV_SHADERASSETSTAGE_DETECT: + return shaderc_glsl_infer_from_source; + default: + ev_log_warn("Invalid ShaderAssetStage. Trying to infer stage from source."); + return shaderc_glsl_infer_from_source; + } +} +typedef shaderc_compilation_result_t (*ShaderCompilationFn)(); +ShaderAsset +ev_shaderloader_loadasset( + AssetHandle handle, + ShaderAssetStage stage, + CONST_STR shader_name, + CONST_STR entrypoint, + CompiledShaderType type) +{ + const Asset *asset = ev_asset_getfromhandle(handle); + ShaderCompilationFn compilation_fn = + (type == EV_SHADER_BIN) + ?(ShaderCompilationFn)shaderc_compile_into_spv: + (type == EV_SHADER_ASM) + ?(ShaderCompilationFn)shaderc_compile_into_spv_assembly + :NULL; + + shaderc_compilation_result_t result = compilation_fn( + ShaderLoaderData.compiler, + asset->data, asset->size, + shader_kind_from_ShaderAssetStage(stage), + shader_name, entrypoint?entrypoint:"main", + ShaderLoaderData.compile_options); + + if(shaderc_result_get_compilation_status(result) != shaderc_compilation_status_success) { + if(shaderc_result_get_num_errors(result) > 0) { + ev_log_error(shaderc_result_get_error_message(result)); + } + } + if(shaderc_result_get_num_warnings(result) > 0) { + ev_log_warn(shaderc_result_get_error_message(result)); + } + + ShaderAsset inter = (ShaderAsset) { + .binary = (PTR)shaderc_result_get_bytes(result), + .len = shaderc_result_get_length(result), + .internal_handle = (GenericHandle)result + }; + + ev_asset_markas(handle, LoaderData.assetType, &inter); + + return inter; +} + +void +ev_shaderloader_shaderasset_destr( + ShaderAsset shader) +{ + shaderc_result_release((shaderc_compilation_result_t)shader.internal_handle); +} + +void +ev_shaderloader_setassettype( + GenericHandle type) +{ + LoaderData.assetType = type; +} diff --git a/src/loaders/ShaderLoader/ShaderLoader.h b/src/loaders/ShaderLoader/ShaderLoader.h new file mode 100644 index 0000000..ca8eb90 --- /dev/null +++ b/src/loaders/ShaderLoader/ShaderLoader.h @@ -0,0 +1,23 @@ +#pragma once + +void +ev_shaderloader_init(); + +void +ev_shaderloader_deinit(); + +ShaderAsset +ev_shaderloader_loadasset( + AssetHandle handle, + ShaderAssetStage stage, + CONST_STR shader_name, + CONST_STR entrypoint, + CompiledShaderType type); + +void +ev_shaderloader_shaderasset_destr( + ShaderAsset shader); + +void +ev_shaderloader_setassettype( + GenericHandle type); diff --git a/src/mod.c b/src/mod.c index 2cac510..475fe4c 100644 --- a/src/mod.c +++ b/src/mod.c @@ -9,6 +9,7 @@ #include "loaders/LoaderCommon.h" #include "loaders/TextLoader/TextLoader.h" #include "loaders/JSONLoader/JSONLoader.h" +#include "loaders/ShaderLoader/ShaderLoader.h" #define AssetSysCheck(...) do { \ assetsys_error_t res = __VA_ARGS__; \ @@ -31,7 +32,7 @@ onRemoveAssetComponent( ECSQuery query) { Asset *assets = ECS->getQueryColumn(query, sizeof(Asset), 1); - for(int i = 0; i < ECS->getQueryMatchCount(query); i++) { + for(U32 i = 0; i < ECS->getQueryMatchCount(query); i++) { aligned_free(assets[i].data); } } @@ -41,7 +42,7 @@ onRemoveTextAsset( ECSQuery query) { TextAsset *assets = ECS->getQueryColumn(query, sizeof(TextAsset), 1); - for(int i = 0; i < ECS->getQueryMatchCount(query); i++) { + for(U32 i = 0; i < ECS->getQueryMatchCount(query); i++) { ev_textloader_textasset_destr(assets[i]); } } @@ -51,13 +52,24 @@ onRemoveJSONAsset( ECSQuery query) { JSONAsset *assets = ECS->getQueryColumn(query, sizeof(JSONAsset), 1); - for(int i = 0; i < ECS->getQueryMatchCount(query); i++) { + for(U32 i = 0; i < ECS->getQueryMatchCount(query); i++) { ev_jsonloader_jsonasset_destr(assets[i]); } } +void +onRemoveShaderAsset( + ECSQuery query) +{ + ShaderAsset *assets = ECS->getQueryColumn(query, sizeof(ShaderAsset), 1); + for(U32 i = 0; i < ECS->getQueryMatchCount(query); i++) { + ev_shaderloader_shaderasset_destr(assets[i]); + } +} + EV_CONSTRUCTOR { + ev_log_trace("evmod_asset constructor"); static_assert(sizeof(AssetEntityID) == sizeof(AssetHandle), "AssetEntityID not the same size of AssetHandle"); AssetManagerData.sys = assetsys_create( 0 ); @@ -76,9 +88,14 @@ EV_CONSTRUCTOR ev_jsonloader_setassettype(AssetECS->registerComponent("JSONAsset", sizeof(JSONAsset), EV_ALIGNOF(JSONAsset))); AssetECS->setOnRemoveTrigger("JSONAssetOnRemove", "JSONAsset", onRemoveJSONAsset); + + ev_shaderloader_setassettype(AssetECS->registerComponent("ShaderAsset", sizeof(ShaderAsset), EV_ALIGNOF(ShaderAsset))); + AssetECS->setOnRemoveTrigger("ShaderAssetOnRemove", "ShaderAsset", onRemoveShaderAsset); } } + ev_shaderloader_init(); + return AssetManagerData.sys == NULL; } @@ -92,6 +109,8 @@ EV_DESTRUCTOR if(AssetManagerData.ecs_mod) { evol_unloadmodule(AssetManagerData.ecs_mod); } + + ev_shaderloader_deinit(); return 0; } @@ -165,6 +184,7 @@ ev_asset_markas( EV_BINDINGS { + ev_log_debug("Binding functions in evmod_asset"); EV_NS_BIND_FN(AssetManager, mount, ev_assetmanager_mount); EV_NS_BIND_FN(Asset, load, ev_asset_load); @@ -175,5 +195,7 @@ EV_BINDINGS EV_NS_BIND_FN(JSONLoader, loadAsset, ev_jsonloader_loadasset); + EV_NS_BIND_FN(ShaderLoader, loadAsset, ev_shaderloader_loadasset); + return 0; } diff --git a/subprojects/packagefiles/libshaderc/meson.build b/subprojects/packagefiles/libshaderc/meson.build new file mode 100644 index 0000000..d158d5a --- /dev/null +++ b/subprojects/packagefiles/libshaderc/meson.build @@ -0,0 +1,13 @@ +project('libshaderc', 'cpp') + +fs = import('fs') +cxxc = meson.get_compiler('cpp') + +shaderc_inc = include_directories('install/include') + +shaderc_dep = declare_dependency( + dependencies: cxxc.find_library('shaderc_combined', dirs: meson.current_source_dir()/'install/lib'), + include_directories: shaderc_inc, +) + +meson.override_dependency('shaderc', shaderc_dep) diff --git a/subprojects/shaderc.wrap b/subprojects/shaderc.wrap new file mode 100644 index 0000000..ca9a081 --- /dev/null +++ b/subprojects/shaderc.wrap @@ -0,0 +1,12 @@ +[wrap-file] +directory = libshaderc + +source_url = https://storage.googleapis.com/shaderc/artifacts/prod/graphics_shader_compiler/shaderc/linux/continuous_clang_release/364/20210607-072233/install.tgz +source_filename = libshaderc-upstream.tgz +source_hash = f46dd35f6904af2b3330201ffb0f2f1ef5f8b8ede44491fad1a37b4a791772ef +lead_directory_missing = libshaderc + +patch_directory = libshaderc + +[provide] +dependency_names = shaderc