2017-10-03 13:53:50 +02:00
|
|
|
#pragma once
|
2017-11-23 23:05:14 +01:00
|
|
|
#include "c-filewatcher.hh"
|
2017-10-03 13:53:50 +02:00
|
|
|
|
|
|
|
|
|
|
|
/*= INPUT FILES ==============================================================*/
|
|
|
|
|
|
|
|
// Type of input chunk
|
|
|
|
enum class E_ShaderInputChunk {
|
|
|
|
CODE ,
|
2017-10-08 10:13:11 +02:00
|
|
|
INCLUDE ,
|
2017-10-03 13:53:50 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
// Input chunk data
|
|
|
|
struct T_ShaderInputChunk
|
|
|
|
{
|
|
|
|
E_ShaderInputChunk type;
|
2017-11-05 10:02:30 +01:00
|
|
|
T_String text;
|
2017-10-03 13:53:50 +02:00
|
|
|
uint32_t lines;
|
|
|
|
|
|
|
|
T_ShaderInputChunk( ) = default;
|
|
|
|
T_ShaderInputChunk(
|
2017-11-04 12:00:58 +01:00
|
|
|
const E_ShaderInputChunk type ,
|
2017-11-05 10:02:30 +01:00
|
|
|
T_String text ,
|
2017-11-04 12:00:58 +01:00
|
|
|
const uint32_t lines )
|
2017-10-03 13:53:50 +02:00
|
|
|
: 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
|
2017-10-04 11:20:27 +02:00
|
|
|
VERTEX , FRAGMENT , GEOMETRY ,
|
|
|
|
COMPUTE
|
2017-10-03 13:53:50 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
// Preprocessing errors
|
|
|
|
struct T_ShaderInputError
|
|
|
|
{
|
|
|
|
uint32_t line;
|
2017-11-05 10:02:30 +01:00
|
|
|
T_String error;
|
|
|
|
|
|
|
|
T_ShaderInputError(
|
|
|
|
const uint32_t line ,
|
|
|
|
T_String error )
|
|
|
|
: line( line ) , error( std::move( error ) )
|
|
|
|
{ }
|
2017-10-03 13:53:50 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
// Source file
|
|
|
|
struct T_ShaderInput
|
|
|
|
{
|
|
|
|
E_ShaderInput type = E_ShaderInput::CHUNK;
|
2017-11-05 10:02:30 +01:00
|
|
|
T_Array< T_ShaderInputChunk > chunks;
|
|
|
|
T_Array< T_ShaderInputError > errors;
|
2017-10-03 13:53:50 +02:00
|
|
|
|
2017-11-05 11:08:00 +01:00
|
|
|
bool load( T_String const& path );
|
2017-10-03 13:53:50 +02:00
|
|
|
};
|
2017-11-05 11:08:00 +01:00
|
|
|
using P_ShaderInput = T_OwnPtr< T_ShaderInput >;
|
2017-10-03 13:53:50 +02:00
|
|
|
|
|
|
|
|
2017-10-03 16:09:12 +02:00
|
|
|
// Type of shader
|
|
|
|
enum class E_ShaderType {
|
2017-10-04 16:29:39 +02:00
|
|
|
VERTEX , FRAGMENT , GEOMETRY ,
|
|
|
|
COMPUTE ,
|
2017-10-04 11:20:27 +02:00
|
|
|
__COUNT__
|
2017-10-03 16:09:12 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Errors in shader code - the errors it represents may come from either
|
|
|
|
// the input loader, the shader loader or the driver.
|
|
|
|
struct T_ShaderError
|
|
|
|
{
|
2017-11-05 10:02:30 +01:00
|
|
|
T_String source;
|
2017-10-03 16:09:12 +02:00
|
|
|
uint32_t line;
|
2017-11-05 10:02:30 +01:00
|
|
|
T_String error;
|
|
|
|
|
|
|
|
T_ShaderError( ) = default;
|
|
|
|
|
|
|
|
T_ShaderError( T_String source ,
|
|
|
|
const uint32_t line ,
|
|
|
|
T_String error )
|
|
|
|
: source( std::move( source ) ) , line( line ) ,
|
|
|
|
error( std::move( error ) )
|
|
|
|
{ }
|
|
|
|
|
|
|
|
T_ShaderError( T_String source ,
|
|
|
|
const uint32_t line ,
|
|
|
|
T_StringBuilder& error )
|
|
|
|
: source( std::move( source ) ) , line( line ) ,
|
|
|
|
error( std::move( error ) )
|
|
|
|
{ }
|
2017-10-03 16:09:12 +02:00
|
|
|
};
|
|
|
|
|
2017-10-04 11:20:27 +02:00
|
|
|
|
2017-10-04 16:29:39 +02:00
|
|
|
struct T_ShaderManager;
|
2017-10-04 11:20:27 +02:00
|
|
|
|
2017-11-14 15:27:25 +01:00
|
|
|
struct T_ShaderProgram
|
|
|
|
{
|
|
|
|
friend struct T_ShaderManager;
|
|
|
|
|
|
|
|
T_ShaderProgram( );
|
|
|
|
COPY( T_ShaderProgram );
|
|
|
|
MOVE( T_ShaderProgram );
|
|
|
|
~T_ShaderProgram( );
|
|
|
|
|
|
|
|
bool valid( ) const noexcept;
|
|
|
|
void enable( ) const;
|
|
|
|
GLuint id( ) const;
|
|
|
|
T_Optional< E_ShaderType > type( ) const;
|
|
|
|
T_String name( ) const;
|
|
|
|
|
|
|
|
private:
|
|
|
|
explicit T_ShaderProgram( uint32_t id ) noexcept;
|
|
|
|
uint32_t id_;
|
|
|
|
};
|
|
|
|
|
2017-10-04 16:29:39 +02:00
|
|
|
struct T_ShaderPipeline
|
2017-10-03 16:09:12 +02:00
|
|
|
{
|
2017-10-04 16:29:39 +02:00
|
|
|
friend struct T_ShaderManager;
|
2017-10-04 11:20:27 +02:00
|
|
|
|
2017-10-04 16:29:39 +02:00
|
|
|
T_ShaderPipeline( );
|
|
|
|
COPY( T_ShaderPipeline );
|
|
|
|
MOVE( T_ShaderPipeline );
|
|
|
|
~T_ShaderPipeline( );
|
2017-10-04 11:20:27 +02:00
|
|
|
|
|
|
|
bool valid( ) const noexcept;
|
|
|
|
void enable( ) const;
|
2017-10-15 09:34:03 +02:00
|
|
|
GLuint id( ) const;
|
2017-10-04 11:20:27 +02:00
|
|
|
|
2017-11-04 12:00:58 +01:00
|
|
|
GLuint program( const E_ShaderType program ) const;
|
2017-10-04 17:29:48 +02:00
|
|
|
|
2017-10-04 11:20:27 +02:00
|
|
|
private:
|
2017-11-05 10:02:30 +01:00
|
|
|
explicit T_ShaderPipeline( T_String id ) noexcept;
|
|
|
|
T_String id_;
|
2017-10-04 11:20:27 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct T_ShaderManager
|
|
|
|
{
|
|
|
|
friend struct T_ShaderPipeline;
|
2017-11-14 15:27:25 +01:00
|
|
|
friend struct T_ShaderProgram;
|
2017-10-04 11:20:27 +02:00
|
|
|
|
2017-10-04 16:29:39 +02:00
|
|
|
struct T_ShaderCode
|
|
|
|
{
|
|
|
|
E_ShaderType type;
|
2017-11-05 10:02:30 +01:00
|
|
|
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_StringBuilder code;
|
|
|
|
T_Array< T_ShaderError > errors;
|
|
|
|
T_KeyValueTable< T_String , bool > files;
|
2017-10-04 16:29:39 +02:00
|
|
|
};
|
|
|
|
|
2017-11-05 10:02:30 +01:00
|
|
|
T_ShaderManager( ) noexcept;
|
|
|
|
|
2017-11-14 15:27:25 +01:00
|
|
|
T_ShaderProgram program( T_String const& name );
|
2017-10-04 11:20:27 +02:00
|
|
|
T_ShaderPipeline pipeline(
|
2017-11-05 10:02:30 +01:00
|
|
|
std::initializer_list< T_String > shaders );
|
2017-11-14 17:35:13 +01:00
|
|
|
T_ShaderPipeline pipeline(
|
|
|
|
T_String const* shaderNames ,
|
|
|
|
uint32_t count );
|
2017-10-04 11:20:27 +02:00
|
|
|
|
2017-10-04 16:29:39 +02:00
|
|
|
void update( );
|
|
|
|
|
2017-10-06 18:42:51 +02:00
|
|
|
void makeUI( );
|
|
|
|
bool& uiEnabled( )
|
|
|
|
{ return uiEnabled_; }
|
|
|
|
|
2017-10-04 11:20:27 +02:00
|
|
|
private:
|
|
|
|
struct T_Pipeline_
|
|
|
|
{
|
2017-11-05 10:02:30 +01:00
|
|
|
T_String idString;
|
|
|
|
uint32_t references = 0;
|
|
|
|
GLuint id = 0;
|
2017-11-14 17:35:13 +01:00
|
|
|
T_Array< T_String > programs{ 6 };
|
2017-11-05 10:02:30 +01:00
|
|
|
|
|
|
|
T_Pipeline_( T_String const& id ,
|
|
|
|
std::initializer_list< T_String > shaders )
|
|
|
|
: idString{ id } , programs{ shaders }
|
|
|
|
{}
|
2017-11-14 17:35:13 +01:00
|
|
|
|
|
|
|
T_Pipeline_( T_String const& id ,
|
|
|
|
T_String const* const shaderNames ,
|
|
|
|
const uint32_t count ) noexcept
|
|
|
|
: idString{ id }
|
|
|
|
{
|
|
|
|
for ( auto i = 0u ; i < count ; i ++ ) {
|
|
|
|
programs.add( shaderNames[ i ] );
|
|
|
|
}
|
|
|
|
}
|
2017-10-04 11:20:27 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
struct T_Program_
|
|
|
|
{
|
2017-11-05 13:47:26 +01:00
|
|
|
T_String name;
|
2017-11-14 15:27:25 +01:00
|
|
|
T_Array< T_String > plReferences;
|
|
|
|
uint32_t saReferences{ 0 };
|
2017-10-04 16:29:39 +02:00
|
|
|
T_ShaderCode code;
|
2017-10-04 11:20:27 +02:00
|
|
|
GLuint id;
|
2017-11-05 10:02:30 +01:00
|
|
|
T_Optional< T_WatchedFiles > watch;
|
2017-10-04 11:20:27 +02:00
|
|
|
};
|
|
|
|
|
2017-10-06 18:42:51 +02:00
|
|
|
bool uiEnabled_ = false;
|
|
|
|
|
2017-11-05 10:02:30 +01:00
|
|
|
T_ObjectTable< T_String , T_Pipeline_ > pipelines_;
|
2017-10-04 11:20:27 +02:00
|
|
|
|
2017-11-05 10:02:30 +01:00
|
|
|
T_Array< T_Program_ > programs_;
|
|
|
|
T_KeyValueTable< T_String , uint32_t > programIndex_;
|
2017-10-03 16:09:12 +02:00
|
|
|
|
2017-11-05 11:08:00 +01:00
|
|
|
T_KeyValueTable< T_String , P_ShaderInput > inputs_;
|
2017-10-04 16:29:39 +02:00
|
|
|
|
2017-11-05 13:47:26 +01:00
|
|
|
T_KeyValueTable< T_String , T_Array< T_String > > missing_;
|
|
|
|
T_Array< T_String > updates_;
|
2017-10-04 16:29:39 +02:00
|
|
|
|
2017-11-14 15:27:25 +01:00
|
|
|
// Load/use existing program for use with pipelines
|
2017-10-04 16:29:39 +02:00
|
|
|
void loadProgram(
|
2017-11-05 10:02:30 +01:00
|
|
|
T_String const& pipeline ,
|
2017-11-05 13:47:26 +01:00
|
|
|
T_String const& name );
|
2017-10-04 16:29:39 +02:00
|
|
|
bool useExistingProgram(
|
2017-11-05 10:02:30 +01:00
|
|
|
T_String const& pipeline ,
|
2017-11-05 13:47:26 +01:00
|
|
|
T_String const& name );
|
2017-10-04 16:29:39 +02:00
|
|
|
|
2017-11-14 15:27:25 +01:00
|
|
|
// Load/use existing program for standalone use
|
|
|
|
void loadProgram( T_String const& name );
|
|
|
|
bool useExistingProgram( T_String const& name );
|
|
|
|
|
|
|
|
// Program management
|
|
|
|
T_Program_& initProgramRecord( // Init management data
|
|
|
|
T_String const& record );
|
|
|
|
uint32_t newProgramRecord( ); // Allocate entry in index
|
|
|
|
|
2017-10-04 16:29:39 +02:00
|
|
|
T_ShaderInput const* getInput(
|
2017-11-05 10:02:30 +01:00
|
|
|
T_String const& name );
|
2017-10-03 16:09:12 +02:00
|
|
|
|
2017-11-05 11:08:00 +01:00
|
|
|
void dereferencePipeline( T_String const& id );
|
2017-10-04 16:29:39 +02:00
|
|
|
void dereferenceProgram(
|
2017-11-04 12:00:58 +01:00
|
|
|
const uint32_t index ,
|
2017-11-05 10:02:30 +01:00
|
|
|
T_String const& pipeline );
|
2017-11-14 15:27:25 +01:00
|
|
|
void dereferenceProgram(
|
|
|
|
const uint32_t index );
|
2017-10-04 16:29:39 +02:00
|
|
|
|
2017-11-05 11:08:00 +01:00
|
|
|
void initPipeline( T_Pipeline_& pipeline ) const;
|
|
|
|
void initProgram( T_Program_& program );
|
2017-10-04 16:29:39 +02:00
|
|
|
|
|
|
|
void parseGLSLError(
|
2017-11-04 12:00:58 +01:00
|
|
|
T_ShaderCode& code ,
|
|
|
|
char const* errorLine );
|
2017-10-04 16:29:39 +02:00
|
|
|
|
2017-11-05 13:47:26 +01:00
|
|
|
void programUpdated( T_String const& name );
|
2017-11-05 11:08:00 +01:00
|
|
|
void resetProgram( T_Program_& program );
|
2017-10-04 16:29:39 +02:00
|
|
|
};
|