#pragma once #include "filewatcher.hh" #include "utilities.hh" /*= INPUT FILES ==============================================================*/ // Type of input chunk enum class E_ShaderInputChunk { CODE , INCLUDE }; // Input chunk data struct T_ShaderInputChunk { E_ShaderInputChunk type; std::string text; uint32_t lines; T_ShaderInputChunk( ) = default; T_ShaderInputChunk( __rd__ const E_ShaderInputChunk type , __rd__ std::string text , __rd__ const uint32_t lines ) : type( type ) , text( std::move( text ) ) , lines( lines ) { } }; // Input file type enum class E_ShaderInput { CHUNK , // Chunk that may be repeated LIBRARY , // Library (will only be loaded once) // "Main" shader source files VERTEX , FRAGMENT , GEOMETRY , COMPUTE }; // Preprocessing errors struct T_ShaderInputError { uint32_t line; std::string error; }; // Source file struct T_ShaderInput { E_ShaderInput type = E_ShaderInput::CHUNK; std::vector< T_ShaderInputChunk > chunks; std::vector< T_ShaderInputError > errors; bool load( __rd__ std::string const& path ); }; using P_ShaderInput = std::unique_ptr< T_ShaderInput >; // Type of shader enum class E_ShaderType { VERTEX , FRAGMENT , GEOMETRY , COMPUTE , __COUNT__ }; // Errors in shader code - the errors it represents may come from either // the input loader, the shader loader or the driver. struct T_ShaderError { std::string source; uint32_t line; std::string error; }; struct T_ShaderManager; struct T_ShaderPipeline { friend struct T_ShaderManager; T_ShaderPipeline( ); COPY( T_ShaderPipeline ); MOVE( T_ShaderPipeline ); ~T_ShaderPipeline( ); bool valid( ) const noexcept; void enable( ) const; GLuint program( __rd__ const E_ShaderType program ) const; private: explicit T_ShaderPipeline( __rd__ const int32_t index ); int32_t smIndex_; }; struct T_ShaderManager { friend struct T_ShaderPipeline; struct T_ShaderCode { E_ShaderType type; std::vector< uint32_t > starts; // Position of chunk in source file std::vector< uint32_t > counts; // Chunk lengths std::vector< std::string > sources; // Chunk source files std::string code; std::vector< T_ShaderError > errors; std::map< std::string , bool > files; }; T_ShaderPipeline pipeline( __rd__ std::initializer_list< std::string > shaders ); void update( ); private: struct T_Pipeline_ { uint32_t references; std::string idString; GLuint id; std::vector< std::string > programs; }; struct T_Program_ { std::string name; std::set< uint32_t > references; T_ShaderCode code; GLuint id; std::unique_ptr< T_WatchedFiles > watch; }; std::vector< T_Pipeline_ > pipelines_; std::map< std::string , uint32_t > pipelineIndex_; std::vector< T_Program_ > programs_; std::map< std::string , uint32_t > programIndex_; std::map< std::string , P_ShaderInput > inputs_; std::map< std::string , std::set< std::string > > missing_; std::set< std::string > updates_; uint32_t newPipelineRecord( ); uint32_t newProgramRecord( ); void loadProgram( __rd__ const uint32_t pipeline , __rd__ std::string const& name ); bool useExistingProgram( __rd__ const uint32_t pipeline , __rd__ std::string const& name ); T_ShaderInput const* getInput( __rd__ std::string const& name ); void dereferencePipeline( __rd__ const uint32_t index ); void dereferenceProgram( __rd__ const uint32_t index , __rd__ const uint32_t pipeline ); void initPipeline( __rw__ T_Pipeline_& pipeline ) const; void initProgram( __rw__ T_Program_& program ); void parseGLSLError( __rw__ T_ShaderCode& code , __rd__ char const* errorLine ); void programUpdated( __rd__ std::string const& name ); void resetProgram( __rw__ T_Program_& program ); };