Emmanuel BENOîT
abb2c02d61
Committing as I need to make a few adjustments to the AST in order to simplify things.
192 lines
4.7 KiB
C++
192 lines
4.7 KiB
C++
#include "externals.hh"
|
|
#include "control.hh"
|
|
#include <ebcl/Algorithms.hh>
|
|
|
|
#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 );
|
|
}
|