diff --git a/TODO b/TODO index a0740c4..9e017fe 100644 --- a/TODO +++ b/TODO @@ -23,8 +23,6 @@ Compiler / emulator: * Check for overrides on the same inputs when setting things up * Aliases * Display errors in UI -* Shader paths relative to scripts (will require different way of handling -libraries) Optimizer: diff --git a/c-opast.hh b/c-opast.hh index 8ac4a21..5ab152d 100644 --- a/c-opast.hh +++ b/c-opast.hh @@ -828,21 +828,22 @@ class T_PipelineInstrNode : public A_ResourceDefInstrNode class T_ProgramInstrNode : public A_ResourceDefInstrNode { private: - T_String path_; + T_FSPath path_; ebcl::T_SRDLocation pathLocation_; public: T_ProgramInstrNode( T_InstrListNode& parent , ebcl::T_SRDToken const& idToken , - ebcl::T_SRDToken const& pathToken ) noexcept + ebcl::T_FSPath path , + ebcl::T_SRDLocation const& pathLoc ) noexcept : A_ResourceDefInstrNode( OP_PROGRAM , parent , idToken , E_DataType::PROGRAM ) , - path_( pathToken.stringValue( ) ) , - pathLocation_( pathToken.location( ) ) + path_( std::move( path ) ) , + pathLocation_( pathLoc ) { } - T_String const& path( ) const noexcept + T_FSPath const& path( ) const noexcept { return path_; } ebcl::T_SRDLocation const& pathLocation( ) const noexcept { return pathLocation_; } diff --git a/c-opcomp.cc b/c-opcomp.cc index 75c0788..3675455 100644 --- a/c-opcomp.cc +++ b/c-opcomp.cc @@ -1,6 +1,10 @@ #include "externals.hh" + +#include "common.hh" +#include "c-project.hh" #include "c-ops.hh" #include "c-opcomp.hh" + #include using namespace ebcl; @@ -505,12 +509,13 @@ bool T_CompilerImpl_::compileNode( case A_Node::OP_PROGRAM: if ( exit ) { auto& pn( (T_ProgramInstrNode&) node ); - if ( !output->progNames.contains( pn.path( ) ) ) { - output->progNames.add( pn.path( ) ); + const auto p{ pn.path( ).makeRelative( Common::Project( ).basePath( ) ) }; + if ( !output->progNames.contains( p ) ) { + output->progNames.add( p ); } assert( locations.contains( pn.id( ) ) ); - addInstruction( OP_INIT_PROGRAM , output->progNames.indexOf( pn.path( ) ) , + addInstruction( OP_INIT_PROGRAM , output->progNames.indexOf( p ) , pn.location( ) ); addInstruction( OP_STORE , *locations.get( pn.id( ) ) , pn.idLocation( ) ); } diff --git a/c-opparser.cc b/c-opparser.cc index 185e9e7..576c5d9 100644 --- a/c-opparser.cc +++ b/c-opparser.cc @@ -1,5 +1,7 @@ #include "externals.hh" +#include "common.hh" +#include "c-project.hh" #include "c-opast.hh" #include "c-ops.hh" #include "c-opcomp.hh" @@ -1704,8 +1706,21 @@ M_INSTR_( Program ) return; } + T_FSPath path{ input[ 2 ].stringValue( ) }; + if ( path.isAbsolute( ) ) { + path = path.makeRelative( path.root( ) ); + path = ( Common::Project( ).basePath( ) + path ).canonical( ); + } else { + path = ( curFile.parent( ) + path ).canonical( ); + } + if ( !path.isUnder( Common::Project( ).basePath( ) ) ) { + errors.addNew( "shader is not in project directory" , + input[ 2 ].location( ) ); + } + T_ProgramInstrNode& program{ instructions.add< T_ProgramInstrNode >( - input[ 1 ] , input[ 2 ] ) }; + input[ 1 ] , std::move( path ) , + input[ 2 ].location( ) ) }; program.location( ) = input[ 0 ].location( ); } diff --git a/c-ops.hh b/c-ops.hh index 28c100a..86cd6c2 100644 --- a/c-ops.hh +++ b/c-ops.hh @@ -142,7 +142,7 @@ struct T_OpProgram nPipelines{ 0 } , // Amount of pipelines nSamplers{ 0 } , // Amount of samplers nTextures{ 0 }; // Amount of textures - T_Array< T_String > progNames; // GLSL program files + T_Array< T_FSPath > progNames; // GLSL program files T_Array< T_String > uiStrings; // UI strings for profiling, etc. T_Array< P_SyncOverrideSection > overrides; diff --git a/c-project.cc b/c-project.cc index 208ebd1..d718fbc 100644 --- a/c-project.cc +++ b/c-project.cc @@ -34,6 +34,12 @@ void T_Project::setBasePath( T_FSPath T_Project::pathOf( T_FSPath const& file ) const noexcept { + if ( file.isAbsolute( ) ) { + if ( file.canonical( ).isUnder( basePath_ ) ) { + return file; + } + return basePath_; + } return ( basePath_ + file ).canonical( ); } diff --git a/c-shaders.cc b/c-shaders.cc index 38a15b6..73561f0 100644 --- a/c-shaders.cc +++ b/c-shaders.cc @@ -1,4 +1,6 @@ #include "externals.hh" +#include "common.hh" +#include "c-project.hh" #include "c-shaders.hh" @@ -30,6 +32,7 @@ struct T_InputReader_ { using T_Tokens_ = std::vector< std::string >; + const T_FSPath path; FILE* const file; T_ShaderInput& input; uint32_t line{ 0 }; @@ -40,9 +43,10 @@ struct T_InputReader_ std::string accumulator{ }; uint32_t accumLines{ 0 }; - T_InputReader_( FILE* const file , + T_InputReader_( T_FSPath const& path , + FILE* const file , T_ShaderInput& input ) - : file( file ) , input( input ) + : path( path ) , file( file ) , input( input ) { } ~T_InputReader_( ); @@ -100,9 +104,28 @@ void T_InputReader_::handleDirective( error( "invalid arguments" ); return; } + + T_FSPath inclPath{ tokens[ 1 ].c_str( ) }; + if ( !inclPath.isValid( ) ) { + nl( ); + error( "invalid path" ); + return; + } + if ( inclPath.isAbsolute( ) ) { + inclPath = inclPath.makeRelative( inclPath.root( ) ); + inclPath = ( Common::Project( ).basePath( ) + inclPath ).canonical( ); + } else { + inclPath = ( path.parent( ) + inclPath ).canonical( ); + } + if ( !inclPath.isUnder( Common::Project( ).basePath( ) ) ) { + nl( ); + error( "path is outside of project" ); + return; + } + addAccumulated( ); auto& ck( input.chunks ); - ck.addNew( E_ShaderInputChunk::INCLUDE , tokens[ 1 ].c_str( ) , 1 ); + ck.addNew( inclPath , 1 ); } else if ( directive == "type" ) { nl( ); @@ -141,8 +164,7 @@ void T_InputReader_::addAccumulated( ) { if ( accumLines ) { auto& ck( input.chunks ); - ck.addNew( E_ShaderInputChunk::CODE , - accumulator.c_str( ) , accumLines ); + ck.addNew( accumulator.c_str( ) , accumLines ); accumulator = {}; accumLines = 0; } @@ -154,18 +176,19 @@ void T_InputReader_::addAccumulated( ) /*= T_ShaderInput ============================================================*/ bool T_ShaderInput::load( - T_String const& path ) + T_FSPath const& path ) { type = E_ShaderInput::CHUNK; chunks.clear( ); errors.clear( ); - FILE* const file{ fopen( (char const*) path.toOSString( ).data( ) , "r" ) }; + const auto osPath{ path.toString( ).toOSString( ) }; + FILE* const file{ fopen( (char const*) osPath.data( ) , "r" ) }; if ( !file ) { return false; } - T_InputReader_ reader( file , *this ); + T_InputReader_ reader{ path , file , *this }; reader.read( ); return true; diff --git a/c-shaders.hh b/c-shaders.hh index 5ea3741..d7e2918 100644 --- a/c-shaders.hh +++ b/c-shaders.hh @@ -17,20 +17,20 @@ enum class E_ShaderType { // the input loader, the shader loader or the driver. struct T_ShaderError { - T_String source; + T_FSPath source; uint32_t line; T_String error; T_ShaderError( ) = default; - T_ShaderError( T_String source , + T_ShaderError( T_FSPath source , const uint32_t line , T_String error ) : source( std::move( source ) ) , line( line ) , error( std::move( error ) ) { } - T_ShaderError( T_String source , + T_ShaderError( T_FSPath source , const uint32_t line , T_StringBuilder& error ) : source( std::move( source ) ) , line( line ) , @@ -51,15 +51,25 @@ enum class E_ShaderInputChunk { struct T_ShaderInputChunk { E_ShaderInputChunk type; - T_String text; + T_Union< T_String , T_FSPath > data; uint32_t lines; T_ShaderInputChunk( ) = default; + T_ShaderInputChunk( - const E_ShaderInputChunk type , T_String text , const uint32_t lines ) - : type( type ) , text( std::move( text ) ) , lines( lines ) + : type( E_ShaderInputChunk::CODE ) , + data( std::move( text ) ) , + lines( lines ) + { } + + T_ShaderInputChunk( + T_FSPath path , + const uint32_t lines ) + : type( E_ShaderInputChunk::INCLUDE ) , + data( std::move( path ) ) , + lines( lines ) { } }; @@ -93,6 +103,6 @@ struct T_ShaderInput T_Array< T_ShaderInputChunk > chunks; T_Array< T_ShaderInputError > errors; - bool load( T_String const& path ); + bool load( T_FSPath const& path ); }; using P_ShaderInput = T_OwnPtr< T_ShaderInput >; diff --git a/test/demo.srd b/test/demo.srd index 69d3872..8f80f0e 100644 --- a/test/demo.srd +++ b/test/demo.srd @@ -1,7 +1,7 @@ -(include "fx-bloom.srd") -(include "fx-dof.srd") -(include "fx-combine.srd") -(include "fx-fxaa.srd") +(include "fx-bloom/fx-bloom.srd") +(include "fx-dof/fx-dof.srd") +(include "fx-combine/fx-combine.srd") +(include "fx-fxaa/fx-fxaa.srd") (init # Compute viewport size @@ -20,7 +20,7 @@ (set vp-x (div (sub $width $vp-width) 2)) (set vp-y (div (sub $height $vp-height) 2)) - (program prg-fullscreen "fullscreen.v.glsl") + (program prg-fullscreen "/fullscreen.v.glsl") (set use-compute 1) diff --git a/test/shaders/fullscreen.v.glsl b/test/fullscreen.v.glsl similarity index 100% rename from test/shaders/fullscreen.v.glsl rename to test/fullscreen.v.glsl diff --git a/test/shaders/bloom-highpass.f.glsl b/test/fx-bloom/bloom-highpass.f.glsl similarity index 100% rename from test/shaders/bloom-highpass.f.glsl rename to test/fx-bloom/bloom-highpass.f.glsl diff --git a/test/shaders/blur-pass.f.glsl b/test/fx-bloom/blur-pass.f.glsl similarity index 100% rename from test/shaders/blur-pass.f.glsl rename to test/fx-bloom/blur-pass.f.glsl diff --git a/test/shaders/downsample.f.glsl b/test/fx-bloom/downsample.f.glsl similarity index 100% rename from test/shaders/downsample.f.glsl rename to test/fx-bloom/downsample.f.glsl diff --git a/test/fx-bloom.srd b/test/fx-bloom/fx-bloom.srd similarity index 100% rename from test/fx-bloom.srd rename to test/fx-bloom/fx-bloom.srd diff --git a/test/shaders/combine.c.glsl b/test/fx-combine/combine.c.glsl similarity index 98% rename from test/shaders/combine.c.glsl rename to test/fx-combine/combine.c.glsl index 8776efd..4da4e24 100644 --- a/test/shaders/combine.c.glsl +++ b/test/fx-combine/combine.c.glsl @@ -6,7 +6,7 @@ layout( ) in; //! type compute -//! include lib/utils.glsl +//! include /lib/utils.glsl layout( location = 0 ) uniform sampler2D u_MainInput; layout( location = 1 ) uniform sampler2D u_BlurInput; diff --git a/test/shaders/combine.f.glsl b/test/fx-combine/combine.f.glsl similarity index 98% rename from test/shaders/combine.f.glsl rename to test/fx-combine/combine.f.glsl index 2205da4..f1bb8ae 100644 --- a/test/shaders/combine.f.glsl +++ b/test/fx-combine/combine.f.glsl @@ -1,7 +1,7 @@ #version 450 core //! type fragment -//! include lib/utils.glsl +//! include /lib/utils.glsl layout( location = 0 ) uniform sampler2D u_MainInput; layout( location = 1 ) uniform sampler2D u_BlurInput; diff --git a/test/fx-combine.srd b/test/fx-combine/fx-combine.srd similarity index 100% rename from test/fx-combine.srd rename to test/fx-combine/fx-combine.srd diff --git a/test/shaders/chunks/dof-cs.glsl b/test/fx-dof/dof-cs.glsl similarity index 98% rename from test/shaders/chunks/dof-cs.glsl rename to test/fx-dof/dof-cs.glsl index 7130d21..d6ddefb 100644 --- a/test/shaders/chunks/dof-cs.glsl +++ b/test/fx-dof/dof-cs.glsl @@ -17,7 +17,7 @@ layout( location = 4 ) uniform vec3 u_ResolutionTime; layout( binding = 0 , rgba16f ) writeonly uniform image2D u_Output; -//!include lib/utils.glsl +//!include /lib/utils.glsl float DOF_CoC( in float z ) diff --git a/test/shaders/lib/dof.glsl b/test/fx-dof/dof-lib.glsl similarity index 97% rename from test/shaders/lib/dof.glsl rename to test/fx-dof/dof-lib.glsl index 5fd17c5..9807a71 100644 --- a/test/shaders/lib/dof.glsl +++ b/test/fx-dof/dof-lib.glsl @@ -1,5 +1,5 @@ //!type library -//!include lib/utils.glsl +//!include /lib/utils.glsl float DOF_CoC( in float z ) diff --git a/test/shaders/dof-pass1.c.glsl b/test/fx-dof/dof-pass1.c.glsl similarity index 92% rename from test/shaders/dof-pass1.c.glsl rename to test/fx-dof/dof-pass1.c.glsl index 0e9315a..d8a2a49 100644 --- a/test/shaders/dof-pass1.c.glsl +++ b/test/fx-dof/dof-pass1.c.glsl @@ -7,7 +7,7 @@ layout( local_size_y = 64 ) in; -//! include chunks/dof-cs.glsl +//! include dof-cs.glsl void main() { diff --git a/test/shaders/dof-pass1.f.glsl b/test/fx-dof/dof-pass1.f.glsl similarity index 89% rename from test/shaders/dof-pass1.f.glsl rename to test/fx-dof/dof-pass1.f.glsl index 800ff2d..825e041 100644 --- a/test/shaders/dof-pass1.f.glsl +++ b/test/fx-dof/dof-pass1.f.glsl @@ -1,7 +1,7 @@ #version 450 core //! type fragment -//! include chunks/dof.glsl +//! include dof.glsl void main() { diff --git a/test/shaders/dof-pass2.c.glsl b/test/fx-dof/dof-pass2.c.glsl similarity index 95% rename from test/shaders/dof-pass2.c.glsl rename to test/fx-dof/dof-pass2.c.glsl index d322ce1..269fa40 100644 --- a/test/shaders/dof-pass2.c.glsl +++ b/test/fx-dof/dof-pass2.c.glsl @@ -7,7 +7,7 @@ layout( local_size_y = 20 ) in; -//! include chunks/dof-cs.glsl +//! include dof-cs.glsl void main() { diff --git a/test/shaders/dof-pass2.f.glsl b/test/fx-dof/dof-pass2.f.glsl similarity index 94% rename from test/shaders/dof-pass2.f.glsl rename to test/fx-dof/dof-pass2.f.glsl index 16ab9f7..2814ed1 100644 --- a/test/shaders/dof-pass2.f.glsl +++ b/test/fx-dof/dof-pass2.f.glsl @@ -1,7 +1,7 @@ #version 450 core //! type fragment -//! include chunks/dof.glsl +//! include dof.glsl void main() { diff --git a/test/shaders/chunks/dof.glsl b/test/fx-dof/dof.glsl similarity index 95% rename from test/shaders/chunks/dof.glsl rename to test/fx-dof/dof.glsl index e18b7aa..c447232 100644 --- a/test/shaders/chunks/dof.glsl +++ b/test/fx-dof/dof.glsl @@ -20,4 +20,4 @@ layout( location = 4 ) uniform vec3 u_ResolutionTime; layout( location = 0 ) out vec3 o_Color; -//!include lib/dof.glsl +//!include dof-lib.glsl diff --git a/test/fx-dof.srd b/test/fx-dof/fx-dof.srd similarity index 100% rename from test/fx-dof.srd rename to test/fx-dof/fx-dof.srd diff --git a/test/fx-fxaa.srd b/test/fx-fxaa/fx-fxaa.srd similarity index 100% rename from test/fx-fxaa.srd rename to test/fx-fxaa/fx-fxaa.srd diff --git a/test/shaders/chunks/fxaa-3.11.glsl b/test/fx-fxaa/fxaa-3.11.glsl similarity index 100% rename from test/shaders/chunks/fxaa-3.11.glsl rename to test/fx-fxaa/fxaa-3.11.glsl diff --git a/test/shaders/fxaa.f.glsl b/test/fx-fxaa/fxaa.f.glsl similarity index 97% rename from test/shaders/fxaa.f.glsl rename to test/fx-fxaa/fxaa.f.glsl index e3eb9bb..a4fc38d 100644 --- a/test/shaders/fxaa.f.glsl +++ b/test/fx-fxaa/fxaa.f.glsl @@ -8,7 +8,7 @@ #define FXAA_GATHER4_ALPHA 1 #define FXAA_QUALITY__PRESET 39 -//! include chunks/fxaa-3.11.glsl +//! include fxaa-3.11.glsl layout( location = 0 ) uniform sampler2D u_Input; layout( location = 1 ) uniform vec4 u_Viewport; diff --git a/test/shaders/lib/fog.glsl b/test/lib/fog.glsl similarity index 100% rename from test/shaders/lib/fog.glsl rename to test/lib/fog.glsl diff --git a/test/shaders/lib/hg_sdf.glsl b/test/lib/hg_sdf.glsl similarity index 96% rename from test/shaders/lib/hg_sdf.glsl rename to test/lib/hg_sdf.glsl index a9285c0..48c6776 100644 --- a/test/shaders/lib/hg_sdf.glsl +++ b/test/lib/hg_sdf.glsl @@ -126,7 +126,7 @@ //! type library -//! include lib/utils.glsl +//! include utils.glsl diff --git a/test/shaders/chunks/raymarcher-cs.glsl b/test/lib/raymarcher-cs.glsl similarity index 95% rename from test/shaders/chunks/raymarcher-cs.glsl rename to test/lib/raymarcher-cs.glsl index 4d33ec7..9818222 100644 --- a/test/shaders/chunks/raymarcher-cs.glsl +++ b/test/lib/raymarcher-cs.glsl @@ -19,4 +19,4 @@ layout( location = 8 ) uniform int u_Correction; //layout( location = 1 ) out float o_Z; layout( binding = 0 , rgba16f ) writeonly uniform image2D u_Output; -//! include lib/raymarching.glsl +//! include raymarching.glsl diff --git a/test/shaders/chunks/raymarcher.glsl b/test/lib/raymarcher.glsl similarity index 94% rename from test/shaders/chunks/raymarcher.glsl rename to test/lib/raymarcher.glsl index a11a929..aa80915 100644 --- a/test/shaders/chunks/raymarcher.glsl +++ b/test/lib/raymarcher.glsl @@ -13,4 +13,4 @@ layout( location = 8 ) uniform int u_Correction; layout( location = 0 ) out vec3 o_Color; layout( location = 1 ) out float o_Z; -//! include lib/raymarching.glsl +//! include raymarching.glsl diff --git a/test/shaders/lib/raymarching.glsl b/test/lib/raymarching.glsl similarity index 99% rename from test/shaders/lib/raymarching.glsl rename to test/lib/raymarching.glsl index 8a651d4..f9f9648 100644 --- a/test/shaders/lib/raymarching.glsl +++ b/test/lib/raymarching.glsl @@ -1,5 +1,5 @@ //! type library -//! include lib/utils.glsl +//! include utils.glsl vec2 RM_Map( in vec3 pos ); diff --git a/test/shaders/lib/shading-blinnphong.glsl b/test/lib/shading-blinnphong.glsl similarity index 100% rename from test/shaders/lib/shading-blinnphong.glsl rename to test/lib/shading-blinnphong.glsl diff --git a/test/shaders/lib/shading-pbr.glsl b/test/lib/shading-pbr.glsl similarity index 99% rename from test/shaders/lib/shading-pbr.glsl rename to test/lib/shading-pbr.glsl index 325e9d1..48365bf 100644 --- a/test/shaders/lib/shading-pbr.glsl +++ b/test/lib/shading-pbr.glsl @@ -1,5 +1,5 @@ //! type library -//! include lib/utils.glsl +//! include utils.glsl struct T_PBRMaterial diff --git a/test/shaders/lib/utils.glsl b/test/lib/utils.glsl similarity index 100% rename from test/shaders/lib/utils.glsl rename to test/lib/utils.glsl diff --git a/test/shaders/scene.c.glsl b/test/scene.c.glsl similarity index 96% rename from test/shaders/scene.c.glsl rename to test/scene.c.glsl index a561218..800413c 100644 --- a/test/shaders/scene.c.glsl +++ b/test/scene.c.glsl @@ -1,12 +1,12 @@ #version 450 core //! type compute -//! include chunks/raymarcher-cs.glsl -//! include lib/hg_sdf.glsl +//! include /lib/raymarcher-cs.glsl +//! include /lib/hg_sdf.glsl -//! include lib/shading-pbr.glsl -//! include lib/shading-blinnphong.glsl -//! include lib/fog.glsl +//! include /lib/shading-pbr.glsl +//! include /lib/shading-blinnphong.glsl +//! include /lib/fog.glsl T_BPMaterial BPMaterials[1] = { diff --git a/test/shaders/scene.f.glsl b/test/scene.f.glsl similarity index 95% rename from test/shaders/scene.f.glsl rename to test/scene.f.glsl index 3a7237f..9040dc7 100644 --- a/test/shaders/scene.f.glsl +++ b/test/scene.f.glsl @@ -1,12 +1,12 @@ #version 450 core //! type fragment -//! include chunks/raymarcher.glsl -//! include lib/hg_sdf.glsl +//! include /lib/raymarcher.glsl +//! include /lib/hg_sdf.glsl -//! include lib/shading-pbr.glsl -//! include lib/shading-blinnphong.glsl -//! include lib/fog.glsl +//! include /lib/shading-pbr.glsl +//! include /lib/shading-blinnphong.glsl +//! include /lib/fog.glsl T_BPMaterial BPMaterials[1] = { diff --git a/ui-opemu.cc b/ui-opemu.cc index 6b99cef..a35886e 100644 --- a/ui-opemu.cc +++ b/ui-opemu.cc @@ -436,7 +436,7 @@ void T_OpContext::run( if ( !prIndex ) { throw X_OpFailure{ instr , "pipeline uses uninitialised program" }; } - progNames[ i ] = programs[ prIndex - 1 ]->name( ); + progNames[ i ] = programs[ prIndex - 1 ]->name( ).toString( ); } pipelines[ plIndex ] = NewOwned< T_ShaderPipeline >( diff --git a/ui-shaders.cc b/ui-shaders.cc index 1a5bbfa..0928d98 100644 --- a/ui-shaders.cc +++ b/ui-shaders.cc @@ -133,7 +133,7 @@ T_Optional< E_ShaderType > T_ShaderProgram::type( ) const } } -T_String T_ShaderProgram::name( ) const +T_FSPath T_ShaderProgram::name( ) const { if ( id_ ) { return UI::Shaders( ).programs_[ id_ - 1 ].name; @@ -260,32 +260,32 @@ GLuint T_ShaderPipeline::program( namespace { -using F_GetInput_ = std::function< T_ShaderInput const*( T_String const& ) >; +using F_GetInput_ = std::function< T_ShaderInput const*( T_FSPath const& ) >; using T_Code_ = T_ShaderManager::T_ShaderCode; // Code builder, state and functions struct T_CodeBuilder_ { struct T_StackEntry_ { - T_String name; + T_FSPath name; T_ShaderInput const* input; uint32_t pos; }; F_GetInput_ loader; - const T_String name; + const T_FSPath name; T_Code_& code; T_ShaderInput const* main; - T_KeyValueTable< T_String , uint32_t > pos; + T_KeyValueTable< T_FSPath , uint32_t > pos; std::vector< T_StackEntry_ > stack; - T_Array< T_String > libraries; + T_Array< T_FSPath > libraries; T_ShaderInput const* current; uint32_t cpos{ 0 }; - T_String cname; + T_FSPath cname; T_CodeBuilder_( F_GetInput_ loader , - T_String const& name , + T_FSPath const& name , T_Code_& code ) : loader( loader ) , name( name ) , code( code ) , main( loader( name ) ) @@ -293,13 +293,13 @@ struct T_CodeBuilder_ bool buildCode( ); void appendChunk( T_ShaderInputChunk const& chunk ); - void include( T_String const& name , + void include( T_FSPath const& name , const uint32_t lines ); void next( ); void addInputLoaderErrors( T_ShaderInput const* input , - T_String const& name ); + T_FSPath const& name ); }; /*----------------------------------------------------------------------------*/ @@ -326,7 +326,7 @@ bool T_CodeBuilder_::buildCode( ) if ( chunk.type == E_ShaderInputChunk::CODE ) { appendChunk( chunk ); } else { - include( chunk.text , chunk.lines ); + include( chunk.data.value< T_FSPath >( ) , chunk.lines ); } next( ); @@ -347,12 +347,12 @@ void T_CodeBuilder_::appendChunk( code.sources.addNew( cname ); code.counts.add( chunk.lines ); code.starts.add( *p ); - code.code << chunk.text; + code.code << chunk.data.value< T_String >( ); *p += chunk.lines; } void T_CodeBuilder_::include( - T_String const& nname , + T_FSPath const& nname , const uint32_t lines ) { auto* const p( pos.get( cname ) ); @@ -376,7 +376,7 @@ void T_CodeBuilder_::include( return; } - T_ShaderInput const* const isi( loader( nname ) ); + T_ShaderInput const* const isi{ loader( nname ) }; code.files.add( nname , isi != nullptr ); // Check for problems @@ -420,7 +420,7 @@ void T_CodeBuilder_::next( ) void T_CodeBuilder_::addInputLoaderErrors( T_ShaderInput const* input , - T_String const& name ) + T_FSPath const& name ) { for ( auto const& errs : input->errors ) { code.errors.addNew( name , errs.line , (char*) errs.error.toOSString( ).data( ) ); @@ -441,7 +441,7 @@ T_ShaderManager::T_ShaderManager( ) noexcept /*----------------------------------------------------------------------------*/ T_ShaderProgram T_ShaderManager::program( - T_String const& name ) + T_FSPath const& name ) { loadProgram( name ); assert( programIndex_.contains( name ) ); @@ -530,16 +530,16 @@ T_ShaderPipeline T_ShaderManager::pipeline( void T_ShaderManager::update( ) { using namespace ebcl; - T_Set< T_String > temp{ UseTag< ArrayBacked< 64 > >( ) }; + T_Set< T_FSPath > temp{ UseTag< ArrayBacked< 64 > >( ) }; T_StringBuilder sb; inputs_.clear( ); // Check for missing files for ( auto it = missing_.keys( ).cbegin( ) ; it.valid( ) ; ++it ) { - const bool exists( ([] ( T_String const& name ) -> bool { - T_FSPath p{ T_FSPath{ "shaders" } + T_FSPath{ name } }; + const bool exists( ([] ( T_FSPath const& name ) -> bool { struct stat buffer; - return ( stat( Common::Project( ).strPathOf( p ).data( ) , &buffer ) == 0 ); + const auto p{ Common::Project( ).strPathOf( name ).toOSString( ) }; + return ( stat( (char const*) p.data( ) , &buffer ) == 0 ); })( *it ) ); if ( !exists ) { continue; @@ -613,7 +613,7 @@ void T_ShaderManager::update( ) void T_ShaderManager::loadProgram( T_String const& pipeline , - T_String const& name ) + T_FSPath const& name ) { if ( !useExistingProgram( pipeline , name ) ) { initProgramRecord( name ).plReferences.add( pipeline ); @@ -622,7 +622,7 @@ void T_ShaderManager::loadProgram( bool T_ShaderManager::useExistingProgram( T_String const& pipeline , - T_String const& name ) + T_FSPath const& name ) { auto const* pos( programIndex_.get( name ) ); if ( !pos ) { @@ -635,7 +635,7 @@ bool T_ShaderManager::useExistingProgram( } void T_ShaderManager::loadProgram( - T_String const& name ) + T_FSPath const& name ) { if ( !useExistingProgram( name ) ) { initProgramRecord( name ); @@ -653,7 +653,7 @@ void T_ShaderManager::loadBuiltinProgram( } bool T_ShaderManager::useExistingProgram( - T_String const& name ) + T_FSPath const& name ) { auto const* pos( programIndex_.get( name ) ); if ( !pos ) { @@ -680,7 +680,7 @@ uint32_t T_ShaderManager::newProgramRecord( ) } T_ShaderManager::T_Program_& T_ShaderManager::initProgramRecord( - T_String const& name , + T_FSPath const& name , const E_ShaderType type , char const* const source ) { @@ -713,24 +713,32 @@ T_ShaderManager::T_Program_& T_ShaderManager::initProgramRecord( /*----------------------------------------------------------------------------*/ T_ShaderInput const* T_ShaderManager::getInput( - T_String const& name ) + T_FSPath const& name ) { - auto const* const existing( inputs_.get( name ) ); + T_FSPath extra; + T_FSPath const* absPath; + T_FSPath const* relPath; + if ( name.isAbsolute( ) ) { + extra = name.makeRelative( Common::Project( ).basePath( ) ); + absPath = &name; + relPath = &extra; + } else { + extra = Common::Project( ).pathOf( name ); + absPath = &extra; + relPath = &name; + } + + auto const* const existing( inputs_.get( *relPath ) ); if ( existing ) { return existing->get( ); } T_ShaderInput ni; - const T_String path{ [&]() -> T_String { - T_StringBuilder sb; - sb << "shaders/" << name; - return std::move( sb ); - }() }; - if ( !ni.load( Common::Project( ).strPathOf( path ) ) ) { + if ( !ni.load( *absPath ) ) { return nullptr; } - inputs_.add( name , NewOwned< T_ShaderInput >( std::move( ni ) ) ); - return inputs_.get( name )->get( ); + inputs_.add( *relPath , NewOwned< T_ShaderInput >( std::move( ni ) ) ); + return inputs_.get( *relPath )->get( ); } /*----------------------------------------------------------------------------*/ @@ -844,15 +852,13 @@ void T_ShaderManager::initProgram( // Build the code auto name( program.name ); - printf( "init program %s\n" , program.name.toOSString( ).data( ) ); + printf( "init program %s\n" , program.name.toString( ).toOSString( ).data( ) ); auto& code( program.code ); - T_CodeBuilder_ cb( [this]( T_String const& n ) { return getInput( n ); } , - name , code ); - const bool built( - T_CodeBuilder_{ - [this]( T_String const& n ) { return getInput( n ); } , - program.name , code - }.buildCode( ) ); + T_CodeBuilder_ cb{ + [this]( T_FSPath const& n ) { return getInput( n ); } , + name , code + }; + const bool built{ cb.buildCode( ) }; // Initialise file watcher + missing files program.watch = T_WatchedFiles{ Common::Watcher( ) , @@ -862,10 +868,9 @@ void T_ShaderManager::initProgram( const auto nf( code.files.size( ) ); auto& w( *( program.watch.target( ) ) ); for ( auto i = 0u ; i < nf ; i ++ ) { - T_String const& fn( code.files.keys( )[ i ] ); + T_FSPath const& fn( code.files.keys( )[ i ] ); if ( code.files.values( )[ i ] ) { - T_FSPath p{ T_FSPath{ "shaders" } + T_FSPath{ fn } }; - w.watch( Common::Project( ).strPathOf( p ) ); + w.watch( Common::Project( ).pathOf( fn ) ); } else { auto& mset( missing_.getOrCreate( fn ) ); if ( !mset.contains( name ) ) { @@ -875,6 +880,7 @@ void T_ShaderManager::initProgram( } if ( !( built && code.errors.empty( ) ) ) { + printf( "... failed\n" ); return; } buildProgram( program ); @@ -887,7 +893,7 @@ void T_ShaderManager::initBuiltinProgram( { auto name( program.name ); printf( "init built-in program %s\n" , - program.name.substr( 1 ).toOSString( ).data( ) ); + program.name.toString( ).substr( 1 ).toOSString( ).data( ) ); program.code.code << source << '\0'; program.code.type = type; @@ -968,7 +974,7 @@ void T_ShaderManager::parseGLSLError( } code.errors.addNew( - pos == 0 ? "*unknown*" : ((char*)code.sources[ pos - 1 ].toOSString( ).data( ) ) , + pos == 0 ? T_FSPath{ "*unknown*" } : code.sources[ pos - 1 ] , pos == 0 ? 0 : ( rawLine + code.counts[ pos - 1 ] - check + code.starts[ pos - 1 ] ) , errorLine ); } @@ -976,7 +982,7 @@ void T_ShaderManager::parseGLSLError( /*----------------------------------------------------------------------------*/ void T_ShaderManager::programUpdated( - T_String const& name ) + T_FSPath const& name ) { if ( !updates_.contains( name ) ) { updates_.add( name ); @@ -998,7 +1004,7 @@ void T_ShaderManager::resetProgram( auto const& files( program.code.files ); const auto nf( files.size( ) ); for ( auto i = 0u ; i < nf ; i ++ ) { - T_String const& k{ files.keys( )[ i ] }; + T_FSPath const& k{ files.keys( )[ i ] }; bool v{ files[ i ] }; auto* const ptr( missing_.get( k ) ); if ( v || !ptr ) { @@ -1032,7 +1038,7 @@ void T_ShaderManager::makeUI( ) const auto n( std::count_if( programs_.begin( ) , programs_.end( ) , []( auto const& p ) { return ( !p.plReferences.empty( ) || p.saReferences != 0 ) - && !p.name.startsWith( "*" ); + && p.name.isValid( ); } ) ); std::vector< size_t > indices; @@ -1040,7 +1046,7 @@ void T_ShaderManager::makeUI( ) for ( auto i = 0u ; i < rn ; i ++ ) { auto const& p( programs_[ i ] ); if ( ( !p.plReferences.empty( ) || p.saReferences ) - && !p.name.startsWith( "*" ) ) { + && p.name.isValid( ) ) { indices.push_back( i ); } } @@ -1064,11 +1070,11 @@ void T_ShaderManager::makeUI( ) const bool open( nErrors ? TreeNodeEx( &program , ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick , "%s" , - program.name.toOSString( ).data( ) ) + program.name.toString( ).toOSString( ).data( ) ) : false ); if ( !nErrors ) { - Text( "%s" , program.name.toOSString( ).data( ) ); + Text( "%s" , program.name.toString( ).toOSString( ).data( ) ); } SameLine( 400 ); @@ -1087,10 +1093,12 @@ void T_ShaderManager::makeUI( ) for ( auto const& err : program.code.errors ) { NewLine( ); SameLine( 50 ); - Text( "%s" , err.source.toOSString( ).data( ) ); - SameLine( 250 ); + Text( "%s" , err.source.makeRelative( + Common::Project( ).basePath( ) + ).toString( ).toOSString( ).data( ) ); + SameLine( 350 ); Text( "line %d" , err.line ); - SameLine( 370 ); + SameLine( 470 ); Text( "%s" , err.error.toOSString( ).data( ) ); } TreePop( ); diff --git a/ui-shaders.hh b/ui-shaders.hh index 5700046..cdd41fb 100644 --- a/ui-shaders.hh +++ b/ui-shaders.hh @@ -18,7 +18,7 @@ struct T_ShaderProgram void enable( ) const; GLuint id( ) const; T_Optional< E_ShaderType > type( ) const; - T_String name( ) const; + T_FSPath name( ) const; private: explicit T_ShaderProgram( uint32_t id ) noexcept; @@ -56,16 +56,16 @@ struct T_ShaderManager E_ShaderType type; T_AutoArray< uint32_t , 8 > starts; // Position of chunk in source file T_AutoArray< uint32_t , 8 > counts; // Chunk lengths - T_AutoArray< T_String , 8 > sources; // Chunk source files + T_AutoArray< T_FSPath , 8 > sources; // Chunk source files T_StringBuilder code; T_Array< T_ShaderError > errors; - T_KeyValueTable< T_String , bool > files; + T_KeyValueTable< T_FSPath , bool > files; }; T_ShaderManager( ) noexcept; // Build / get a program based on its name - T_ShaderProgram program( T_String const& name ); + T_ShaderProgram program( T_FSPath const& name ); // Build a program from its source code T_ShaderProgram program( T_String const& name , E_ShaderType type , @@ -112,7 +112,7 @@ struct T_ShaderManager struct T_Program_ { - T_String name; + T_FSPath name; T_Array< T_String > plReferences; uint32_t saReferences{ 0 }; T_ShaderCode code; @@ -122,43 +122,43 @@ struct T_ShaderManager bool uiEnabled_ = false; - T_ObjectTable< T_String , T_Pipeline_ > pipelines_; + T_ObjectTable< T_FSPath , T_Pipeline_ > pipelines_; T_Array< T_Program_ > programs_; - T_KeyValueTable< T_String , uint32_t > programIndex_; + T_KeyValueTable< T_FSPath , uint32_t > programIndex_; - T_KeyValueTable< T_String , P_ShaderInput > inputs_; + T_KeyValueTable< T_FSPath , P_ShaderInput > inputs_; - T_KeyValueTable< T_String , T_Array< T_String > > missing_; - T_Array< T_String > updates_; + T_KeyValueTable< T_FSPath , T_Array< T_FSPath > > missing_; + T_Array< T_FSPath > updates_; T_String cPipeline_{ }; // Load/use existing program for use with pipelines void loadProgram( T_String const& pipeline , - T_String const& name ); + T_FSPath const& name ); bool useExistingProgram( T_String const& pipeline , - T_String const& name ); + T_FSPath const& name ); // Load/use existing program for standalone use - void loadProgram( T_String const& name ); + void loadProgram( T_FSPath const& name ); void loadBuiltinProgram( T_String const& name , E_ShaderType type , char const* source ); - bool useExistingProgram( T_String const& name ); + bool useExistingProgram( T_FSPath const& name ); // Program management T_Program_& initProgramRecord( // Init management data - T_String const& record , + T_FSPath const& record , E_ShaderType type = E_ShaderType::__COUNT__ , char const* source = nullptr ); uint32_t newProgramRecord( ); // Allocate entry in index T_ShaderInput const* getInput( - T_String const& name ); + T_FSPath const& name ); void dereferencePipeline( T_String const& id ); void dereferenceProgram( @@ -178,6 +178,6 @@ struct T_ShaderManager T_ShaderCode& code , char const* errorLine ); - void programUpdated( T_String const& name ); + void programUpdated( T_FSPath const& name ); void resetProgram( T_Program_& program ); };