2017-11-06 18:15:56 +01:00
|
|
|
#include "externals.hh"
|
2017-11-06 10:15:38 +01:00
|
|
|
#include "opast.hh"
|
2017-11-09 12:13:08 +01:00
|
|
|
#include <ebcl/Algorithms.hh>
|
2017-11-06 10:15:38 +01:00
|
|
|
|
|
|
|
using namespace ebcl;
|
|
|
|
using namespace opast;
|
|
|
|
|
|
|
|
|
|
|
|
/*= A_Node ===================================================================*/
|
|
|
|
|
|
|
|
A_Node::A_Node( const E_Type type ,
|
|
|
|
A_Node* const parent ) noexcept
|
|
|
|
: type_( type ) , parent_( parent )
|
|
|
|
{
|
|
|
|
assert( ( type == ROOT && !parent ) || ( type != ROOT && parent ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
A_Node::~A_Node( ) { }
|
|
|
|
|
|
|
|
T_RootNode& A_Node::root( ) const noexcept
|
|
|
|
{
|
|
|
|
A_Node const* node( this );
|
|
|
|
while ( node->parent_ ) {
|
|
|
|
node = node->parent_;
|
|
|
|
}
|
|
|
|
assert( node );
|
|
|
|
assert( node->type_ == ROOT );
|
|
|
|
return *dynamic_cast< T_RootNode* >(
|
|
|
|
const_cast< A_Node* >( node ) );
|
|
|
|
}
|
|
|
|
|
2017-11-09 12:13:08 +01:00
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
A_Node* opast::ASTVisitorBrowser(
|
|
|
|
A_Node& node ,
|
|
|
|
const uint32_t child ) noexcept
|
|
|
|
{
|
|
|
|
switch ( node.type( ) ) {
|
|
|
|
|
|
|
|
// Root node
|
|
|
|
case A_Node::ROOT: {
|
|
|
|
auto& n( (T_RootNode&) node );
|
|
|
|
if ( child < n.nFunctions( ) ) {
|
|
|
|
return &n.function( child );
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Functions / special blocks
|
|
|
|
case A_Node::DECL_FN: case A_Node::DECL_INIT: case A_Node::DECL_FRAME:
|
|
|
|
if ( child == 0 ) {
|
|
|
|
auto& n( (A_FuncNode&) node );
|
|
|
|
return &n.instructions( );
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
// Instruction list
|
|
|
|
case A_Node::ILIST: {
|
|
|
|
auto& n( (T_InstrListNode&) node );
|
|
|
|
if ( child < n.size( ) ) {
|
|
|
|
return &n.node( child );
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Unary operators
|
|
|
|
case A_Node::EXPR_NEG: case A_Node::EXPR_INV:
|
|
|
|
case A_Node::EXPR_NOT: case A_Node::EXPR_SIN:
|
|
|
|
case A_Node::EXPR_COS: case A_Node::EXPR_TAN:
|
|
|
|
case A_Node::EXPR_SQRT: case A_Node::EXPR_EXP:
|
|
|
|
case A_Node::EXPR_LN:
|
|
|
|
{
|
|
|
|
auto& n( (T_UnaryOperatorNode&) node );
|
|
|
|
if ( child == 0 && n.hasArgument( ) ) {
|
|
|
|
return &n.argument( );
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Binary operators
|
|
|
|
case A_Node::EXPR_ADD: case A_Node::EXPR_SUB:
|
|
|
|
case A_Node::EXPR_MUL: case A_Node::EXPR_DIV:
|
|
|
|
case A_Node::EXPR_POW:
|
|
|
|
case A_Node::EXPR_CMP_EQ: case A_Node::EXPR_CMP_NE:
|
|
|
|
case A_Node::EXPR_CMP_GT: case A_Node::EXPR_CMP_GE:
|
|
|
|
case A_Node::EXPR_CMP_LT: case A_Node::EXPR_CMP_LE:
|
|
|
|
{
|
|
|
|
auto& n( (T_BinaryOperatorNode&) node );
|
|
|
|
if ( child == 0 && n.hasLeft( ) ) {
|
|
|
|
return &n.left( );
|
|
|
|
}
|
|
|
|
if ( child < 2 && n.hasRight( ) ) {
|
|
|
|
return &n.right( );
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Nodes that do not have children
|
|
|
|
case A_Node::EXPR_ID: case A_Node::EXPR_CONST:
|
2017-11-09 18:24:39 +01:00
|
|
|
case A_Node::EXPR_INPUT:
|
2017-11-10 10:15:56 +01:00
|
|
|
//
|
2017-11-09 12:13:08 +01:00
|
|
|
case A_Node::OP_PROGRAM: case A_Node::OP_PIPELINE:
|
2017-11-09 18:24:39 +01:00
|
|
|
case A_Node::OP_INPUT: case A_Node::OP_FULLSCREEN:
|
2017-11-10 21:01:35 +01:00
|
|
|
case A_Node::OP_ODBG: case A_Node::OP_LOCALS:
|
2017-11-10 21:56:28 +01:00
|
|
|
case A_Node::OP_MAINOUT:
|
2017-11-10 10:15:56 +01:00
|
|
|
//
|
2017-11-09 18:24:39 +01:00
|
|
|
case A_Node::OP_USE_FRAMEBUFFER: case A_Node::OP_USE_PIPELINE:
|
|
|
|
case A_Node::OP_USE_PROGRAM: case A_Node::OP_USE_TEXTURE:
|
2017-11-09 12:13:08 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
// Profile instruction
|
|
|
|
case A_Node::OP_PROFILE:
|
|
|
|
if ( child == 0 ) {
|
|
|
|
return &( ((T_ProfileInstrNode&) node).instructions( ) );
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
// Call instruction
|
|
|
|
case A_Node::OP_CALL:
|
|
|
|
{
|
|
|
|
auto& n( (T_CallInstrNode&) node );
|
2017-11-13 09:25:32 +01:00
|
|
|
const auto nArgs( n.arguments( ) );
|
|
|
|
if ( child < nArgs ) {
|
|
|
|
return &n.argument( nArgs - child - 1 );
|
2017-11-09 12:13:08 +01:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2017-11-12 17:01:13 +01:00
|
|
|
case A_Node::TN_ARG:
|
|
|
|
{
|
|
|
|
if ( child == 0 ) {
|
|
|
|
return &( (T_CallInstrNode::T_Argument&) node ).expression( );
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2017-11-09 12:13:08 +01:00
|
|
|
|
2017-11-10 22:09:24 +01:00
|
|
|
// Clear instruction
|
|
|
|
case A_Node::OP_CLEAR:
|
|
|
|
{
|
|
|
|
auto& n( (T_ClearInstrNode&) node );
|
|
|
|
if ( child < n.components( ) ) {
|
|
|
|
return &n.component( child );
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2017-11-12 11:13:38 +01:00
|
|
|
// Conditional instruction & associated technical nodes
|
2017-11-09 12:13:08 +01:00
|
|
|
case A_Node::OP_COND:
|
|
|
|
{
|
|
|
|
auto& n( (T_CondInstrNode&) node );
|
|
|
|
auto c = child;
|
|
|
|
if ( n.hasExpression( ) ) {
|
|
|
|
if ( c == 0 ) {
|
|
|
|
return &n.expression( );
|
|
|
|
}
|
|
|
|
c --;
|
|
|
|
}
|
|
|
|
if ( !n.cases( ).empty( ) ) {
|
|
|
|
if ( c < n.cases( ).size( ) ) {
|
|
|
|
return &n.getCase( n.cases( )[ c ] );
|
|
|
|
}
|
|
|
|
c -= n.cases( ).size( );
|
|
|
|
}
|
|
|
|
if ( n.hasDefaultCase( ) && c == 0 ) {
|
|
|
|
return &n.defaultCase( );
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2017-11-12 11:13:38 +01:00
|
|
|
case A_Node::TN_CONDITION:
|
|
|
|
if ( child == 0 ) {
|
|
|
|
return &( (T_CondInstrNode::T_Expression&) node ).expression( );
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case A_Node::TN_CASE:
|
|
|
|
if ( child == 0 ) {
|
|
|
|
return &( (T_CondInstrNode::T_ValuedCase&) node ).instructions( );
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case A_Node::TN_DEFAULT:
|
|
|
|
if ( child == 0 ) {
|
|
|
|
return &( (T_CondInstrNode::T_DefaultCase&) node ).instructions( );
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2017-11-09 12:13:08 +01:00
|
|
|
// Set instruction
|
|
|
|
case A_Node::OP_SET:
|
|
|
|
if ( child == 0 ) {
|
|
|
|
auto& n( (T_SetInstrNode&) node );
|
|
|
|
if ( n.hasExpression( ) ) {
|
|
|
|
return &n.expression( );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
// Texture instruction
|
|
|
|
case A_Node::OP_TEXTURE:
|
|
|
|
{
|
|
|
|
auto& n( (T_TextureInstrNode&) node );
|
|
|
|
auto c = child;
|
|
|
|
if ( n.hasWidth( ) ) {
|
|
|
|
if ( c == 0 ) {
|
|
|
|
return &n.width( );
|
|
|
|
}
|
|
|
|
c --;
|
|
|
|
}
|
2017-11-10 20:38:17 +01:00
|
|
|
if ( n.hasHeight( ) ) {
|
|
|
|
if ( c == 0 ) {
|
|
|
|
return &n.height( );
|
|
|
|
}
|
|
|
|
c --;
|
|
|
|
}
|
2017-11-10 21:01:35 +01:00
|
|
|
return c == 0 ? n.lods( ) : nullptr;
|
2017-11-10 20:38:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Framebuffer definition; may have LOD expressions
|
|
|
|
case A_Node::OP_FRAMEBUFFER:
|
|
|
|
{
|
|
|
|
auto& n( (T_FramebufferInstrNode&) node );
|
|
|
|
auto c = child;
|
|
|
|
for ( auto i = 0u ; i < n.colorAttachments( ) ; i ++ ) {
|
|
|
|
auto* const lod( n.colorAttachmentLOD( i ) );
|
|
|
|
if ( lod ) {
|
|
|
|
if ( c == 0 ) {
|
|
|
|
return lod;
|
|
|
|
}
|
|
|
|
c --;
|
|
|
|
}
|
|
|
|
}
|
2017-11-10 21:01:35 +01:00
|
|
|
if ( c == 0 && n.hasDepthAttachment( ) ) {
|
2017-11-10 20:38:17 +01:00
|
|
|
return n.depthAttachmentLOD( );
|
2017-11-09 12:13:08 +01:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2017-11-10 17:18:29 +01:00
|
|
|
// Sampler definition may have LOD expressions
|
|
|
|
case A_Node::OP_SAMPLER:
|
|
|
|
{
|
|
|
|
auto& n( (T_SamplerInstrNode&) node );
|
|
|
|
auto c = child;
|
|
|
|
if ( n.minLod( ) ) {
|
|
|
|
if ( c == 0 ) {
|
|
|
|
return n.minLod( );
|
|
|
|
}
|
|
|
|
c--;
|
|
|
|
}
|
|
|
|
if ( n.maxLod( ) && c == 0 ) {
|
|
|
|
return n.maxLod( );
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2017-11-09 23:20:48 +01:00
|
|
|
// Uniforms instruction
|
|
|
|
case A_Node::OP_UNIFORMS:
|
|
|
|
{
|
|
|
|
auto& n( (T_UniformsInstrNode&) node );
|
|
|
|
if ( child < n.values( ) ) {
|
|
|
|
return &n.value( child );
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2017-11-09 18:24:39 +01:00
|
|
|
// Viewport instruction
|
|
|
|
case A_Node::OP_VIEWPORT:
|
|
|
|
{
|
|
|
|
auto& n( (T_ViewportInstrNode&) node );
|
|
|
|
auto c = child;
|
|
|
|
for ( int i = 0 ; i < 4 ; i ++ ) {
|
|
|
|
T_ViewportInstrNode::E_Parameter p{
|
|
|
|
T_ViewportInstrNode::E_Parameter( i ) };
|
|
|
|
if ( n.hasParameter( p ) ) {
|
|
|
|
if ( c == 0 ) {
|
|
|
|
return &n.parameter( p );
|
|
|
|
}
|
|
|
|
c --;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2017-11-09 12:13:08 +01:00
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2017-11-06 14:06:21 +01:00
|
|
|
|
2017-11-10 23:09:36 +01:00
|
|
|
/*= E_DataType ===============================================================*/
|
|
|
|
|
|
|
|
T_StringBuilder& opast::operator<<(
|
|
|
|
T_StringBuilder& sb ,
|
|
|
|
const E_DataType dt )
|
|
|
|
{
|
|
|
|
switch ( dt ) {
|
|
|
|
case E_DataType::UNKNOWN:
|
|
|
|
sb << "unknown";
|
|
|
|
return sb;
|
|
|
|
case E_DataType::BUILTIN:
|
|
|
|
sb << "built-in variable";
|
|
|
|
return sb;
|
|
|
|
case E_DataType::VARIABLE:
|
|
|
|
sb << "variable";
|
|
|
|
return sb;
|
|
|
|
case E_DataType::FRAMEBUFFER:
|
|
|
|
sb << "framebuffer";
|
|
|
|
return sb;
|
|
|
|
case E_DataType::INPUT:
|
|
|
|
sb << "input";
|
|
|
|
return sb;
|
|
|
|
case E_DataType::PIPELINE:
|
|
|
|
sb << "pipeline";
|
|
|
|
return sb;
|
|
|
|
case E_DataType::PROGRAM:
|
|
|
|
sb << "program";
|
|
|
|
return sb;
|
|
|
|
case E_DataType::SAMPLER:
|
|
|
|
sb << "sampler";
|
|
|
|
return sb;
|
|
|
|
case E_DataType::TEXTURE:
|
|
|
|
sb << "texture";
|
|
|
|
return sb;
|
|
|
|
}
|
|
|
|
|
|
|
|
sb << "*unknown data type*";
|
|
|
|
return sb;
|
|
|
|
}
|
|
|
|
|
2017-11-06 10:15:38 +01:00
|
|
|
/*= A_FuncNode ===============================================================*/
|
|
|
|
|
|
|
|
A_FuncNode::A_FuncNode(
|
|
|
|
const bool isInit ,
|
|
|
|
T_RootNode* const root ) noexcept
|
|
|
|
: A_Node( isInit ? DECL_INIT : DECL_FRAME , root ) ,
|
2017-11-06 14:06:21 +01:00
|
|
|
name_( isInit ? "*init*" : "*frame*" ) ,
|
|
|
|
instructions_( *this )
|
2017-11-06 10:15:38 +01:00
|
|
|
{ }
|
|
|
|
|
|
|
|
A_FuncNode::A_FuncNode(
|
|
|
|
T_String const& name ,
|
|
|
|
T_RootNode* const root ) noexcept
|
2017-11-06 14:06:21 +01:00
|
|
|
: A_Node( DECL_FN , root ) , name_( name ) ,
|
|
|
|
instructions_( *this )
|
2017-11-06 10:15:38 +01:00
|
|
|
{ }
|
|
|
|
|
2017-11-11 09:54:38 +01:00
|
|
|
T_Optional< T_SRDLocation > A_FuncNode::addLocalVariable(
|
|
|
|
T_String const& name ,
|
|
|
|
T_SRDLocation const& location ) noexcept
|
|
|
|
{
|
|
|
|
auto const* const pnp( locals_.get( name ) );
|
|
|
|
if ( pnp ) {
|
|
|
|
return pnp->location;
|
|
|
|
}
|
2017-11-11 12:00:20 +01:00
|
|
|
T_Local_ lv{ name , location , false };
|
|
|
|
lv.type = E_DataType::VARIABLE;
|
|
|
|
locals_.add( std::move( lv ) );
|
2017-11-11 09:54:38 +01:00
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
2017-11-06 10:15:38 +01:00
|
|
|
|
|
|
|
/*= T_RootNode ===============================================================*/
|
|
|
|
|
|
|
|
T_RootNode::T_RootNode( ) noexcept
|
|
|
|
: A_Node( ROOT , nullptr ) , functions_(
|
|
|
|
[]( T_OwnPtr< A_FuncNode > const& f ) {
|
|
|
|
return f->name( );
|
|
|
|
} )
|
|
|
|
{ }
|
|
|
|
|
|
|
|
T_RootNode::T_AddFunctionResult T_RootNode::addFunction(
|
|
|
|
T_OwnPtr< A_FuncNode >& function ) noexcept
|
|
|
|
{
|
|
|
|
T_String const& fn( function->name( ) );
|
|
|
|
auto const* const pf( functions_.get( fn ) );
|
|
|
|
if ( !pf ) {
|
|
|
|
auto* const rv( function.get( ) );
|
|
|
|
functions_.add( std::move( function ) );
|
|
|
|
return *rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
T_String dfn;
|
|
|
|
uint32_t dupCtr( 0 );
|
|
|
|
do {
|
|
|
|
T_StringBuilder fnsb;
|
|
|
|
fnsb << fn << " dup " << dupCtr ++;
|
|
|
|
dfn = std::move( fnsb );
|
|
|
|
} while ( functions_.contains( dfn ) );
|
|
|
|
|
|
|
|
T_OwnPtr< A_FuncNode > df( NewOwned< T_FuncNode >( dfn , *this ) );
|
|
|
|
auto* const rv( df.get( ) );
|
|
|
|
functions_.add( std::move( df ) );
|
|
|
|
return T_AddFunctionResult{ *rv , (*pf)->location( ) };
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*= T_FuncNode ===============================================================*/
|
|
|
|
|
|
|
|
T_Optional< T_SRDLocation > T_FuncNode::addArgument(
|
|
|
|
T_SRDToken const& token ) noexcept
|
|
|
|
{
|
|
|
|
assert( token.type( ) == E_SRDTokenType::WORD );
|
|
|
|
assert( token.hasLocation( ) );
|
|
|
|
|
2017-11-11 09:54:38 +01:00
|
|
|
const auto pnp( locals_.indexOf( token.stringValue( ) ) );
|
|
|
|
if ( pnp != T_HashIndex::INVALID_INDEX ) {
|
|
|
|
return locals_[ pnp ].location;
|
2017-11-06 10:15:38 +01:00
|
|
|
}
|
2017-11-11 09:54:38 +01:00
|
|
|
locals_.add( T_Local_{ token.stringValue( ) , token.location( ) , true } );
|
2017-11-06 10:15:38 +01:00
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
2017-11-11 09:54:38 +01:00
|
|
|
uint32_t T_FuncNode::arguments( ) const noexcept
|
|
|
|
{
|
|
|
|
const auto n( locals_.size( ) );
|
|
|
|
uint32_t na{ 0u };
|
|
|
|
|
|
|
|
for ( auto i = 0u ; i < n ; i ++ ) {
|
|
|
|
if ( locals_[ i ].argument ) {
|
|
|
|
na ++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return na;
|
|
|
|
}
|
|
|
|
|
2017-11-06 10:15:38 +01:00
|
|
|
|
2017-11-06 14:06:21 +01:00
|
|
|
/*= T_PipelineInstrNode ======================================================*/
|
|
|
|
|
|
|
|
T_Optional< T_SRDLocation > T_PipelineInstrNode::addProgram(
|
|
|
|
T_SRDToken const& pidToken ) noexcept
|
|
|
|
{
|
|
|
|
T_String const& name( pidToken.stringValue( ) );
|
|
|
|
const auto pIndex( pids_.indexOf( name ) );
|
|
|
|
if ( pIndex != -1 ) {
|
|
|
|
return pidLocations_[ pIndex ];
|
|
|
|
}
|
|
|
|
pids_.add( name );
|
|
|
|
pidLocations_.add( pidToken.location( ) );
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-11-06 16:38:04 +01:00
|
|
|
/*= T_UnaryOperatorNode ======================================================*/
|
|
|
|
|
|
|
|
T_UnaryOperatorNode::T_UnaryOperatorNode(
|
|
|
|
A_Node& parent ,
|
|
|
|
const E_Operator op ) noexcept
|
|
|
|
: A_ExpressionNode( ([op]() {
|
|
|
|
switch ( op ) {
|
|
|
|
case NEG: return EXPR_NEG;
|
|
|
|
case INV: return EXPR_INV;
|
|
|
|
case NOT: return EXPR_NOT;
|
|
|
|
case SIN: return EXPR_SIN;
|
|
|
|
case COS: return EXPR_COS;
|
|
|
|
case TAN: return EXPR_TAN;
|
|
|
|
case SQRT: return EXPR_SQRT;
|
|
|
|
case EXP: return EXPR_EXP;
|
|
|
|
case LN: return EXPR_LN;
|
|
|
|
}
|
|
|
|
std::abort( );
|
|
|
|
})( ) , parent ) , op_( op )
|
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
|
|
/*= T_BinaryOperatorNode =====================================================*/
|
|
|
|
|
|
|
|
T_BinaryOperatorNode::T_BinaryOperatorNode(
|
|
|
|
A_Node& parent ,
|
|
|
|
const E_Operator op ) noexcept
|
|
|
|
: A_ExpressionNode( ([op]() {
|
|
|
|
switch ( op ) {
|
|
|
|
case ADD: return EXPR_ADD;
|
|
|
|
case SUB: return EXPR_SUB;
|
|
|
|
case MUL: return EXPR_MUL;
|
|
|
|
case DIV: return EXPR_DIV;
|
|
|
|
case POW: return EXPR_POW;
|
|
|
|
case CMP_EQ: return EXPR_CMP_EQ;
|
|
|
|
case CMP_NE: return EXPR_CMP_NE;
|
|
|
|
case CMP_GT: return EXPR_CMP_GT;
|
|
|
|
case CMP_GE: return EXPR_CMP_GE;
|
|
|
|
case CMP_LT: return EXPR_CMP_LT;
|
|
|
|
case CMP_LE: return EXPR_CMP_LE;
|
|
|
|
}
|
|
|
|
std::abort( );
|
|
|
|
})( ) , parent ) , op_( op )
|
|
|
|
{ }
|
2017-11-10 10:15:56 +01:00
|
|
|
|
|
|
|
|
|
|
|
/*= T_FramebufferInstrNode ===================================================*/
|
|
|
|
|
2017-11-10 20:38:17 +01:00
|
|
|
bool T_FramebufferInstrNode::hasAttachment(
|
|
|
|
T_String const& name ) const noexcept
|
|
|
|
{
|
|
|
|
if ( depthAttachment_ && depthAttachment_->id == name ) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
const auto nca( colorAttachments_.size( ) );
|
|
|
|
for ( auto i = 0u ; i < nca ; i ++ ) {
|
|
|
|
if ( colorAttachments_[ i ].id == name ) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-11-10 10:15:56 +01:00
|
|
|
bool T_FramebufferInstrNode::addColorAttachment(
|
2017-11-10 20:38:17 +01:00
|
|
|
T_SRDToken const& id ,
|
|
|
|
P_ExpressionNode lod ) noexcept
|
2017-11-10 10:15:56 +01:00
|
|
|
{
|
2017-11-10 20:38:17 +01:00
|
|
|
if ( hasAttachment( id.stringValue( ) ) ) {
|
2017-11-10 10:15:56 +01:00
|
|
|
return false;
|
|
|
|
}
|
2017-11-10 20:38:17 +01:00
|
|
|
colorAttachments_.add( T_Attachment_{ id.stringValue( ) ,
|
|
|
|
std::move( lod ) , id.location( ) } );
|
2017-11-10 10:15:56 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool T_FramebufferInstrNode::setDepthAttachment(
|
2017-11-10 20:38:17 +01:00
|
|
|
T_SRDToken const& id ,
|
|
|
|
P_ExpressionNode lod ) noexcept
|
2017-11-10 10:15:56 +01:00
|
|
|
{
|
2017-11-10 20:38:17 +01:00
|
|
|
if ( depthAttachment_ || hasAttachment( id.stringValue( ) ) ) {
|
2017-11-10 10:15:56 +01:00
|
|
|
return false;
|
|
|
|
}
|
2017-11-10 20:38:17 +01:00
|
|
|
depthAttachment_ = T_Attachment_{ id.stringValue( ) ,
|
|
|
|
std::move( lod ) , id.location( ) };
|
2017-11-10 10:15:56 +01:00
|
|
|
return true;
|
|
|
|
}
|
2017-11-10 12:48:57 +01:00
|
|
|
|
|
|
|
|
|
|
|
/*= T_OutputDebugInstrNode ===================================================*/
|
|
|
|
|
|
|
|
T_OutputDebugInstrNode::T_OutputDebugInstrNode(
|
|
|
|
T_InstrListNode& parent ,
|
|
|
|
T_SRDToken const& texture ,
|
|
|
|
const E_ODbgMode mode ,
|
|
|
|
T_SRDLocation const& modeLocation ,
|
|
|
|
T_SRDToken const& description ) noexcept
|
|
|
|
: A_InstructionNode( OP_ODBG , parent ) ,
|
|
|
|
idTexture_( texture.stringValue( ) ) ,
|
|
|
|
locTexture_( texture.location( ) ) ,
|
|
|
|
mode_( mode ) , locMode_( modeLocation ) ,
|
|
|
|
description_( description.stringValue( ) ) ,
|
|
|
|
locDescription_( description.location( ) )
|
|
|
|
{ }
|
2017-11-10 17:18:29 +01:00
|
|
|
|
|
|
|
|
|
|
|
/*= T_SamplerInstrNode =========================================================*/
|
|
|
|
|
|
|
|
T_Optional< T_SRDLocation > T_SamplerInstrNode::setSampling(
|
|
|
|
E_TexSampling mode ,
|
|
|
|
T_SRDLocation const& location ) noexcept
|
|
|
|
{
|
|
|
|
if ( sampling_ ) {
|
|
|
|
return sampling_->location;
|
|
|
|
}
|
|
|
|
sampling_ = T_Sampling_{ location , mode };
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
|
|
|
T_Optional< T_SRDLocation > T_SamplerInstrNode::setMipmapSampling(
|
|
|
|
E_TexSampling mode ,
|
|
|
|
T_SRDLocation const& location ) noexcept
|
|
|
|
{
|
|
|
|
if ( mipmaps_ ) {
|
|
|
|
return mipmaps_->location;
|
|
|
|
}
|
|
|
|
mipmaps_ = T_Mipmaps_{ location , mode };
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
|
|
|
T_Optional< T_SRDLocation > T_SamplerInstrNode::setNoMipmap(
|
|
|
|
T_SRDLocation const& location ) noexcept
|
|
|
|
{
|
|
|
|
if ( mipmaps_ ) {
|
|
|
|
return mipmaps_->location;
|
|
|
|
}
|
|
|
|
mipmaps_ = T_Mipmaps_{ location , {} };
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
|
|
|
T_Optional< T_SRDLocation > T_SamplerInstrNode::setWrapping(
|
|
|
|
E_TexWrap mode ,
|
|
|
|
T_SRDLocation const& location ) noexcept
|
|
|
|
{
|
|
|
|
if ( wrapping_ ) {
|
|
|
|
return wrapping_->location;
|
|
|
|
}
|
|
|
|
wrapping_ = T_Wrapping_{ location , mode };
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
|
|
|
T_Optional< T_SRDLocation > T_SamplerInstrNode::setLOD(
|
|
|
|
T_SRDLocation const& location ,
|
|
|
|
P_ExpressionNode min ,
|
|
|
|
P_ExpressionNode max ) noexcept
|
|
|
|
{
|
|
|
|
if ( lod_ ) {
|
|
|
|
return lod_->location;
|
|
|
|
}
|
|
|
|
lod_ = T_LOD_{ location , std::move( min ) , std::move( max ) };
|
|
|
|
return {};
|
|
|
|
}
|
2017-11-10 21:01:35 +01:00
|
|
|
|
2017-11-12 11:13:38 +01:00
|
|
|
|
2017-11-10 21:01:35 +01:00
|
|
|
/*= T_LocalsInstrNode ===========================================================*/
|
|
|
|
|
2017-11-11 09:54:38 +01:00
|
|
|
T_Optional< T_SRDLocation > T_LocalsInstrNode::addVariable(
|
2017-11-10 21:01:35 +01:00
|
|
|
T_SRDToken const& token ) noexcept
|
|
|
|
{
|
2017-11-11 09:54:38 +01:00
|
|
|
const auto pnp( vars_.indexOf( token.stringValue( ) ) );
|
|
|
|
if ( pnp != -1 ) {
|
|
|
|
return varLocs_[ pnp ];
|
2017-11-10 21:01:35 +01:00
|
|
|
}
|
|
|
|
vars_.add( token.stringValue( ) );
|
|
|
|
varLocs_.add( token.location( ) );
|
2017-11-11 09:54:38 +01:00
|
|
|
return {};
|
2017-11-10 21:01:35 +01:00
|
|
|
}
|
2017-11-12 11:13:38 +01:00
|
|
|
|
|
|
|
|
|
|
|
/*= T_CondInstrNode ============================================================*/
|
|
|
|
|
|
|
|
void T_CondInstrNode::setExpression(
|
|
|
|
P_ExpressionNode expression ) noexcept
|
|
|
|
{
|
|
|
|
if ( !expression ) {
|
|
|
|
expression_.clear( );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
expression_ = NewOwned< T_Expression >(
|
|
|
|
*this , std::move( expression ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
void T_CondInstrNode::setCase(
|
|
|
|
const int64_t value ,
|
|
|
|
P_InstrListNode instrList ) noexcept
|
|
|
|
{
|
|
|
|
cases_.remove( value );
|
|
|
|
if ( instrList ) {
|
|
|
|
cases_.add( NewOwned< T_ValuedCase >( *this , value ,
|
|
|
|
std::move( instrList ) ) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void T_CondInstrNode::setDefaultCase(
|
|
|
|
P_InstrListNode defaultCase ) noexcept
|
|
|
|
{
|
|
|
|
if ( !defaultCase ) {
|
|
|
|
defaultCase_.clear( );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
defaultCase_ = NewOwned< T_DefaultCase >( *this ,
|
|
|
|
std::move( defaultCase ) );
|
|
|
|
}
|