From 2c6b96c6e2c52a8113dee4e6578f8ec144626475 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emmanuel=20Beno=C3=AEt?= Date: Sat, 14 Oct 2017 12:00:47 +0200 Subject: [PATCH] Started work on operators --- Makefile | 1 + control.cc | 246 +++++++++++++++++++++++++++++++++++++++++++++++++++++ control.hh | 214 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 461 insertions(+) create mode 100644 control.cc create mode 100644 control.hh diff --git a/Makefile b/Makefile index f672934..54940d5 100644 --- a/Makefile +++ b/Makefile @@ -26,6 +26,7 @@ DEMO = \ shaders.cc \ odbg.cc \ sync.cc \ + control.cc \ \ demo.cc \ \ diff --git a/control.cc b/control.cc new file mode 100644 index 0000000..17c7b44 --- /dev/null +++ b/control.cc @@ -0,0 +1,246 @@ +#include "externals.hh" +#include "control.hh" +#include "sync.hh" + +using namespace cops; + + +/*= X_OpFailure ==============================================================*/ + +X_OpFailure::X_OpFailure( + __rd__ std::string const& source , + __rd__ uint32_t line , + __rd__ std::string const& error ) noexcept + : std::exception( ) , source_( source ) , line_( line ) , + error_( error ) +{ + std::ostringstream oss; + oss << "Program error (" << source << ", l. " << line << "): " << error; + fullMessage_ = oss.str( ); +} + +char const* X_OpFailure::what( ) const noexcept +{ + return fullMessage_.c_str( ); +} + + +/*= T_Op =====================================================================*/ + +T_Op::T_Op( __rd__ const E_Op op ) + : op_( op ) +{ } + +T_Op::~T_Op( ) { } + + +X_OpFailure T_Op::error( + __rd__ std::string const& message ) const noexcept +{ + return X_OpFailure( source , line , message ); +} + + +/*= OPLoadConstant ===========================================================*/ + +OPLoadConstant::OPLoadConstant( + __rd__ const float constant ) + : T_Op( OP_LOAD_CONSTANT ) , constant( constant ) +{ } + +void OPLoadConstant::execute( + __rw__ T_Context& ctx ) +{ + ctx.opStack.push_back( constant ); +} + + +/*= OPLoadVariable ===========================================================*/ + +OPLoadVariable::OPLoadVariable( + __rd__ std::string const& variable ) + : T_Op( OP_LOAD_VARIABLE ) , variable( variable ) +{ } + +void OPLoadVariable::execute( + __rw__ T_Context& ctx ) +{ + const auto vPos( ctx.varPos.find( variable ) ); + if ( vPos == ctx.varPos.end( ) ) { + throw error( "variable '" + variable + "' not found" ); + } + ctx.opStack.push_back( ctx.varValues[ vPos->second ] ); +} + + +/*= OPLoadInput ==============================================================*/ + +OPLoadInput::OPLoadInput( + __rd__ std::string const& input ) + : T_Op( OP_LOAD_VARIABLE ) , input( input ) +{ } + +void OPLoadInput::execute( + __rw__ T_Context& ctx ) +{ + ctx.opStack.push_back( ctx.sync->valueOf( input , *( ctx.time ) ) ); +} + + +/*= OPStoreVariable ==========================================================*/ + +OPStoreVariable::OPStoreVariable( + __rd__ std::string const& variable ) + : T_Op( OP_LOAD_VARIABLE ) , variable( variable ) +{ } + +void OPStoreVariable::execute( + __rw__ T_Context& ctx ) +{ + if ( ctx.opStack.empty( ) ) { + throw error( "stack is empty" ); + } + + const auto vPos( ctx.varPos.find( variable ) ); + uint32_t pos; + if ( vPos == ctx.varPos.end( ) ) { + pos = ctx.varValues.size( ); + ctx.varPos.emplace( variable , pos ); + } else { + pos = vPos->second; + } + + ctx.varValues[ pos ] = ctx.opStack.back( ); + ctx.opStack.pop_back( ); +} + + +/*= Arithmetic operators =====================================================*/ + +void OPAdd::execute( + __rw__ T_Context& ctx ) +{ + if ( ctx.opStack.size( ) < 2 ) { + throw error( "missing operands in stack" ); + } + const float v( ctx.opStack.back( ) ); + ctx.opStack.pop_back( ); + ctx.opStack.back( ) += v; +} + +void OPMul::execute( + __rw__ T_Context& ctx ) +{ + if ( ctx.opStack.size( ) < 2 ) { + throw error( "missing operands in stack" ); + } + const float v( ctx.opStack.back( ) ); + ctx.opStack.pop_back( ); + ctx.opStack.back( ) *= v; +} + +void OPNeg::execute( + __rw__ T_Context& ctx ) +{ + if ( ctx.opStack.empty( ) ) { + throw error( "missing operand in stack" ); + } + ctx.opStack.back( ) = -ctx.opStack.back( ); +} + +void OPInv::execute( + __rw__ T_Context& ctx ) +{ + if ( ctx.opStack.empty( ) || ctx.opStack.back( ) == 0 ) { + throw error( "missing operand in stack" ); + } + ctx.opStack.back( ) = 1.0f / ctx.opStack.back( ); +} + + +/*= Stack operations =========================================================*/ + +OPDup::OPDup( __rd__ const uint32_t stackIndex ) + : T_Op( OP_DUP ) , stackIndex( stackIndex ) +{ } + +void OPDup::execute( + __rw__ T_Context& ctx ) +{ + if ( ctx.opStack.size( ) <= stackIndex ) { + std::string err( "stack does not have " ); + err += stackIndex + 1; + err += " items"; + throw error( err ); + } + ctx.opStack.push_back( *( ctx.opStack.end( ) - stackIndex - 1 ) ); +} + +/*----------------------------------------------------------------------------*/ + +OPXchg::OPXchg( __rd__ const uint32_t stackIndex ) + : T_Op( OP_XCHG ) , stackIndex( stackIndex ) +{ } + +void OPXchg::execute( + __rw__ T_Context& ctx ) +{ + if ( ctx.opStack.size( ) <= stackIndex ) { + std::string err( "stack does not have " ); + err += stackIndex + 1; + err += " items"; + throw error( err ); + } + if ( stackIndex ) { + std::swap( *( ctx.opStack.end( ) - 1 ) , *( ctx.opStack.end( ) - stackIndex - 1 ) ); + } +} + + +/*= OPSetUniform =============================================================*/ + +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 ) +{ } + +void OPSetUniform::execute( + __rw__ T_Context& ctx ) +{ + if ( count == 0 || ctx.opStack.size( ) < count ) { + std::string err( "stack does not have " ); + err += count; + err += " items"; + throw error( err ); + } + + void* funcs[] = { + &glProgramUniform1fv , &glProgramUniform2fv , &glProgramUniform3fv , &glProgramUniform4fv , + &glProgramUniform1iv , &glProgramUniform2iv , &glProgramUniform3iv , &glProgramUniform4iv , + }; + void (*func)( int , int , int , void* ) = (void (*)( int , int , int , void* )) funcs[ count + ( integer ? 4 : 0 ) ]; + + if ( integer ) { + int values[ count ]; + auto i = count; + while ( i != 0 ) { + values[ count - i ] = int( ctx.opStack.back( ) ); + ctx.opStack.pop_back( ); + i --; + } + func( program , uniform , 1 , values ); + } else { + float values[ count ]; + auto i = count; + while ( i != 0 ) { + values[ count - i ] = ctx.opStack.back( ); + ctx.opStack.pop_back( ); + i --; + } + func( program , uniform , 1 , values ); + } +} diff --git a/control.hh b/control.hh new file mode 100644 index 0000000..e63b3c8 --- /dev/null +++ b/control.hh @@ -0,0 +1,214 @@ +#pragma once +#ifndef REAL_BUILD +# include "externals.hh" +#endif + +struct T_SyncData; + +namespace cops { + + struct T_Context + { + float const* time; + T_SyncData const* sync; + + std::vector< float > varValues; + std::map< std::string , uint32_t > varPos; + + std::vector< float > opStack; + }; + + class X_OpFailure : public std::exception + { + public: + X_OpFailure( ) = delete; + DEF_COPY( X_OpFailure ); + DEF_MOVE( X_OpFailure ); + + X_OpFailure( + __rd__ std::string const& source , + __rd__ uint32_t line , + __rd__ std::string const& error ) noexcept; + + std::string const& source( ) const noexcept + { return source_; } + uint32_t line( ) const noexcept + { return line_; } + std::string const& error( ) const noexcept + { return error_; } + + char const* what( ) const noexcept override; + + private: + std::string source_; + uint32_t line_; + std::string error_; + std::string fullMessage_; + }; + + /*--------------------------------------------------------------------*/ + + enum E_Op + { + OP_LOAD_CONSTANT , + OP_LOAD_VARIABLE , + OP_LOAD_INPUT , + OP_STORE_VARIABLE , + // + OP_ADD , OP_MUL , + OP_NEG , OP_INV , + // + OP_DUP , OP_XCHG , + // + OP_SET_UNIFORM , + OP_USE_PIPELINE , + OP_USE_TEXTURE , + OP_USE_FRAMEBUFFER , + }; + + struct T_Op + { + explicit T_Op( + __rd__ const E_Op op ); + virtual ~T_Op( ) = 0; + + E_Op op( ) const noexcept + { return op_; } + + virtual void execute( + __rw__ T_Context& ctx ) = 0; + + std::string source; + uint32_t line; + + protected: + X_OpFailure error( + __rd__ std::string const& message ) const noexcept; + + private: + E_Op op_; + }; + using T_Operations = std::vector< cops::T_Op >; + + /*====================================================================*/ + + struct OPLoadConstant : public T_Op + { + explicit OPLoadConstant( + __rd__ const float constant ); + void execute( + __rw__ T_Context& ctx ) override; + float constant; + }; + + struct OPLoadVariable : public T_Op + { + explicit OPLoadVariable( + __rd__ std::string const& variable ); + void execute( + __rw__ T_Context& ctx ) override; + std::string variable; + }; + + struct OPLoadInput : public T_Op + { + explicit OPLoadInput( + __rd__ std::string const& input ); + void execute( + __rw__ T_Context& ctx ) override; + std::string input; + }; + + struct OPStoreVariable : public T_Op + { + explicit OPStoreVariable( + __rd__ std::string const& variable ); + void execute( + __rw__ T_Context& ctx ) override; + std::string variable; + }; + + /*--------------------------------------------------------------------*/ + + struct OPAdd : public T_Op + { + OPAdd( ) : T_Op( OP_ADD ) {} + void execute( + __rw__ T_Context& ctx ) override; + }; + + struct OPMul : public T_Op + { + OPMul( ) : T_Op( OP_MUL ) {} + void execute( + __rw__ T_Context& ctx ) override; + }; + + struct OPNeg : public T_Op + { + OPNeg( ) : T_Op( OP_NEG ) {} + void execute( + __rw__ T_Context& ctx ) override; + }; + + struct OPInv : public T_Op + { + OPInv( ) : T_Op( OP_INV ) {} + void execute( + __rw__ T_Context& ctx ) override; + }; + + /*--------------------------------------------------------------------*/ + + struct OPDup : public T_Op + { + explicit OPDup( uint32_t stackIndex = 0 ); + void execute( + __rw__ T_Context& ctx ) override; + uint32_t stackIndex; + }; + + struct OPXchg : public T_Op + { + explicit OPXchg( uint32_t stackIndex = 1 ); + void execute( + __rw__ T_Context& ctx ) override; + uint32_t stackIndex; + }; + + /*--------------------------------------------------------------------*/ + + 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 ) override; + + uint32_t program; + uint32_t uniform; + uint32_t count; + bool integer; + }; + + + struct OPUsePipeline : public T_Op + { + explicit OPUsePipeline( + __rd__ const uint32_t index ); + void execute( + __rw__ T_Context& ctx ) override; + + uint32_t pipeline; + }; + + /*====================================================================*/ + + void Execute( + __rd__ T_Operations const& operations , + __rw__ T_Context& context ); + +} // namespace cops