#include "externals.hh" #include "control.hh" #include #define INVASIVE_TRACES using namespace ebcl; using namespace ops; using namespace opast; namespace { struct T_CompilerImpl_ { T_Visitor< A_Node > astVisitor{ ASTVisitorBrowser }; T_Set< uint32_t > constants{ UseTag< IndexBacked< > >( ) }; T_ParserOutput* input; P_OpProgram output; uint32_t fiVariables , fiFramebuffers , fiPipelines , fiPrograms , fiSamplers , fiTextures; P_OpProgram compile( T_ParserOutput const& input ) noexcept; private: void gatherConstants( ) noexcept; void countAssets( ) noexcept; bool compileNode( uint32_t funcIndex , A_Node& node , bool exit ) noexcept; }; P_OpProgram T_CompilerImpl_::compile( T_ParserOutput const& in ) noexcept { input = const_cast< T_ParserOutput* >( &in ); output = NewOwned< T_OpProgram >( ); // Gather all constants used in expressions, count resources gatherConstants( ); countAssets( ); // Get function indices // FIXME ideally we should remap functions so that init is always 0 // and frame is always 1 output->init = input->root.functionIndex( "*init*" ); output->frame = input->root.functionIndex( "*frame*" ); #ifdef INVASIVE_TRACES printf( "function indices\n\t%d\tinit\n\t%d\tframe\n" , output->init , output->frame ); #endif // Compile each function uint32_t cfi; for ( cfi = 0u ; cfi < input->root.nFunctions( ) ; cfi ++ ) { output->ops.next( ); auto& func( input->root.function( cfi ) ); #ifdef INVASIVE_TRACES printf( "compiling function %s\n" , func.name( ).toOSString( ).data( ) ); #endif astVisitor.visit( func , [=]( A_Node& node , const bool exit ) -> bool { return compileNode( cfi , node , exit ); } ); } return std::move( output ); } void T_CompilerImpl_::gatherConstants( ) noexcept { constants.clear( ); astVisitor.visit( input->root , [&]( A_Node& node , const bool exit ) { if ( exit && node.type( ) == A_Node::EXPR_CONST ) { T_OpValue value; value.f = dynamic_cast< T_ConstantExprNode& >( node ).floatValue( ); if ( value.f != 0 && value.f != 1 ) { constants.add( value.u ); } } return true; } ); #ifdef INVASIVE_TRACES printf( "%d constants\n" , constants.size( ) ); for ( auto i = 0u ; i < constants.size( ) ; i ++ ) { printf( " %08x" , constants[ i ] ); if ( i % 4 == 3 ) { printf( "\n" ); } } if ( constants.size( ) % 4 ) { printf( "\n" ); } #endif } void T_CompilerImpl_::countAssets( ) noexcept { auto const nt{ input->types.size( ) }; for ( auto i = 0u ; i < nt ; i ++ ) { const auto t{ input->types.values( )[ i ] }; switch ( t ) { case E_DataType::FRAMEBUFFER: output->nFramebuffers ++; break; case E_DataType::PIPELINE: output->nPipelines ++; break; case E_DataType::PROGRAM: output->nPrograms ++; break; case E_DataType::SAMPLER: output->nSamplers ++; break; case E_DataType::TEXTURE: output->nTextures ++; break; case E_DataType::VARIABLE: output->nVariables ++; break; case E_DataType::INPUT: assert( !output->inputs.contains( input->types.keys( )[ i ] ) ); output->inputs.add( input->types.keys( )[ i ] ); break; case E_DataType::BUILTIN: case E_DataType::UNKNOWN: break; } } fiVariables = 3 + constants.size( ); fiFramebuffers = fiVariables + output->nVariables; fiPipelines = fiFramebuffers + output->nFramebuffers; fiPrograms = fiPipelines + output->nPipelines; fiSamplers = fiPrograms + output->nPrograms; fiTextures = fiSamplers + output->nSamplers; #ifdef INVASIVE_TRACES printf( "assets\n\t%d framebuffers\n\t%d pipelines\n" "\t%d programs\n\t%d samplers\n\t%d textures\n" "\t%d variables\n\t%d inputs\n" , output->nFramebuffers , output->nPipelines , output->nPrograms , output->nSamplers , output->nTextures , output->nVariables , output->inputs.size( ) ); printf( "table ranges\n\t0\t2\tBuilt-ins\n" "\t3\t%d\tConstants\n" "\t%d\t%d\tVariables\n" "\t%d\t%d\tFramebuffers\n" "\t%d\t%d\tPipelines\n" "\t%d\t%d\tPrograms\n" "\t%d\t%d\tSamplers\n" "\t%d\t%d\tTextures\n" , fiVariables - 1 , fiVariables , fiFramebuffers - 1 , fiFramebuffers , fiPipelines - 1 , fiPipelines , fiPrograms - 1 , fiPrograms , fiSamplers - 1 , fiSamplers , fiTextures - 1 , fiTextures , fiTextures + output->nTextures - 1 ); #endif } bool T_CompilerImpl_::compileNode( const uint32_t funcIndex , A_Node& node , const bool exit ) noexcept { return false; } } /*= T_Compiler =================================================================*/ T_Compiler::T_Compiler( ) noexcept : A_PrivateImplementation( new T_CompilerImpl_( ) ) { } P_OpProgram T_Compiler::compile( T_ParserOutput const& input ) noexcept { return p< T_CompilerImpl_ >( ).compile( input ); }