diff --git a/meson.build b/meson.build index 2a2a955..d90383f 100644 --- a/meson.build +++ b/meson.build @@ -1,12 +1,15 @@ -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/' run_command( 'python3', meson.source_root() + '/subprojects/evol/buildscripts/copy.py', src, dst) subdir('import') +cc = meson.get_compiler('c') +cc_id = cc.get_id() + subproject('evmod_ecs') mod_src = [ @@ -16,6 +19,7 @@ mod_src = [ 'src/loaders/TextLoader/TextLoader.c', 'src/loaders/JSONLoader/JSONLoader.c', 'src/loaders/MeshLoader/MeshLoader.c', + 'src/loaders/ShaderLoader/ShaderLoader.c', ] mod_incdir = [ @@ -25,10 +29,18 @@ mod_incdir = [ mod_deps = [ evmod_deps, + dependency('threads'), + dependency('assetsys'), dependency('evmod_ecs'), ] +if cc_id == 'msvc' + mod_deps += dependency('shaderc_msvc') +else + mod_deps += dependency('shaderc_clang') +endif + module = shared_module( 'evmodassetmanager', mod_src, include_directories: mod_incdir, diff --git a/meta/evmod.namespaces b/meta/evmod.namespaces index b56dae9..e33a1c4 100644 --- a/meta/evmod.namespaces +++ b/meta/evmod.namespaces @@ -30,3 +30,10 @@ EV_NS_DEF_BEGIN(MeshLoader) EV_NS_DEF_FN(MeshAsset, loadAsset, (AssetHandle, handle)) EV_NS_DEF_END(MeshLoader) + + +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 9d1040c..cd9ad62 100644 --- a/meta/evmod.types +++ b/meta/evmod.types @@ -10,6 +10,7 @@ TYPE(JSONAsset, struct { PTR json_data; }) + TYPE(MeshAsset, struct { uint32_t vertexBuferSize; uint32_t vertexCount; @@ -18,4 +19,26 @@ TYPE(MeshAsset, struct { uint32_t indexBuferSize; uint32_t indexCount; uint32_t *indexData; + +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 db1073f..51d7c7e 100644 --- a/src/mod.c +++ b/src/mod.c @@ -10,6 +10,7 @@ #include "loaders/TextLoader/TextLoader.h" #include "loaders/JSONLoader/JSONLoader.h" #include "loaders/MeshLoader/MeshLoader.h" +#include "loaders/ShaderLoader/ShaderLoader.h" #define AssetSysCheck(...) do { \ assetsys_error_t res = __VA_ARGS__; \ @@ -32,7 +33,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); } } @@ -42,7 +43,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]); } } @@ -52,11 +53,12 @@ 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 // onRemoveMeshAsset( // ECSQuery query) @@ -67,8 +69,19 @@ onRemoveJSONAsset( // } // } +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 ); @@ -88,11 +101,17 @@ EV_CONSTRUCTOR ev_jsonloader_setassettype(AssetECS->registerComponent("JSONAsset", sizeof(JSONAsset), EV_ALIGNOF(JSONAsset))); AssetECS->setOnRemoveTrigger("JSONAssetOnRemove", "JSONAsset", onRemoveJSONAsset); + ev_jsonloader_setassettype(AssetECS->registerComponent("MeshAsset", sizeof(MeshAsset), EV_ALIGNOF(MeshAsset))); // AssetECS->setOnRemoveTrigger("MeshAssetOnRemove", "MeshAsset", onRemoveMeshAsset); + + ev_shaderloader_setassettype(AssetECS->registerComponent("ShaderAsset", sizeof(ShaderAsset), EV_ALIGNOF(ShaderAsset))); + AssetECS->setOnRemoveTrigger("ShaderAssetOnRemove", "ShaderAsset", onRemoveShaderAsset); } } + ev_shaderloader_init(); + return AssetManagerData.sys == NULL; } @@ -106,6 +125,8 @@ EV_DESTRUCTOR if(AssetManagerData.ecs_mod) { evol_unloadmodule(AssetManagerData.ecs_mod); } + + ev_shaderloader_deinit(); return 0; } @@ -179,6 +200,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); @@ -191,5 +213,7 @@ EV_BINDINGS EV_NS_BIND_FN(MeshLoader, loadAsset, ev_meshloader_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..d5bbdbb --- /dev/null +++ b/subprojects/packagefiles/libshaderc/meson.build @@ -0,0 +1,14 @@ +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_msvc', shaderc_dep) +meson.override_dependency('shaderc_clang', shaderc_dep) diff --git a/subprojects/shaderc_clang.wrap b/subprojects/shaderc_clang.wrap new file mode 100644 index 0000000..5c20d09 --- /dev/null +++ b/subprojects/shaderc_clang.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-clang.tgz +source_hash = f46dd35f6904af2b3330201ffb0f2f1ef5f8b8ede44491fad1a37b4a791772ef +lead_directory_missing = libshaderc + +patch_directory = libshaderc + +[provide] +dependency_names = shaderc_clang diff --git a/subprojects/shaderc_msvc.wrap b/subprojects/shaderc_msvc.wrap new file mode 100644 index 0000000..32a9368 --- /dev/null +++ b/subprojects/shaderc_msvc.wrap @@ -0,0 +1,12 @@ +[wrap-file] +directory = libshaderc + +source_url = https://storage.googleapis.com/shaderc/artifacts/prod/graphics_shader_compiler/shaderc/windows/continuous_release_2017/368/20210607-072143/install.zip +source_filename = libshaderc-upstream-msvc.zip +source_hash = 5256f02a11dceb3390edaabd452a23ee48c4fe7b43bca754de87738adea96255 +lead_directory_missing = libshaderc + +patch_directory = libshaderc + +[provide] +dependency_names = shaderc_msvc