From e0e7ab54419b732f3a7404e338ab297ff0013557 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emmanuel=20Beno=C3=AEt?= Date: Wed, 15 Nov 2017 23:09:52 +0100 Subject: [PATCH] Ops - Auto-reload + resize support --- Makefile | 2 + TODO | 1 - demo.cc | 107 ++++++++++++-------------------------------- demo.hh | 22 ++++----- demo.srd | 11 +++-- globals.cc | 13 ++++-- globals.hh | 17 ++++--- main.cc | 31 +++++++------ opcomp.hh | 40 ++++++++++++++--- opmgr.cc | 78 ++++++++++++++++++++++++++++++++ shaders/fxaa.f.glsl | 7 +-- 11 files changed, 201 insertions(+), 128 deletions(-) create mode 100644 opmgr.cc diff --git a/Makefile b/Makefile index 7271aa1..657dac4 100644 --- a/Makefile +++ b/Makefile @@ -27,10 +27,12 @@ COMMON = \ shaders.cc \ odbg.cc \ sync.cc \ + \ ops.cc \ opast.cc \ opparser.cc \ opcomp.cc \ + opmgr.cc \ # END COMMON DEMO = \ diff --git a/TODO b/TODO index 104c5df..85013e0 100644 --- a/TODO +++ b/TODO @@ -11,7 +11,6 @@ Scripting: type errors * Spill values in the FPU stack runs out * More checks in the execution engine -* Reload script on file changes * Re-execute init if shaders are changed (better yet, only execute the parts that are actually needed) * Overrides diff --git a/demo.cc b/demo.cc index af73df5..cb6dc82 100644 --- a/demo.cc +++ b/demo.cc @@ -3,30 +3,28 @@ #include "sync.hh" #include "rendertarget.hh" #include "globals.hh" +#include "ops.hh" #include "opcomp.hh" #include #include -T_Demo::T_Demo( const uint32_t width , - const uint32_t height ) - : width( width ) , height( height ) -{ } - - -bool T_Demo::initialise( ) +bool T_Demo::initialise( + const uint32_t w , + const uint32_t h ) { - if ( !program ) { - loadProgram( ); - } - - return true; + width = w; + height = h; + return program && runInit( *program ); } void T_Demo::render( ) { - if ( program && !context ) { - runInit( ); + if ( Globals::Ops( ).hasNewProgram( ) ) { + auto nProgram{ Globals::Ops( ).program( ) }; + if ( runInit( *nProgram ) ) { + program = std::move( nProgram ); + } } auto& sync( Globals::Sync( ) ); @@ -99,83 +97,34 @@ void WriteSRDError( } // namespace -bool T_Demo::loadProgram( ) + +bool T_Demo::runInit( + ops::T_OpProgram& p ) { - using namespace ebcl; - const T_String inputName( T_String::Pooled( "demo.srd" ) ); - T_File input( inputName , E_FileMode::READ_ONLY ); + auto nContext{ NewOwned< ops::T_OpContext >( p ) }; try { - input.open( ); - } 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 ); + nContext->run( ops::T_OpContext::R_INIT , 0 , width , height ); } catch ( ops::X_OpFailure const& fail ) { printf( "FAILED TO RUN INIT!\n\t%s\n" , fail.what( ) ); - context->aborted = true; - return; + nContext.clear( ); } + if ( !nContext ) { + return false; + } + context = std::move( nContext ); Globals::Sync( ).clearInputs( ); const auto n( context->initialInputs.size( ) ); - assert( n == program->inputs.size( ) ); + assert( n == p.inputs.size( ) ); for ( auto i = 0u ; i < n ; i ++ ) { - Globals::Sync( ).addInput( program->inputs[ i ] , + Globals::Sync( ).addInput( p.inputs[ i ] , context->initialInputs[ i ] ); #ifdef INVASIVE_TRACES - printf( "#%d %s pos %d\n" , i , program->inputs[ i ].toOSString( ).data( ) , - Globals::Sync( ).inputPos( program->inputs[ i ] ) ); + printf( "#%d %s pos %d\n" , i , p.inputs[ i ].toOSString( ).data( ) , + Globals::Sync( ).inputPos( p.inputs[ i ] ) ); #endif //INVASIVE_TRACES } Globals::Sync( ).updateCurveCaches( ); + + return true; } diff --git a/demo.hh b/demo.hh index b0e2e20..f7292b7 100644 --- a/demo.hh +++ b/demo.hh @@ -2,24 +2,22 @@ #include "opcomp.hh" +namespace ops { class T_OpContext; } + struct T_Demo { - T_Demo( ) = delete; + T_Demo( ) = default; + NO_COPY( T_Demo ); NO_MOVE( T_Demo ); // --------------------------------------------------------------------- - T_Demo( const uint32_t width , + bool initialise( const uint32_t width , const uint32_t height ); - - bool initialise( ); void render( ); - bool loadProgram( ); - void runInit( ); - void handleDND( ImVec2 const& move , const bool hasCtrl , @@ -34,15 +32,17 @@ struct T_Demo // --------------------------------------------------------------------- - const uint32_t width; - const uint32_t height; - bool playing = false; + private: + uint32_t width; + uint32_t height; + T_OwnPtr< ops::T_OpProgram > program; T_OwnPtr< ops::T_OpContext > context; - private: bool playingPrevious = false; float lastFrame; + + bool runInit( ops::T_OpProgram& program ); }; diff --git a/demo.srd b/demo.srd index ee5d3b5..fc1fac0 100644 --- a/demo.srd +++ b/demo.srd @@ -1,12 +1,14 @@ (init # 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-width (mul $height (div 16 9))) + (set vp-width (mul $height $aspect-ratio)) )( (set vp-width $width) - (set vp-height (div $width (div 16 9))) + (set vp-height (div $width $aspect-ratio)) ) ) # Viewport location @@ -448,7 +450,8 @@ # FIXME temp - we'll need to do init right before this # can be moved back to initialisation (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) (viewport 0 0 $width $height) diff --git a/globals.cc b/globals.cc index 91fe252..07a95c4 100644 --- a/globals.cc +++ b/globals.cc @@ -2,12 +2,14 @@ #include "globals.hh" #include "filewatcher.hh" -#include "profiling.hh" -#include "texture.hh" -#include "shaders.hh" -#include "window.hh" #include "odbg.hh" +#include "opcomp.hh" +#include "ops.hh" +#include "profiling.hh" +#include "shaders.hh" #include "sync.hh" +#include "texture.hh" +#include "window.hh" 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_ShaderManager > Globals::shaders_; T_OwnPtr< T_OutputDebugger > Globals::odbg_; +T_OwnPtr< T_ScriptManager > Globals::ops_; void Globals::Init( ) @@ -28,10 +31,12 @@ void Globals::Init( ) textures_ = NewOwned< T_TextureManager >( ); shaders_ = NewOwned< T_ShaderManager >( ); odbg_ = NewOwned< T_OutputDebugger >( ); + ops_ = NewOwned< T_ScriptManager >( ); } void Globals::Shutdown( ) { + ops_.clear( ); odbg_.clear( ); shaders_.clear( ); textures_.clear( ); diff --git a/globals.hh b/globals.hh index 47cfee6..f98bd0f 100644 --- a/globals.hh +++ b/globals.hh @@ -11,6 +11,7 @@ struct T_TextureManager; struct T_ShaderManager; struct T_OutputDebugger; struct T_SyncManager; +struct T_ScriptManager; struct Globals @@ -25,13 +26,15 @@ struct Globals static T_TextureManager& Textures( ) { return *textures_; } static T_ShaderManager& Shaders( ) { return *shaders_; } static T_OutputDebugger& ODbg( ) { return *odbg_; } + static T_ScriptManager& Ops( ) { return *ops_; } private: - static ebcl::T_OwnPtr< T_FilesWatcher > watcher_; - static ebcl::T_OwnPtr< T_Window > window_; - static ebcl::T_OwnPtr< T_Profiler > profiler_; - static ebcl::T_OwnPtr< T_SyncManager > sync_; - static ebcl::T_OwnPtr< T_ShaderManager > shaders_; - static ebcl::T_OwnPtr< T_TextureManager > textures_; - static ebcl::T_OwnPtr< T_OutputDebugger > odbg_; + static T_OwnPtr< T_FilesWatcher > watcher_; + static T_OwnPtr< T_Window > window_; + static T_OwnPtr< T_Profiler > profiler_; + static T_OwnPtr< T_SyncManager > sync_; + static T_OwnPtr< T_ShaderManager > shaders_; + static T_OwnPtr< T_TextureManager > textures_; + static T_OwnPtr< T_OutputDebugger > odbg_; + static T_OwnPtr< T_ScriptManager > ops_; }; diff --git a/main.cc b/main.cc index a501939..f199989 100644 --- a/main.cc +++ b/main.cc @@ -7,7 +7,9 @@ #include "window.hh" #include "shaders.hh" #include "odbg.hh" +#include "ops.hh" #include "rendertarget.hh" +#include "sync.hh" using ebcl::T_Optional; @@ -47,27 +49,30 @@ struct T_Main T_Main::T_Main( ) { Globals::Init( ); - prevSize = ImVec2( 1280 , 720 ); + prevSize = ImVec2( -1 , -1 ); } void T_Main::mainLoop( ) { auto& p( Globals::Profiler( ) ); while ( !done ) { - if ( demo ) { - auto const& dspSize( ImGui::GetIO( ).DisplaySize ); - if ( prevSize.x != dspSize.x || prevSize.y != dspSize.y ) { + auto const& dspSize( ImGui::GetIO( ).DisplaySize ); + if ( prevSize.x != dspSize.x || prevSize.y != dspSize.y ) { + const auto doit( prevSize.x > 0 ); + prevSize = dspSize; + if ( doit ) { stopResize = ResizeDelay; - prevSize = dspSize; } } + + bool needInit( !demo ); if ( stopResize > 0 ) { stopResize --; if ( stopResize == 0 ) { - demo.clear( ); + needInit = true; } } - if ( !demo ) { + if ( needInit ) { initDemo( ); } @@ -100,18 +105,18 @@ T_Main::~T_Main( ) void T_Main::initDemo( ) { - assert( !demo ); auto const& dspSize( ImGui::GetIO( ).DisplaySize ); if ( dspSize.x < 0 || dspSize.y < 0 ) { return; } + if ( !demo ) { + demo.setNew( ); + } + printf( "init w/ dspsize %dx%d\n" , int( dspSize.x ) , int( dspSize.y ) ); - demo.setNew( dspSize.x , dspSize.y ); - if ( demo->initialise( ) ) { + if ( demo->initialise( (uint32_t) dspSize.x , (uint32_t) dspSize.y ) ) { Globals::Profiler( ).clear( ); - } else { - demo.clear( ); } } @@ -207,9 +212,7 @@ void T_Main::makeUI( ) void T_Main::render( ) { if ( demo ) { - Globals::Profiler( ).start( "Render" ); demo->render( ); - glFinish( ); Globals::Profiler( ).end( "Render" ); Globals::Profiler( ).start( "Debug" ); T_Rendertarget::MainOutput( ); diff --git a/opcomp.hh b/opcomp.hh index 3a92270..c9af282 100644 --- a/opcomp.hh +++ b/opcomp.hh @@ -1,14 +1,11 @@ #pragma once -#ifndef REAL_BUILD -# include "externals.hh" -#endif +#include "filewatcher.hh" +#include "opast.hh" #include /*= PARSER ===================================================================*/ -namespace opast { class T_RootNode; } - // Parser output. Consists in a root node as well as other details (table of // constants, data types, etc...) struct T_OpsParserOutput @@ -31,6 +28,7 @@ class T_OpsParser : public ebcl::A_PrivateImplementation T_Array< ebcl::T_SRDError > const& errors( ) const noexcept { return errors_; } + T_OwnPtr< T_OpsParserOutput > result( ) noexcept { return std::move( output_ ); } }; @@ -48,3 +46,35 @@ class T_OpsCompiler : public ebcl::A_PrivateImplementation 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; +}; diff --git a/opmgr.cc b/opmgr.cc new file mode 100644 index 0000000..9f3fab6 --- /dev/null +++ b/opmgr.cc @@ -0,0 +1,78 @@ +#include "externals.hh" +#include "globals.hh" +#include "opcomp.hh" +#include "ops.hh" + +#include +#include +#include + + +/*= 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 +} diff --git a/shaders/fxaa.f.glsl b/shaders/fxaa.f.glsl index 79190b8..e3eb9bb 100644 --- a/shaders/fxaa.f.glsl +++ b/shaders/fxaa.f.glsl @@ -11,7 +11,7 @@ //! include chunks/fxaa-3.11.glsl 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; #define uSPQuality (u_Parameters.x) @@ -22,13 +22,14 @@ layout( location = 0 ) out vec4 o_Color; void main( void ) { + vec2 coords = gl_FragCoord.xy - u_Viewport.xy; o_Color = FxaaPixelShader( - ( gl_FragCoord.xy / u_Resolution ) , // pos (vec2) + ( coords / u_Viewport.zw ) , // pos (vec2) vec4( 0 ) , // unused (vec4) u_Input , // 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)