From 647e247916301154fb63cee3cf34f87aefbb43f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emmanuel=20Beno=C3=AEt?= Date: Sun, 15 Oct 2017 10:22:24 +0200 Subject: [PATCH] Control system: function calls --- control.cc | 72 +++++++++++++++++++++++++++++++++++++++++++++--------- control.hh | 66 ++++++++++++++++++++++++++++++++++++++++--------- dof.cc | 59 +++++++++++++++++++++----------------------- dof.hh | 3 --- 4 files changed, 143 insertions(+), 57 deletions(-) diff --git a/control.cc b/control.cc index 1801ff5..5e1be37 100644 --- a/control.cc +++ b/control.cc @@ -8,14 +8,26 @@ using namespace cops; /*= Command execution ========================================================*/ void cops::Execute( - __rd__ T_Operations const& operations , - __rw__ T_Context& context ) + __rd__ T_Operations const& operations , + __rw__ T_Context& context ) { for ( auto const& op : operations ) { op->execute( context ); } } +T_Operations& T_Program::function( + __rd__ std::string const& name , + __rd__ const uint32_t args ) +{ + const auto p( functions.find( name ) ); + if ( p == functions.end( ) ) { + return functions.emplace( name , T_Function{ name , args } ).first->second.operations; + } + assert( p->second.arguments == args ); + return p->second.operations; +} + /*= X_OpFailure ==============================================================*/ @@ -188,10 +200,10 @@ void OPDup::execute( __rw__ T_Context& ctx ) const { if ( ctx.opStack.size( ) <= stackIndex ) { - std::string err( "stack does not have " ); - err += stackIndex + 1; - err += " items"; - throw error( err ); + std::ostringstream oss; + oss << "stack does not have " << ( stackIndex + 1 ) + << " items (only " << ctx.opStack.size( ) << ")"; + throw error( oss.str( ) ); } ctx.opStack.push_back( *( ctx.opStack.end( ) - stackIndex - 1 ) ); } @@ -224,20 +236,17 @@ void OPXchg::execute( // or, you know, a program name OPSetUniform::OPSetUniform( - __rd__ const uint32_t program , - __rd__ const uint32_t uniform , __rd__ const uint32_t count , __rd__ const bool integer ) - : T_Op( OP_SET_UNIFORM ) , program( program ) , uniform( uniform ) , - count( count ) , integer( integer ) + : T_Op( OP_SET_UNIFORM ) , count( count ) , integer( integer ) { } void OPSetUniform::execute( __rw__ T_Context& ctx ) const { - if ( count == 0 || ctx.opStack.size( ) < count ) { + if ( count == 0 || ctx.opStack.size( ) < count + 2 ) { std::string err( "stack does not have " ); - err += count; + err += count + 2; err += " items"; throw error( err ); } @@ -249,6 +258,11 @@ void OPSetUniform::execute( }; const F_SetUniform_ func{ *(F_SetUniform_*) funcs[ count + ( integer ? 4 : 0 ) - 1 ] }; + const GLuint program( ctx.opStack.back( ) ); + ctx.opStack.pop_back( ); + const GLuint uniform( ctx.opStack.back( ) ); + ctx.opStack.pop_back( ); + if ( integer ) { int values[ count ]; auto i = count; @@ -367,3 +381,37 @@ void OPFullscreen::execute( glBindVertexArray( 0 ); glDrawArrays( GL_TRIANGLE_STRIP , 0 , 4 ); } + + +/*= Flow control =============================================================*/ + +OPCall::OPCall( + __rd__ std::string const& function ) + : T_Op( OP_CALL ) , function( function ) +{ } + +void OPCall::execute( + __rw__ T_Context& ctx ) const +{ + auto fp( ctx.program->functions.find( function ) ); + if ( fp == ctx.program->functions.end( ) ) { + throw error( "function '" + function + "' not found" ); + } + + auto const& func( fp->second ); + const auto ssz( ctx.opStack.size( ) ); + if ( ssz < func.arguments ) { + std::string err; + err = "function '" + function + "' requires "; + err += func.arguments; + err += " argument"; + err += ( func.arguments > 1 ? "s" : "" ); + throw error( err ); + } + + Execute( func.operations , ctx ); + if ( ctx.opStack.size( ) < ssz ) { + throw error( "function '" + function + "' ate the stack" ); + } + ctx.opStack.resize( ssz - func.arguments ); +} diff --git a/control.hh b/control.hh index 5a4d3b0..a66bac6 100644 --- a/control.hh +++ b/control.hh @@ -7,8 +7,12 @@ struct T_SyncData; namespace cops { + struct T_Program; + struct T_Context { + T_Program const* program; + float const* time; T_SyncData const* sync; @@ -71,7 +75,9 @@ namespace cops { OP_SET_VIEWPORT , // OP_CLEAR , - OP_FULLSCREEN + OP_FULLSCREEN , + // + OP_CALL }; struct T_Op @@ -86,8 +92,8 @@ namespace cops { virtual void execute( __rw__ T_Context& ctx ) const = 0; - std::string source; - uint32_t line; + std::string source{}; + uint32_t line{0}; protected: X_OpFailure error( @@ -108,6 +114,42 @@ namespace cops { return ops; } + void Execute( + __rd__ T_Operations const& operations , + __rw__ T_Context& context ); + + /*--------------------------------------------------------------------*/ + + struct T_Function + { + std::string name; + uint32_t arguments; + T_Operations operations; + + T_Function( __rd__ std::string const& name , + __rd__ const uint32_t arguments ) + : name( name ) , arguments( arguments ) + { } + DEF_COPY( T_Function ); + DEF_MOVE( T_Function ); + }; + + struct T_Program + { + std::map< std::string , T_Function > functions; + T_Operations main; + + T_Operations& function( + __rd__ std::string const& name , + __rd__ const uint32_t args ); + + void execute( __rw__ T_Context& context ) + { + context.program = this; + Execute( main , context ); + } + }; + /*====================================================================*/ struct OPLoadConstant : public T_Op @@ -199,15 +241,11 @@ namespace cops { struct OPSetUniform : public T_Op { OPSetUniform( - __rd__ const uint32_t program , - __rd__ const uint32_t uniform , __rd__ const uint32_t count , __rd__ const bool integer ); void execute( __rw__ T_Context& ctx ) const override; - uint32_t program; - uint32_t uniform; uint32_t count; bool integer; }; @@ -269,10 +307,16 @@ namespace cops { __rw__ T_Context& ctx ) const override; }; - /*====================================================================*/ + /*--------------------------------------------------------------------*/ - void Execute( - __rd__ T_Operations const& operations , - __rw__ T_Context& context ); + struct OPCall : public T_Op + { + explicit OPCall( + __rd__ std::string const& function ); + void execute( + __rw__ T_Context& ctx ) const override; + + std::string function; + }; } // namespace cops diff --git a/dof.cc b/dof.cc index 9de40ec..437758a 100644 --- a/dof.cc +++ b/dof.cc @@ -55,9 +55,8 @@ void T_DoFPass::render( const auto idPass1( spPass1_.program( E_ShaderType::FRAGMENT ) ); const auto idPass2( spPass2_.program( E_ShaderType::FRAGMENT ) ); const auto idSampler( tm.sampler( "linear-edge" )->id( ) ); - ops_.clear( ); - ops_ - // First pass + T_Program program; + program.function( "SetDofUniforms" , 1 ) << OPLoadVariable( "height" ) << OPLoadVariable( "width" ) << OPLoadConstant( 0 ) @@ -65,48 +64,46 @@ void T_DoFPass::render( << OPLoadVariable( "time" ) << OPLoadVariable( "height" ) << OPLoadVariable( "width" ) + << OPLoadConstant( U_RES_TIME ) + << OPDup( 8 ) << OPLoadConstant( nSamples_ ) + << OPLoadConstant( U_SAMPLES ) + << OPDup( 11 ) << OPLoadConstant( filterParams_[ 3 ] ) << OPLoadConstant( filterParams_[ 2 ] ) << OPLoadConstant( filterParams_[ 1 ] ) << OPLoadConstant( filterParams_[ 0 ] ) + << OPLoadConstant( U_PARAMS ) + << OPDup( 17 ) << OPLoadConstant( 1 ) + << OPLoadConstant( U_DEPTH ) + << OPDup( 20 ) << OPLoadConstant( 0 ) - << OPSetUniform( idPass1 , U_INPUT , 1 , true ) - << OPSetUniform( idPass1 , U_DEPTH , 1 , true ) - << OPSetUniform( idPass1 , U_PARAMS , 4 , false ) - << OPSetUniform( idPass1 , U_SAMPLES , 1 , false ) - << OPSetUniform( idPass1 , U_RES_TIME , 3 , false ) + << OPLoadConstant( U_INPUT ) + << OPDup( 23 ) + << OPSetUniform( 1 , true ) + << OPSetUniform( 1 , true ) + << OPSetUniform( 4 , false ) + << OPSetUniform( 1 , false ) + << OPSetUniform( 3 , false ) + << OPSetViewport( ) + ; + + program.main + // First pass + << OPLoadConstant( idPass1 ) + << OPCall( "SetDofUniforms" ) << OPUseTexture( 0 , imageInput_.id( ) , idSampler ) << OPUseTexture( 1 , depthInput_.id( ) , idSampler ) << OPUsePipeline( spPass1_.id( ) ) << OPUseFramebuffer( rtPass1_.id( ) ) - << OPSetViewport( ) << OPFullscreen( ) // Second pass - << OPLoadVariable( "height" ) - << OPLoadVariable( "width" ) - << OPLoadConstant( 0 ) - << OPLoadConstant( 0 ) - << OPLoadVariable( "time" ) - << OPLoadVariable( "height" ) - << OPLoadVariable( "width" ) - << OPLoadConstant( nSamples_ ) - << OPLoadConstant( filterParams_[ 3 ] ) - << OPLoadConstant( filterParams_[ 2 ] ) - << OPLoadConstant( filterParams_[ 1 ] ) - << OPLoadConstant( filterParams_[ 0 ] ) - << OPLoadConstant( 1 ) - << OPLoadConstant( 0 ) - << OPSetUniform( idPass2 , U_INPUT , 1 , true ) - << OPSetUniform( idPass2 , U_DEPTH , 1 , true ) - << OPSetUniform( idPass2 , U_PARAMS , 4 , false ) - << OPSetUniform( idPass2 , U_SAMPLES , 1 , false ) - << OPSetUniform( idPass2 , U_RES_TIME , 3 , false ) + << OPLoadConstant( idPass2 ) + << OPCall( "SetDofUniforms" ) << OPUseTexture( 0 , txPass1_.id( ) , idSampler ) << OPUsePipeline( spPass2_.id( ) ) << OPUseFramebuffer( rtPass2_.id( ) ) - << OPSetViewport( ) << OPFullscreen( ) ; @@ -114,11 +111,11 @@ void T_DoFPass::render( printf( "GL fail in DoF" ); } ); - cops::T_Context ctx; + T_Context ctx; ctx.store( "time" , position ); ctx.store( "width" , imageInput_.width( ) ); ctx.store( "height" , imageInput_.height( ) ); - cops::Execute( ops_ , ctx ); + program.execute( ctx ); PEND( ); } diff --git a/dof.hh b/dof.hh index df3baf1..7c5164d 100644 --- a/dof.hh +++ b/dof.hh @@ -36,8 +36,5 @@ struct T_DoFPass // SharpDist/SharpRange/Falloff/MaxBlur float filterParams_[ 4 ]; int nSamples_; - - // XXX experimenting with control system - cops::T_Operations ops_; };