#pragma once #include "sync.hh" #include "opast.hh" struct T_Rendertarget; namespace ops { using namespace ebcl; enum E_OpType { OP_END , // OP_CALL , OP_RET , // OP_SKIP , OP_COND_SKIP , // OP_RES_STACK , OP_PUSH , OP_POP , OP_DUP , // OP_LOAD , OP_STORE , OP_SLOAD , OP_CONST , OP_OFFSET , // OP_GET_INPUT , // OP_FP_LOAD , OP_FP_STORE , OP_FP_SLOAD , OP_FP_SSTORE , OP_FP_SSTORE_INT , // OP_FP_CMP , OP_FP_ADD , OP_FP_SUB , OP_FP_MUL , OP_FP_DIV , OP_FP_POW , // OP_FP_NEG , OP_FP_INV , OP_FP_NOT , OP_FP_SIN , OP_FP_COS , OP_FP_TAN , OP_FP_SQRT , OP_FP_EXP , OP_FP_LN , // OP_GEN_ASSETS , OP_INIT_PIPELINE , OP_INIT_PROGRAM , OP_INIT_SAMPLER , OP_INIT_TEXTURE , OP_FB_ATTACH , // OP_USE_FRAMEBUFFER , OP_FB_TOGGLE , OP_USE_PIPELINE , OP_USE_PROGRAM , OP_USE_TEXTURE , OP_UNIFORMS , OP_VIEWPORT , // OP_FULLSCREEN , OP_CLEAR , // OP_UI_PENTER , OP_UI_PEXIT , OP_UI_INPUT_DFT , OP_UI_ODBG , }; M_LSHIFT_OP( T_StringBuilder , E_OpType ); uint32_t ArgumentsFor( E_OpType op ) noexcept; int32_t DeltaMainStack( E_OpType op ) noexcept; int32_t DeltaFPUStack( E_OpType op ) noexcept; struct T_Op { static constexpr int MAX_ARGS = 2; E_OpType op; T_SRDLocation location; uint32_t args[ MAX_ARGS ]; T_Op( const E_OpType op , T_SRDLocation const& location , const uint32_t arg0 = 0 ) noexcept : op( op ) , location( location ) , args{ arg0 } { } T_Op( const E_OpType op , T_SRDLocation const& location , std::initializer_list< uint32_t > a ) noexcept : op( op ) , location( location ) { assert( a.size( ) <= MAX_ARGS ); auto it = a.begin( ); for ( auto i = 0u ; i < a.size( ) ; i ++ , ++it ) { args[ i ] = *it; } } }; M_LSHIFT_OP( T_StringBuilder , T_Op const& ); union T_OpValue { int32_t i; uint32_t u; float f; constexpr T_OpValue( ) : i{ 0 } {} constexpr T_OpValue( uint32_t u ) : u{ u } {} constexpr T_OpValue( float f ) : f{ f } {} }; struct T_OpProgram { T_MultiArray< T_Op > ops; // All operations uint32_t init , // Index of initialisation function frame; // Index of frame rendering function T_Array< T_OpValue > constants; // Constants values uint32_t nVariables{ 0 }; // Amount of variables T_Array< T_String > inputs; // Input definitions uint32_t nPrograms{ 0 } , // Amount of programs nFramebuffers{ 0 } , // Amount of framebuffers nPipelines{ 0 } , // Amount of pipelines nSamplers{ 0 } , // Amount of samplers nTextures{ 0 }; // Amount of textures T_Array< T_String > progNames; // GLSL program files T_Array< T_String > uiStrings; // UI strings for profiling, etc. }; using P_OpProgram = T_OwnPtr< T_OpProgram >; class T_Compiler : public A_PrivateImplementation { public: T_Compiler( ) noexcept; P_OpProgram compile( opast::T_ParserOutput const& input ) noexcept; }; struct T_OpContext { T_OpProgram& program; // The program uint32_t instrPtr; // Instruction pointer bool aborted{ false }; // Did the program fail? T_Array< T_OpValue > values; // VM data T_Array< T_OpValue > stack; // Main VM stack T_Array< float > initialInputs; // Initial input values T_OpValue wreg; // Work register double x87stack[ 8 ]; // x87 FPU emulation stack uint32_t x87sp; // x87 FPU emulation stack pointer // Allocated resources T_Array< T_OwnPtr< T_Rendertarget > > framebuffers; T_Array< T_OwnPtr< T_ShaderProgram > > programs; T_Array< T_OwnPtr< T_ShaderPipeline > > pipelines; T_Array< T_OwnPtr< T_TextureSampler > > samplers; T_Array< T_OwnPtr< T_Texture > > textures; T_Array< T_String > profiling; // Profiling sections that have been started int32_t curFb{ -1 }; // Index of current framebuffer enum E_RunTarget { R_INIT , R_RENDER }; explicit T_OpContext( T_OpProgram& program ) noexcept; void run( E_RunTarget target , float time , float width , float height ); private: void ensureStack( T_Op const& op , uint32_t min ); void ensureFpuStack( T_Op const& op , uint32_t minStacked , uint32_t minFree ); void checkAddress( T_Op const& op , uint32_t address ); }; class X_OpFailure : public std::exception { public: X_OpFailure( ) = delete; DEF_COPY( X_OpFailure ); DEF_MOVE( X_OpFailure ); X_OpFailure( T_Op const& op , T_String error ) noexcept; T_Op const& op( ) const noexcept { return *op_; } T_String const& error( ) const noexcept { return error_; } char const* what( ) const noexcept override; private: T_Op const* op_; T_String error_; T_String fullMessage_; }; } // namespace ops