Shaders - Relative paths

Shaders are no longer found under /shaders in the project; they can be
anywhere. In addition, paths for both (program) instructions in the
script and include directives in shader source code are relative to the
file which contains them.
This commit is contained in:
Emmanuel BENOîT 2017-12-29 11:33:15 +01:00
parent 3344f96af0
commit 68d01ca42e
41 changed files with 198 additions and 132 deletions

2
TODO
View file

@ -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:

View file

@ -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_; }

View file

@ -1,6 +1,10 @@
#include "externals.hh"
#include "common.hh"
#include "c-project.hh"
#include "c-ops.hh"
#include "c-opcomp.hh"
#include <ebcl/Algorithms.hh>
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( ) );
}

View file

@ -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( );
}

View file

@ -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;

View file

@ -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( );
}

View file

@ -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;

View file

@ -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 >;

View file

@ -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)

View file

@ -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;

View file

@ -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;

View file

@ -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 )

View file

@ -1,5 +1,5 @@
//!type library
//!include lib/utils.glsl
//!include /lib/utils.glsl
float DOF_CoC(
in float z )

View file

@ -7,7 +7,7 @@ layout(
local_size_y = 64
) in;
//! include chunks/dof-cs.glsl
//! include dof-cs.glsl
void main()
{

View file

@ -1,7 +1,7 @@
#version 450 core
//! type fragment
//! include chunks/dof.glsl
//! include dof.glsl
void main()
{

View file

@ -7,7 +7,7 @@ layout(
local_size_y = 20
) in;
//! include chunks/dof-cs.glsl
//! include dof-cs.glsl
void main()
{

View file

@ -1,7 +1,7 @@
#version 450 core
//! type fragment
//! include chunks/dof.glsl
//! include dof.glsl
void main()
{

View file

@ -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

View file

@ -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;

View file

@ -126,7 +126,7 @@
//! type library
//! include lib/utils.glsl
//! include utils.glsl

View file

@ -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

View file

@ -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

View file

@ -1,5 +1,5 @@
//! type library
//! include lib/utils.glsl
//! include utils.glsl
vec2 RM_Map( in vec3 pos );

View file

@ -1,5 +1,5 @@
//! type library
//! include lib/utils.glsl
//! include utils.glsl
struct T_PBRMaterial

View file

@ -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] = {

View file

@ -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] = {

View file

@ -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 >(

View file

@ -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( );

View file

@ -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 );
};