Ops - Auto-reload + resize support

This commit is contained in:
Emmanuel BENOîT 2017-11-15 23:09:52 +01:00
parent c3171aba94
commit e0e7ab5441
11 changed files with 201 additions and 128 deletions

View file

@ -27,10 +27,12 @@ COMMON = \
shaders.cc \ shaders.cc \
odbg.cc \ odbg.cc \
sync.cc \ sync.cc \
\
ops.cc \ ops.cc \
opast.cc \ opast.cc \
opparser.cc \ opparser.cc \
opcomp.cc \ opcomp.cc \
opmgr.cc \
# END COMMON # END COMMON
DEMO = \ DEMO = \

1
TODO
View file

@ -11,7 +11,6 @@ Scripting:
type errors type errors
* Spill values in the FPU stack runs out * Spill values in the FPU stack runs out
* More checks in the execution engine * More checks in the execution engine
* Reload script on file changes
* Re-execute init if shaders are changed * Re-execute init if shaders are changed
(better yet, only execute the parts that are actually needed) (better yet, only execute the parts that are actually needed)
* Overrides * Overrides

107
demo.cc
View file

@ -3,30 +3,28 @@
#include "sync.hh" #include "sync.hh"
#include "rendertarget.hh" #include "rendertarget.hh"
#include "globals.hh" #include "globals.hh"
#include "ops.hh"
#include "opcomp.hh" #include "opcomp.hh"
#include <ebcl/Files.hh> #include <ebcl/Files.hh>
#include <ebcl/SRDText.hh> #include <ebcl/SRDText.hh>
T_Demo::T_Demo( const uint32_t width , bool T_Demo::initialise(
const uint32_t height ) const uint32_t w ,
: width( width ) , height( height ) const uint32_t h )
{ }
bool T_Demo::initialise( )
{ {
if ( !program ) { width = w;
loadProgram( ); height = h;
} return program && runInit( *program );
return true;
} }
void T_Demo::render( ) void T_Demo::render( )
{ {
if ( program && !context ) { if ( Globals::Ops( ).hasNewProgram( ) ) {
runInit( ); auto nProgram{ Globals::Ops( ).program( ) };
if ( runInit( *nProgram ) ) {
program = std::move( nProgram );
}
} }
auto& sync( Globals::Sync( ) ); auto& sync( Globals::Sync( ) );
@ -99,83 +97,34 @@ void WriteSRDError(
} // namespace } // namespace
bool T_Demo::loadProgram( )
bool T_Demo::runInit(
ops::T_OpProgram& p )
{ {
using namespace ebcl; auto nContext{ NewOwned< ops::T_OpContext >( p ) };
const T_String inputName( T_String::Pooled( "demo.srd" ) );
T_File input( inputName , E_FileMode::READ_ONLY );
try { try {
input.open( ); nContext->run( ops::T_OpContext::R_INIT , 0 , width , height );
} catch ( X_StreamError const& e ) {
PrintStreamError( "Could not open" , inputName , e );
return false;
}
// Load SRD data
T_SRDMemoryTarget srdOut;
srdOut.clearComments( true ).clearFlushToken( true );
try {
T_SRDTextReader srdReader{ srdOut };
T_FileInputStream fis{ input };
srdReader.read( inputName , fis );
} catch ( X_StreamError const& e ) {
PrintStreamError( "Could not open" , inputName , e );
return false;
} catch ( X_SRDErrors const& e ) {
T_StringBuilder sb;
const auto nErrors( e.errors.size( ) );
for ( auto i = 0u ; i < nErrors ; i ++ ) {
WriteSRDError( sb , e.errors[ i ] );
}
sb << "No parsing happened due to format errors\n" << '\0';
fprintf( stderr , "%s" , sb.data( ) );
return false;
}
// Parse the fuck
T_OpsParser parser;
if ( parser.parse( srdOut.list( ) ) ) {
printf( "Parser successful. Compiling...\n" );
T_OpsCompiler compiler;
program = compiler.compile( *parser.result( ) );
return true;
}
T_StringBuilder sb;
sb << "- PARSE ERRORS -------------------------\n";
const auto nErrors( parser.errors( ).size( ) );
for ( auto i = 0u ; i < nErrors ; i ++ ) {
WriteSRDError( sb , parser.errors( )[ i ] );
}
sb << "----------------------------------------\n";
sb << '\0';
fprintf( stderr , "%s" , sb.data( ) );
return false;
}
void T_Demo::runInit( )
{
context = NewOwned< ops::T_OpContext >( *program );
try {
context->run( ops::T_OpContext::R_INIT , 0 , width , height );
} catch ( ops::X_OpFailure const& fail ) { } catch ( ops::X_OpFailure const& fail ) {
printf( "FAILED TO RUN INIT!\n\t%s\n" , fail.what( ) ); printf( "FAILED TO RUN INIT!\n\t%s\n" , fail.what( ) );
context->aborted = true; nContext.clear( );
return;
} }
if ( !nContext ) {
return false;
}
context = std::move( nContext );
Globals::Sync( ).clearInputs( ); Globals::Sync( ).clearInputs( );
const auto n( context->initialInputs.size( ) ); const auto n( context->initialInputs.size( ) );
assert( n == program->inputs.size( ) ); assert( n == p.inputs.size( ) );
for ( auto i = 0u ; i < n ; i ++ ) { for ( auto i = 0u ; i < n ; i ++ ) {
Globals::Sync( ).addInput( program->inputs[ i ] , Globals::Sync( ).addInput( p.inputs[ i ] ,
context->initialInputs[ i ] ); context->initialInputs[ i ] );
#ifdef INVASIVE_TRACES #ifdef INVASIVE_TRACES
printf( "#%d %s pos %d\n" , i , program->inputs[ i ].toOSString( ).data( ) , printf( "#%d %s pos %d\n" , i , p.inputs[ i ].toOSString( ).data( ) ,
Globals::Sync( ).inputPos( program->inputs[ i ] ) ); Globals::Sync( ).inputPos( p.inputs[ i ] ) );
#endif //INVASIVE_TRACES #endif //INVASIVE_TRACES
} }
Globals::Sync( ).updateCurveCaches( ); Globals::Sync( ).updateCurveCaches( );
return true;
} }

22
demo.hh
View file

@ -2,24 +2,22 @@
#include "opcomp.hh" #include "opcomp.hh"
namespace ops { class T_OpContext; }
struct T_Demo struct T_Demo
{ {
T_Demo( ) = delete; T_Demo( ) = default;
NO_COPY( T_Demo ); NO_COPY( T_Demo );
NO_MOVE( T_Demo ); NO_MOVE( T_Demo );
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
T_Demo( const uint32_t width , bool initialise( const uint32_t width ,
const uint32_t height ); const uint32_t height );
bool initialise( );
void render( ); void render( );
bool loadProgram( );
void runInit( );
void handleDND( void handleDND(
ImVec2 const& move , ImVec2 const& move ,
const bool hasCtrl , const bool hasCtrl ,
@ -34,15 +32,17 @@ struct T_Demo
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
const uint32_t width;
const uint32_t height;
bool playing = false; bool playing = false;
private:
uint32_t width;
uint32_t height;
T_OwnPtr< ops::T_OpProgram > program; T_OwnPtr< ops::T_OpProgram > program;
T_OwnPtr< ops::T_OpContext > context; T_OwnPtr< ops::T_OpContext > context;
private:
bool playingPrevious = false; bool playingPrevious = false;
float lastFrame; float lastFrame;
bool runInit( ops::T_OpProgram& program );
}; };

View file

@ -1,12 +1,14 @@
(init (init
# Compute viewport size # Compute viewport size
(if (cmp-gt $width $height) (locals aspect-ratio)
(set aspect-ratio (div 16 9))
(if (cmp-gt (div $width $aspect-ratio) $height)
( (
(set vp-height $height) (set vp-height $height)
(set vp-width (mul $height (div 16 9))) (set vp-width (mul $height $aspect-ratio))
)( )(
(set vp-width $width) (set vp-width $width)
(set vp-height (div $width (div 16 9))) (set vp-height (div $width $aspect-ratio))
) )
) )
# Viewport location # Viewport location
@ -448,7 +450,8 @@
# FIXME temp - we'll need to do init right before this # FIXME temp - we'll need to do init right before this
# can be moved back to initialisation # can be moved back to initialisation
(uniforms-i prg-fxaa 0 0) (uniforms-i prg-fxaa 0 0)
(uniforms prg-fxaa 1 $vp-width $vp-height) (uniforms prg-fxaa 1
$vp-x $vp-y $vp-width $vp-height)
(main-output) (main-output)
(viewport 0 0 $width $height) (viewport 0 0 $width $height)

View file

@ -2,12 +2,14 @@
#include "globals.hh" #include "globals.hh"
#include "filewatcher.hh" #include "filewatcher.hh"
#include "profiling.hh"
#include "texture.hh"
#include "shaders.hh"
#include "window.hh"
#include "odbg.hh" #include "odbg.hh"
#include "opcomp.hh"
#include "ops.hh"
#include "profiling.hh"
#include "shaders.hh"
#include "sync.hh" #include "sync.hh"
#include "texture.hh"
#include "window.hh"
T_OwnPtr< T_FilesWatcher > Globals::watcher_; T_OwnPtr< T_FilesWatcher > Globals::watcher_;
@ -17,6 +19,7 @@ T_OwnPtr< T_SyncManager > Globals::sync_;
T_OwnPtr< T_TextureManager > Globals::textures_; T_OwnPtr< T_TextureManager > Globals::textures_;
T_OwnPtr< T_ShaderManager > Globals::shaders_; T_OwnPtr< T_ShaderManager > Globals::shaders_;
T_OwnPtr< T_OutputDebugger > Globals::odbg_; T_OwnPtr< T_OutputDebugger > Globals::odbg_;
T_OwnPtr< T_ScriptManager > Globals::ops_;
void Globals::Init( ) void Globals::Init( )
@ -28,10 +31,12 @@ void Globals::Init( )
textures_ = NewOwned< T_TextureManager >( ); textures_ = NewOwned< T_TextureManager >( );
shaders_ = NewOwned< T_ShaderManager >( ); shaders_ = NewOwned< T_ShaderManager >( );
odbg_ = NewOwned< T_OutputDebugger >( ); odbg_ = NewOwned< T_OutputDebugger >( );
ops_ = NewOwned< T_ScriptManager >( );
} }
void Globals::Shutdown( ) void Globals::Shutdown( )
{ {
ops_.clear( );
odbg_.clear( ); odbg_.clear( );
shaders_.clear( ); shaders_.clear( );
textures_.clear( ); textures_.clear( );

View file

@ -11,6 +11,7 @@ struct T_TextureManager;
struct T_ShaderManager; struct T_ShaderManager;
struct T_OutputDebugger; struct T_OutputDebugger;
struct T_SyncManager; struct T_SyncManager;
struct T_ScriptManager;
struct Globals struct Globals
@ -25,13 +26,15 @@ struct Globals
static T_TextureManager& Textures( ) { return *textures_; } static T_TextureManager& Textures( ) { return *textures_; }
static T_ShaderManager& Shaders( ) { return *shaders_; } static T_ShaderManager& Shaders( ) { return *shaders_; }
static T_OutputDebugger& ODbg( ) { return *odbg_; } static T_OutputDebugger& ODbg( ) { return *odbg_; }
static T_ScriptManager& Ops( ) { return *ops_; }
private: private:
static ebcl::T_OwnPtr< T_FilesWatcher > watcher_; static T_OwnPtr< T_FilesWatcher > watcher_;
static ebcl::T_OwnPtr< T_Window > window_; static T_OwnPtr< T_Window > window_;
static ebcl::T_OwnPtr< T_Profiler > profiler_; static T_OwnPtr< T_Profiler > profiler_;
static ebcl::T_OwnPtr< T_SyncManager > sync_; static T_OwnPtr< T_SyncManager > sync_;
static ebcl::T_OwnPtr< T_ShaderManager > shaders_; static T_OwnPtr< T_ShaderManager > shaders_;
static ebcl::T_OwnPtr< T_TextureManager > textures_; static T_OwnPtr< T_TextureManager > textures_;
static ebcl::T_OwnPtr< T_OutputDebugger > odbg_; static T_OwnPtr< T_OutputDebugger > odbg_;
static T_OwnPtr< T_ScriptManager > ops_;
}; };

27
main.cc
View file

@ -7,7 +7,9 @@
#include "window.hh" #include "window.hh"
#include "shaders.hh" #include "shaders.hh"
#include "odbg.hh" #include "odbg.hh"
#include "ops.hh"
#include "rendertarget.hh" #include "rendertarget.hh"
#include "sync.hh"
using ebcl::T_Optional; using ebcl::T_Optional;
@ -47,27 +49,30 @@ struct T_Main
T_Main::T_Main( ) T_Main::T_Main( )
{ {
Globals::Init( ); Globals::Init( );
prevSize = ImVec2( 1280 , 720 ); prevSize = ImVec2( -1 , -1 );
} }
void T_Main::mainLoop( ) void T_Main::mainLoop( )
{ {
auto& p( Globals::Profiler( ) ); auto& p( Globals::Profiler( ) );
while ( !done ) { while ( !done ) {
if ( demo ) {
auto const& dspSize( ImGui::GetIO( ).DisplaySize ); auto const& dspSize( ImGui::GetIO( ).DisplaySize );
if ( prevSize.x != dspSize.x || prevSize.y != dspSize.y ) { if ( prevSize.x != dspSize.x || prevSize.y != dspSize.y ) {
stopResize = ResizeDelay; const auto doit( prevSize.x > 0 );
prevSize = dspSize; prevSize = dspSize;
if ( doit ) {
stopResize = ResizeDelay;
} }
} }
bool needInit( !demo );
if ( stopResize > 0 ) { if ( stopResize > 0 ) {
stopResize --; stopResize --;
if ( stopResize == 0 ) { if ( stopResize == 0 ) {
demo.clear( ); needInit = true;
} }
} }
if ( !demo ) { if ( needInit ) {
initDemo( ); initDemo( );
} }
@ -100,18 +105,18 @@ T_Main::~T_Main( )
void T_Main::initDemo( ) void T_Main::initDemo( )
{ {
assert( !demo );
auto const& dspSize( ImGui::GetIO( ).DisplaySize ); auto const& dspSize( ImGui::GetIO( ).DisplaySize );
if ( dspSize.x < 0 || dspSize.y < 0 ) { if ( dspSize.x < 0 || dspSize.y < 0 ) {
return; return;
} }
if ( !demo ) {
demo.setNew( );
}
printf( "init w/ dspsize %dx%d\n" , int( dspSize.x ) , int( dspSize.y ) ); printf( "init w/ dspsize %dx%d\n" , int( dspSize.x ) , int( dspSize.y ) );
demo.setNew( dspSize.x , dspSize.y ); if ( demo->initialise( (uint32_t) dspSize.x , (uint32_t) dspSize.y ) ) {
if ( demo->initialise( ) ) {
Globals::Profiler( ).clear( ); Globals::Profiler( ).clear( );
} else {
demo.clear( );
} }
} }
@ -207,9 +212,7 @@ void T_Main::makeUI( )
void T_Main::render( ) void T_Main::render( )
{ {
if ( demo ) { if ( demo ) {
Globals::Profiler( ).start( "Render" );
demo->render( ); demo->render( );
glFinish( ); Globals::Profiler( ).end( "Render" );
Globals::Profiler( ).start( "Debug" ); Globals::Profiler( ).start( "Debug" );
T_Rendertarget::MainOutput( ); T_Rendertarget::MainOutput( );

View file

@ -1,14 +1,11 @@
#pragma once #pragma once
#ifndef REAL_BUILD #include "filewatcher.hh"
# include "externals.hh" #include "opast.hh"
#endif
#include <ebcl/SRDData.hh> #include <ebcl/SRDData.hh>
/*= PARSER ===================================================================*/ /*= PARSER ===================================================================*/
namespace opast { class T_RootNode; }
// Parser output. Consists in a root node as well as other details (table of // Parser output. Consists in a root node as well as other details (table of
// constants, data types, etc...) // constants, data types, etc...)
struct T_OpsParserOutput struct T_OpsParserOutput
@ -31,6 +28,7 @@ class T_OpsParser : public ebcl::A_PrivateImplementation
T_Array< ebcl::T_SRDError > const& errors( ) const noexcept T_Array< ebcl::T_SRDError > const& errors( ) const noexcept
{ return errors_; } { return errors_; }
T_OwnPtr< T_OpsParserOutput > result( ) noexcept T_OwnPtr< T_OpsParserOutput > result( ) noexcept
{ return std::move( output_ ); } { return std::move( output_ ); }
}; };
@ -48,3 +46,35 @@ class T_OpsCompiler : public ebcl::A_PrivateImplementation
ops::P_OpProgram compile( T_OpsParserOutput const& input ) noexcept; ops::P_OpProgram compile( T_OpsParserOutput const& input ) noexcept;
}; };
/*= SCRIPT MANAGER =============================================================*/
// The script manager watches over the demo's script, attempting to reload it if
// it is changed.
class T_ScriptManager
{
private:
T_WatchedFiles watcher_;
T_OpsParser parser_;
T_OpsCompiler compiler_;
ops::P_OpProgram output_;
T_Array< ebcl::T_SRDError > errors_;
public:
T_ScriptManager( ) noexcept;
bool hasNewProgram( ) const noexcept
{ return bool( output_ ); }
ops::P_OpProgram program( ) noexcept
{ return std::move( output_ ); }
T_Array< ebcl::T_SRDError > const& errors( ) const noexcept
{ return errors_; }
private:
void loadScript( ) noexcept;
};

78
opmgr.cc Normal file
View file

@ -0,0 +1,78 @@
#include "externals.hh"
#include "globals.hh"
#include "opcomp.hh"
#include "ops.hh"
#include <ebcl/Files.hh>
#include <ebcl/SRDIO.hh>
#include <ebcl/SRDText.hh>
/*= T_ScriptManager ============================================================*/
T_ScriptManager::T_ScriptManager( ) noexcept
: watcher_( Globals::Watcher( ) , [this](){
loadScript( );
} ) ,
parser_( ) , compiler_( )
{
watcher_.watch( T_String::Pooled( "demo.srd" ) );
loadScript( );
}
void T_ScriptManager::loadScript( ) noexcept
{
output_.clear( );
errors_.clear( );
using namespace ebcl;
const T_String inputName( T_String::Pooled( "demo.srd" ) );
T_File input( inputName , E_FileMode::READ_ONLY );
try {
input.open( );
} catch ( X_StreamError const& e ) {
T_StringBuilder sb;
sb << "could not open: " << e.what( );
if ( e.code( ) == ebcl::E_StreamError::SYSTEM_ERROR ) {
sb << " (error code " << e.systemError( ) << ")";
}
errors_.addNew( std::move( sb ) ,
T_SRDLocation{ inputName , 1 , 1 } );
return;
}
// Load SRD data
T_SRDMemoryTarget srdOut;
srdOut.clearComments( true ).clearFlushToken( true );
try {
T_SRDTextReader srdReader{ srdOut };
T_FileInputStream fis{ input };
srdReader.read( inputName , fis );
} catch ( X_StreamError const& e ) {
T_StringBuilder sb;
sb << "could not load: " << e.what( );
if ( e.code( ) == ebcl::E_StreamError::SYSTEM_ERROR ) {
sb << " (error code " << e.systemError( ) << ")";
}
errors_.addNew( std::move( sb ) ,
T_SRDLocation{ inputName , 1 , 1 } );
return;
} catch ( X_SRDErrors const& e ) {
T_StringBuilder sb;
const auto nErrors( e.errors.size( ) );
errors_.ensureCapacity( nErrors );
for ( auto i = 0u ; i < nErrors ; i ++ ) {
errors_.add( e.errors[ i ] );
}
return;
}
// Parse the fuck
if ( !parser_.parse( srdOut.list( ) ) ) {
errors_.addAll( parser_.errors( ) );
return;
}
output_ = compiler_.compile( *parser_.result( ) );
// FIXME - errors from compiler
}

View file

@ -11,7 +11,7 @@
//! include chunks/fxaa-3.11.glsl //! include chunks/fxaa-3.11.glsl
layout( location = 0 ) uniform sampler2D u_Input; layout( location = 0 ) uniform sampler2D u_Input;
layout( location = 1 ) uniform vec2 u_Resolution; layout( location = 1 ) uniform vec4 u_Viewport;
layout( location = 2 ) uniform vec3 u_Parameters; layout( location = 2 ) uniform vec3 u_Parameters;
#define uSPQuality (u_Parameters.x) #define uSPQuality (u_Parameters.x)
@ -22,13 +22,14 @@ layout( location = 0 ) out vec4 o_Color;
void main( void ) void main( void )
{ {
vec2 coords = gl_FragCoord.xy - u_Viewport.xy;
o_Color = FxaaPixelShader( o_Color = FxaaPixelShader(
( gl_FragCoord.xy / u_Resolution ) , // pos (vec2) ( coords / u_Viewport.zw ) , // pos (vec2)
vec4( 0 ) , // unused (vec4) vec4( 0 ) , // unused (vec4)
u_Input , // input texture u_Input , // input texture
u_Input , // (unused) input texture u_Input , // (unused) input texture
u_Input , // (unused) input texture u_Input , // (unused) input texture
vec2( 1 ) / u_Resolution , // 1/resolution (vec2) vec2( 1 ) / u_Viewport.zw , // 1/resolution (vec2)
vec4( 0 ) , // unused (vec4) vec4( 0 ) , // unused (vec4)
vec4( 0 ) , // unused (vec4) vec4( 0 ) , // unused (vec4)
vec4( 0 ) , // unused (vec4) vec4( 0 ) , // unused (vec4)