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 \
odbg.cc \
sync.cc \
\
ops.cc \
opast.cc \
opparser.cc \
opcomp.cc \
opmgr.cc \
# END COMMON
DEMO = \

1
TODO
View file

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

107
demo.cc
View file

@ -3,30 +3,28 @@
#include "sync.hh"
#include "rendertarget.hh"
#include "globals.hh"
#include "ops.hh"
#include "opcomp.hh"
#include <ebcl/Files.hh>
#include <ebcl/SRDText.hh>
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;
}

22
demo.hh
View file

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

View file

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

View file

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

View file

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

31
main.cc
View file

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

View file

@ -1,14 +1,11 @@
#pragma once
#ifndef REAL_BUILD
# include "externals.hh"
#endif
#include "filewatcher.hh"
#include "opast.hh"
#include <ebcl/SRDData.hh>
/*= 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;
};

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