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:
parent
3344f96af0
commit
68d01ca42e
41 changed files with 198 additions and 132 deletions
2
TODO
2
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:
|
||||
|
|
11
c-opast.hh
11
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_; }
|
||||
|
|
11
c-opcomp.cc
11
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 <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( ) );
|
||||
}
|
||||
|
|
|
@ -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( );
|
||||
}
|
||||
|
||||
|
|
2
c-ops.hh
2
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;
|
||||
|
|
|
@ -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( );
|
||||
}
|
||||
|
||||
|
|
39
c-shaders.cc
39
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;
|
||||
|
|
24
c-shaders.hh
24
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 >;
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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;
|
|
@ -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;
|
|
@ -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 )
|
|
@ -1,5 +1,5 @@
|
|||
//!type library
|
||||
//!include lib/utils.glsl
|
||||
//!include /lib/utils.glsl
|
||||
|
||||
float DOF_CoC(
|
||||
in float z )
|
|
@ -7,7 +7,7 @@ layout(
|
|||
local_size_y = 64
|
||||
) in;
|
||||
|
||||
//! include chunks/dof-cs.glsl
|
||||
//! include dof-cs.glsl
|
||||
|
||||
void main()
|
||||
{
|
|
@ -1,7 +1,7 @@
|
|||
#version 450 core
|
||||
|
||||
//! type fragment
|
||||
//! include chunks/dof.glsl
|
||||
//! include dof.glsl
|
||||
|
||||
void main()
|
||||
{
|
|
@ -7,7 +7,7 @@ layout(
|
|||
local_size_y = 20
|
||||
) in;
|
||||
|
||||
//! include chunks/dof-cs.glsl
|
||||
//! include dof-cs.glsl
|
||||
|
||||
void main()
|
||||
{
|
|
@ -1,7 +1,7 @@
|
|||
#version 450 core
|
||||
|
||||
//! type fragment
|
||||
//! include chunks/dof.glsl
|
||||
//! include dof.glsl
|
||||
|
||||
void main()
|
||||
{
|
|
@ -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
|
|
@ -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;
|
|
@ -126,7 +126,7 @@
|
|||
|
||||
|
||||
//! type library
|
||||
//! include lib/utils.glsl
|
||||
//! include utils.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
|
|
@ -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
|
|
@ -1,5 +1,5 @@
|
|||
//! type library
|
||||
//! include lib/utils.glsl
|
||||
//! include utils.glsl
|
||||
|
||||
vec2 RM_Map( in vec3 pos );
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
//! type library
|
||||
//! include lib/utils.glsl
|
||||
//! include utils.glsl
|
||||
|
||||
|
||||
struct T_PBRMaterial
|
|
@ -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] = {
|
|
@ -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] = {
|
|
@ -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 >(
|
||||
|
|
122
ui-shaders.cc
122
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( );
|
||||
|
|
|
@ -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 );
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue