Emmanuel BENOîT
68d01ca42e
Shaders are no longer found under /shaders in the project; they can be anywhere. In addition, paths for both (program) instructions in the script and include directives in shader source code are relative to the file which contains them.
1512 lines
38 KiB
C++
1512 lines
38 KiB
C++
#pragma once
|
|
#include "c-renderdefs.hh"
|
|
#include <ebcl/SRDData.hh>
|
|
|
|
|
|
struct T_SyncOverrideSection;
|
|
|
|
namespace opast {
|
|
|
|
|
|
/*= BASE CLASS FOR AST NODES ===================================================*/
|
|
|
|
class T_RootNode;
|
|
|
|
class A_Node
|
|
{
|
|
public:
|
|
enum E_Type {
|
|
ROOT , // Root node
|
|
ILIST , // Instruction list
|
|
//
|
|
DECL_INIT , // Initialisation block
|
|
DECL_FRAME , // Frame block
|
|
DECL_FN , // Function
|
|
//
|
|
OP_CALL , // Function call
|
|
OP_CLEAR , // Clear buffer
|
|
OP_COMPUTE , // Compute shader dispatch
|
|
OP_COND , // Conditional instruction
|
|
OP_FRAMEBUFFER ,// Define framebuffer
|
|
OP_FULLSCREEN , // Draw a fullscreen quad
|
|
OP_IMAGE , // Image unit binding
|
|
OP_INPUT , // Input declaration
|
|
OP_LOCALS , // Declare local variables
|
|
OP_MAINOUT , // Select the output buffer
|
|
OP_ODBG , // Output debugging
|
|
OP_OVERRIDES , // Register input overrides
|
|
OP_PIPELINE , // Shader pipeline declaration
|
|
OP_PROFILE , // Profiling block
|
|
OP_PROGRAM , // Shader program declaration
|
|
OP_SAMPLER , // Define sampler
|
|
OP_SET , // Set instruction
|
|
OP_TEXTURE , // Define texture
|
|
OP_UNIFORMS , // Set uniforms
|
|
OP_VIEWPORT , // Set viewport
|
|
// "Use-<obj type>" instructions
|
|
OP_USE_FRAMEBUFFER ,
|
|
OP_USE_PIPELINE ,
|
|
OP_USE_PROGRAM ,
|
|
OP_USE_TEXTURE ,
|
|
// Unary operators
|
|
EXPR_NEG , EXPR_INV , EXPR_NOT ,
|
|
EXPR_SIN , EXPR_COS , EXPR_TAN ,
|
|
EXPR_SQRT , EXPR_EXP , EXPR_LN ,
|
|
// Binary operators
|
|
EXPR_ADD , EXPR_SUB ,
|
|
EXPR_MUL , EXPR_DIV ,
|
|
EXPR_POW ,
|
|
// Binary operators - comparisons
|
|
EXPR_CMP_EQ , EXPR_CMP_NE ,
|
|
EXPR_CMP_GT , EXPR_CMP_GE ,
|
|
EXPR_CMP_LT , EXPR_CMP_LE ,
|
|
//
|
|
EXPR_ID , // Variable access
|
|
EXPR_INPUT , // Input value access
|
|
EXPR_CONST , // Numeric constant
|
|
// Technical nodes
|
|
TN_CONDITION , // Expression for a conditional instruction
|
|
TN_CASE , // Valued case for a conditional instruction
|
|
TN_DEFAULT , // Default case for a conditional instruction
|
|
TN_FBATT , // Framebuffer attachment
|
|
TN_ARG , // Call argument
|
|
};
|
|
|
|
private:
|
|
const E_Type type_;
|
|
A_Node* parent_;
|
|
ebcl::T_SRDLocation location_;
|
|
|
|
protected:
|
|
T_AutoArray< T_OwnPtr< A_Node > , 8 > children_;
|
|
|
|
explicit A_Node( const E_Type type ,
|
|
A_Node* const parent ) noexcept;
|
|
|
|
public:
|
|
virtual ~A_Node( ) = 0;
|
|
|
|
E_Type type( ) const noexcept
|
|
{ return type_; }
|
|
|
|
ebcl::T_SRDLocation& location( ) noexcept
|
|
{ return location_; }
|
|
ebcl::T_SRDLocation const& location( ) const noexcept
|
|
{ return location_; }
|
|
|
|
A_Node& parent( ) const noexcept
|
|
{ assert( parent_ ); return *parent_; }
|
|
|
|
T_RootNode& root( ) const noexcept;
|
|
|
|
uint32_t size( ) const noexcept
|
|
{ return children_.size( ); }
|
|
|
|
T_OwnPtr< A_Node > const& child(
|
|
const uint32_t index ) const noexcept
|
|
{ return children_[ index ]; }
|
|
T_OwnPtr< A_Node >& child(
|
|
const uint32_t index ) noexcept
|
|
{ return children_[ index ]; }
|
|
|
|
bool replace( A_Node const& node ,
|
|
T_OwnPtr< A_Node >& replacement ) noexcept;
|
|
|
|
void setParent( A_Node& newParent ) noexcept
|
|
{ parent_ = &newParent; }
|
|
};
|
|
|
|
// Browser function to be used with T_Visitor
|
|
extern A_Node* ASTVisitorBrowser(
|
|
A_Node& node ,
|
|
const uint32_t child ) noexcept;
|
|
|
|
// Data types
|
|
enum class E_DataType {
|
|
UNKNOWN ,
|
|
BUILTIN ,
|
|
VARIABLE ,
|
|
FRAMEBUFFER ,
|
|
INPUT ,
|
|
PIPELINE ,
|
|
PROGRAM ,
|
|
SAMPLER ,
|
|
TEXTURE ,
|
|
};
|
|
M_LSHIFT_OP( T_StringBuilder , E_DataType );
|
|
|
|
|
|
/*= BASE STRUCTURES FOR INSTRUCTIONS =========================================*/
|
|
|
|
// Some instructions are restricted to either the initialisation code or the
|
|
// frame code.
|
|
enum class E_InstrRestriction
|
|
{
|
|
INIT , FRAME
|
|
};
|
|
using T_InstrRestriction = T_Flags< E_InstrRestriction >;
|
|
|
|
// Base class for instruction nodes
|
|
class A_InstructionNode : public A_Node
|
|
{
|
|
private:
|
|
const T_InstrRestriction restriction_;
|
|
|
|
protected:
|
|
A_InstructionNode( const E_Type type ,
|
|
A_Node& parent ,
|
|
T_InstrRestriction restriction = {} ) noexcept
|
|
: A_Node( type , &parent ) ,
|
|
restriction_( restriction )
|
|
{
|
|
assert( !restriction_.isSet({
|
|
E_InstrRestriction::INIT ,
|
|
E_InstrRestriction::FRAME }) );
|
|
}
|
|
|
|
public:
|
|
T_InstrRestriction restriction( ) const noexcept
|
|
{ return restriction_; }
|
|
};
|
|
|
|
// Nodes that store lists of instructions
|
|
class T_InstrListNode : public A_Node
|
|
{
|
|
public:
|
|
T_InstrListNode( A_Node& parent ) noexcept
|
|
: A_Node( ILIST , &parent ) { }
|
|
|
|
template<
|
|
typename IType ,
|
|
typename... ArgTypes
|
|
> IType& add( ArgTypes&&... args );
|
|
|
|
A_InstructionNode& node( const uint32_t index ) const noexcept
|
|
{ return dynamic_cast< A_InstructionNode& >( *children_[ index ] ); }
|
|
|
|
void replaceMultiple(
|
|
A_InstructionNode& instruction ,
|
|
T_InstrListNode* replacement ) noexcept;
|
|
};
|
|
|
|
template<
|
|
typename IType ,
|
|
typename... ArgTypes
|
|
> inline IType& T_InstrListNode::add(
|
|
ArgTypes&&... args )
|
|
{
|
|
children_.add( NewOwned< IType >( *this ,
|
|
std::forward< ArgTypes >( args ) ... ) );
|
|
return (IType&) *children_.last( );
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
|
|
// Base class for expressions
|
|
class A_ExpressionNode : public A_Node
|
|
{
|
|
protected:
|
|
A_ExpressionNode( E_Type type ,
|
|
A_Node& parent ) noexcept
|
|
: A_Node( type , &parent )
|
|
{ }
|
|
};
|
|
using P_ExpressionNode = T_OwnPtr< A_ExpressionNode >;
|
|
|
|
// Technical node used for the arguments of various instructions
|
|
class T_ArgumentNode : public A_Node
|
|
{
|
|
public:
|
|
T_ArgumentNode( A_Node& parent ,
|
|
P_ExpressionNode expr ) noexcept
|
|
: A_Node( TN_ARG , &parent )
|
|
{
|
|
if ( expr ) {
|
|
location( ) = expr->location( );
|
|
children_.add( std::move( expr ) );
|
|
}
|
|
}
|
|
|
|
A_ExpressionNode& expression( ) const noexcept
|
|
{ return (A_ExpressionNode&) *child( 0 ); }
|
|
bool isIdentifier( ) const noexcept
|
|
{ return expression( ).type( ) == EXPR_ID; }
|
|
|
|
void expression( P_ExpressionNode expr ) noexcept
|
|
{ assert( expr ); child( 0 ) = std::move( expr ); }
|
|
};
|
|
using P_ArgumentNode = T_OwnPtr< T_ArgumentNode >;
|
|
|
|
|
|
/*= FUNCTIONS AND ROOT NODES =================================================*/
|
|
|
|
// Function-like nodes
|
|
class A_FuncNode : public A_Node
|
|
{
|
|
private:
|
|
T_String name_;
|
|
T_InstrListNode* instructions_{ nullptr };
|
|
|
|
protected:
|
|
struct T_Local_
|
|
{
|
|
T_String name;
|
|
ebcl::T_SRDLocation location;
|
|
bool argument;
|
|
E_DataType type{ E_DataType::UNKNOWN };
|
|
|
|
T_Local_( T_String const& name ,
|
|
ebcl::T_SRDLocation const& location ,
|
|
const bool argument ) noexcept
|
|
: name{ name } , location{ location } ,
|
|
argument{ argument }
|
|
{ }
|
|
};
|
|
T_ObjectTable< T_String , T_Local_ > locals_{
|
|
[]( T_Local_ const& l ) -> T_String {
|
|
return l.name;
|
|
}
|
|
};
|
|
|
|
protected:
|
|
// For init or frame entry points.
|
|
// isInit = true => init entry point
|
|
// isInit = false => frame entry point
|
|
explicit A_FuncNode( bool isInit ,
|
|
T_RootNode* const parent ) noexcept;
|
|
|
|
// For normal functions
|
|
explicit A_FuncNode( T_String const& name ,
|
|
T_RootNode* const parent ) noexcept;
|
|
|
|
public:
|
|
T_String const& name( ) const noexcept
|
|
{ return name_; }
|
|
|
|
T_InstrListNode& instructions( ) noexcept
|
|
{
|
|
if ( !instructions_ ) {
|
|
auto p{ NewOwned< T_InstrListNode >( *this ) };
|
|
instructions_ = p.get( );
|
|
children_.add( std::move( p ) );
|
|
}
|
|
return *instructions_;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------
|
|
|
|
T_Optional< ebcl::T_SRDLocation > addLocalVariable(
|
|
T_String const& name ,
|
|
ebcl::T_SRDLocation const& location ) noexcept;
|
|
|
|
uint32_t locals( ) const noexcept
|
|
{ return locals_.size( ); }
|
|
bool hasLocal( T_String const& id ) const noexcept
|
|
{ return locals_.contains( id ); }
|
|
|
|
bool isArgument( T_String const& id ) const noexcept
|
|
{
|
|
auto const* const ptr( locals_.get( id ) );
|
|
return ptr && ptr->argument;
|
|
}
|
|
|
|
uint32_t getLocalIndex(
|
|
T_String const& name ) const noexcept
|
|
{ return locals_.indexOf( name ); }
|
|
|
|
T_String const& getLocalName(
|
|
const uint32_t index ) const noexcept
|
|
{ return locals_[ index ].name; }
|
|
ebcl::T_SRDLocation const& getLocalLocation(
|
|
const uint32_t index ) const noexcept
|
|
{ return locals_[ index ].location; }
|
|
|
|
E_DataType getLocalType(
|
|
T_String const& name ) const noexcept
|
|
{ return locals_.get( name )->type; }
|
|
E_DataType getLocalType(
|
|
const uint32_t index ) const noexcept
|
|
{ return locals_[ index ].type; }
|
|
|
|
void setLocalType(
|
|
const uint32_t index ,
|
|
const E_DataType type ) noexcept
|
|
{ locals_[ index ].type = type; }
|
|
|
|
void removeLocal( T_String const& name ) noexcept
|
|
{ locals_.remove( name ); }
|
|
};
|
|
using P_InstrListNode = T_OwnPtr< T_InstrListNode >;
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
// Root node, keeps track of the whole tree and related data (function table,
|
|
// assets...)
|
|
class T_RootNode : public A_Node
|
|
{
|
|
private:
|
|
T_KeyValueTable< T_String , uint32_t > functions_;
|
|
|
|
public:
|
|
T_RootNode( ) noexcept;
|
|
|
|
// ---------------------------------------------------------------------
|
|
|
|
// Return type for addFunction. We'll always return a reference to a
|
|
// function node (which may or may not be the same as the initial one,
|
|
// if there were duplicates), and we'll return the location of the
|
|
// initial function in the case of a duplicate.
|
|
struct T_AddFunctionResult
|
|
{
|
|
A_FuncNode& function;
|
|
T_Optional< ebcl::T_SRDLocation > dupLocation;
|
|
|
|
T_AddFunctionResult( A_FuncNode& function ) noexcept
|
|
: function{ function } , dupLocation{}
|
|
{}
|
|
|
|
T_AddFunctionResult( A_FuncNode& function ,
|
|
ebcl::T_SRDLocation const& dupLocation ) noexcept
|
|
: function{ function } , dupLocation{ dupLocation }
|
|
{}
|
|
};
|
|
|
|
// Attempts to add a function. If the function is already present in
|
|
// the table, the result will be set up with the previous declaration's
|
|
// location, and the specified function will not be modified (a duplicate
|
|
// entry will be added to the table instead).
|
|
T_AddFunctionResult addFunction(
|
|
T_OwnPtr< A_FuncNode >& function ) noexcept;
|
|
|
|
// ---------------------------------------------------------------------
|
|
|
|
bool hasFunction( T_String const& name ) noexcept
|
|
{ return functions_.contains( name ); }
|
|
bool hasInit( ) noexcept
|
|
{ return hasFunction( "*init*" ); }
|
|
bool hasFrame( ) noexcept
|
|
{ return hasFunction( "*frame*" ); }
|
|
|
|
uint32_t nFunctions( ) const noexcept
|
|
{ return functions_.size( ); }
|
|
|
|
int32_t functionIndex( T_String const& name ) const noexcept
|
|
{
|
|
auto const* const ip{ functions_.get( name ) };
|
|
return ip ? *ip : -1;
|
|
}
|
|
|
|
A_FuncNode& function( const uint32_t index ) const noexcept
|
|
{ return dynamic_cast< A_FuncNode& >( *child( index ) ); }
|
|
|
|
void removeFunction( T_String const& name ) noexcept
|
|
{
|
|
auto const* const ip{ functions_.get( name ) };
|
|
if ( !ip ) {
|
|
return;
|
|
}
|
|
const auto i{ *ip };
|
|
functions_.remove( name );
|
|
children_.removeSwap( i );
|
|
if ( i < children_.size( ) ) {
|
|
functions_.update( function( i ).name( ) , i );
|
|
}
|
|
}
|
|
};
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
// Init & frame functions
|
|
class T_SpecialFuncNode : public A_FuncNode
|
|
{
|
|
public:
|
|
T_SpecialFuncNode(
|
|
bool isInit ,
|
|
T_RootNode& parent ) noexcept
|
|
: A_FuncNode( isInit , &parent )
|
|
{ }
|
|
};
|
|
|
|
// Normal functions
|
|
class T_FuncNode : public A_FuncNode
|
|
{
|
|
public:
|
|
T_FuncNode( T_String const& name ,
|
|
T_RootNode& parent ) noexcept
|
|
: A_FuncNode( name , &parent )
|
|
{ }
|
|
|
|
// Add an argument. If the argument is a duplicate, return the location
|
|
// of the initial argument.
|
|
T_Optional< ebcl::T_SRDLocation > addArgument(
|
|
ebcl::T_SRDToken const& token ) noexcept;
|
|
|
|
uint32_t arguments( ) const noexcept;
|
|
};
|
|
|
|
|
|
/*= GENERAL / FLOW CONTROL INSTRUCTIONS ========================================*/
|
|
|
|
// Function call
|
|
class T_CallInstrNode : public A_InstructionNode
|
|
{
|
|
private:
|
|
T_String id_;
|
|
ebcl::T_SRDLocation idLocation_;
|
|
|
|
public:
|
|
T_CallInstrNode( T_InstrListNode& parent ,
|
|
ebcl::T_SRDToken const& idToken ) noexcept
|
|
: A_InstructionNode( OP_CALL , parent ) ,
|
|
id_( idToken.stringValue( ) ) ,
|
|
idLocation_( idToken.location( ) )
|
|
{ }
|
|
|
|
void addArgument( P_ExpressionNode expr ) noexcept
|
|
{
|
|
if ( expr ) {
|
|
children_.add( NewOwned< T_ArgumentNode >(
|
|
*this , std::move( expr ) ) );
|
|
}
|
|
}
|
|
|
|
T_String const& id( ) const noexcept
|
|
{ return id_; }
|
|
ebcl::T_SRDLocation const& idLocation( ) const noexcept
|
|
{ return idLocation_; }
|
|
|
|
T_ArgumentNode& argument( const uint32_t index ) const noexcept
|
|
{ return (T_ArgumentNode&) *child( index ); }
|
|
};
|
|
|
|
// Conditional instruction
|
|
class T_CondInstrNode : public A_InstructionNode
|
|
{
|
|
public:
|
|
class T_Expression : public A_Node
|
|
{
|
|
public:
|
|
T_Expression( T_CondInstrNode& parent ,
|
|
P_ExpressionNode expr )
|
|
: A_Node( TN_CONDITION , &parent )
|
|
{
|
|
children_.add( std::move( expr ) );
|
|
}
|
|
|
|
A_ExpressionNode& expression( ) const noexcept
|
|
{ return (A_ExpressionNode&) *child( 0 ); }
|
|
|
|
void expression( P_ExpressionNode expr ) noexcept
|
|
{ assert( expr ); child( 0 ) = std::move( expr ); }
|
|
};
|
|
|
|
class T_ValuedCase : public A_Node
|
|
{
|
|
private:
|
|
int64_t value_;
|
|
|
|
public:
|
|
T_ValuedCase( T_CondInstrNode& parent ,
|
|
const int64_t value ,
|
|
P_InstrListNode il )
|
|
: A_Node( TN_CASE , &parent ) ,
|
|
value_( value )
|
|
{
|
|
children_.add( std::move( il ) );
|
|
}
|
|
|
|
int64_t value( ) const noexcept
|
|
{ return value_; }
|
|
T_InstrListNode& instructions( ) const noexcept
|
|
{ return (T_InstrListNode&) *child( 0 ); }
|
|
};
|
|
|
|
class T_DefaultCase : public A_Node
|
|
{
|
|
public:
|
|
T_DefaultCase( T_CondInstrNode& parent ,
|
|
P_InstrListNode il )
|
|
: A_Node( TN_DEFAULT , &parent )
|
|
{
|
|
children_.add( std::move( il ) );
|
|
}
|
|
|
|
T_InstrListNode& instructions( ) const noexcept
|
|
{ return (T_InstrListNode&) *child( 0 ); }
|
|
};
|
|
|
|
private:
|
|
T_Optional< uint32_t > expression_;
|
|
T_KeyValueTable< int64_t , uint32_t > cases_;
|
|
T_Optional< uint32_t > defaultCase_;
|
|
|
|
void handleRemoval( uint32_t idx ) noexcept;
|
|
|
|
public:
|
|
explicit T_CondInstrNode( T_InstrListNode& parent ) noexcept
|
|
: A_InstructionNode( OP_COND , parent )
|
|
{ }
|
|
|
|
void setExpression( P_ExpressionNode expression ) noexcept;
|
|
bool hasExpression( ) const noexcept
|
|
{ return bool( expression_ ); }
|
|
T_Expression& expression( ) const noexcept
|
|
{ return (T_Expression&) *child( *expression_ ); }
|
|
|
|
void setCase( const int64_t value ,
|
|
P_InstrListNode instrList ) noexcept;
|
|
void rmCase( const int64_t value ) noexcept
|
|
{ cases_.remove( value ); }
|
|
|
|
uint32_t nCases( ) const noexcept
|
|
{ return cases_.size( ); }
|
|
T_Array< int64_t > const& cases( ) const noexcept
|
|
{ return cases_.keys( ); }
|
|
bool hasCase( const int64_t value ) const noexcept
|
|
{ return cases_.contains( value ); }
|
|
T_ValuedCase& getCase( const int64_t value ) const noexcept
|
|
{ return (T_ValuedCase&) *child( *cases_.get( value ) ); }
|
|
T_ValuedCase& getCaseByIndex(
|
|
const uint32_t index ) const noexcept
|
|
{ return (T_ValuedCase&) *child( cases_[ index ] ); }
|
|
|
|
void setDefaultCase( P_InstrListNode defaultCase ) noexcept;
|
|
bool hasDefaultCase( ) const noexcept
|
|
{ return bool( defaultCase_ ); }
|
|
T_DefaultCase& defaultCase( ) const noexcept
|
|
{ return (T_DefaultCase&) *child( *defaultCase_ ); }
|
|
};
|
|
|
|
// Local variable declarations
|
|
class T_LocalsInstrNode : public A_InstructionNode
|
|
{
|
|
private:
|
|
T_AutoArray< T_String , 8 > vars_;
|
|
T_AutoArray< ebcl::T_SRDLocation , 8 > varLocs_;
|
|
|
|
public:
|
|
T_LocalsInstrNode( T_InstrListNode& parent ) noexcept
|
|
: A_InstructionNode( OP_LOCALS , parent )
|
|
{ }
|
|
|
|
T_Optional< ebcl::T_SRDLocation > addVariable(
|
|
ebcl::T_SRDToken const& token ) noexcept;
|
|
|
|
uint32_t variables( ) const noexcept
|
|
{ return vars_.size( ); }
|
|
|
|
T_String const& varName(
|
|
const uint32_t index ) const noexcept
|
|
{ return vars_[ index ]; }
|
|
|
|
ebcl::T_SRDLocation const& varLocation(
|
|
const uint32_t index ) const noexcept
|
|
{ return varLocs_[ index ]; }
|
|
};
|
|
|
|
// Setting a global variable
|
|
class T_SetInstrNode : public A_InstructionNode
|
|
{
|
|
private:
|
|
T_String id_;
|
|
ebcl::T_SRDLocation idLocation_;
|
|
|
|
public:
|
|
T_SetInstrNode( T_InstrListNode& parent ,
|
|
ebcl::T_SRDToken const& idToken ) noexcept
|
|
: A_InstructionNode( OP_SET , parent ) ,
|
|
id_( idToken.stringValue( ) ) ,
|
|
idLocation_( idToken.location( ) )
|
|
{ }
|
|
|
|
T_String const& id( ) const noexcept
|
|
{ return id_; }
|
|
ebcl::T_SRDLocation const& idLocation( ) const noexcept
|
|
{ return idLocation_; }
|
|
|
|
void id( T_String const& nid ) noexcept
|
|
{ id_ = nid; }
|
|
|
|
void setExpression( P_ExpressionNode expression ) noexcept
|
|
{
|
|
if ( children_.size( ) ) {
|
|
child( 0 ) = std::move( expression );
|
|
} else {
|
|
children_.add( std::move( expression ) );
|
|
}
|
|
}
|
|
|
|
bool hasExpression( ) const noexcept
|
|
{ return children_.size( ) && child( 0 ); }
|
|
A_ExpressionNode& expression( ) const noexcept
|
|
{ return (A_ExpressionNode&) *child( 0 ); }
|
|
};
|
|
|
|
|
|
/*= RESOURCE DEFINITION INSTRUCTIONS =========================================*/
|
|
|
|
// Base class
|
|
class A_ResourceDefInstrNode : public A_InstructionNode
|
|
{
|
|
private:
|
|
T_String id_;
|
|
ebcl::T_SRDLocation idLocation_;
|
|
E_DataType dataType_;
|
|
|
|
protected:
|
|
A_ResourceDefInstrNode(
|
|
const E_Type type ,
|
|
T_InstrListNode& parent ,
|
|
ebcl::T_SRDToken const& identifier ,
|
|
const E_DataType dataType ) noexcept
|
|
: A_InstructionNode( type , parent , E_InstrRestriction::FRAME ) ,
|
|
id_( identifier.stringValue( ) ) ,
|
|
idLocation_( identifier.location( ) ) ,
|
|
dataType_( dataType )
|
|
{ }
|
|
|
|
public:
|
|
T_String const& id( ) const noexcept
|
|
{ return id_; }
|
|
ebcl::T_SRDLocation const& idLocation( ) const noexcept
|
|
{ return idLocation_; }
|
|
|
|
E_DataType dataType( ) const noexcept
|
|
{ return dataType_; }
|
|
};
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
|
|
// Framebuffer definition instruction
|
|
class T_FramebufferInstrNode : public A_ResourceDefInstrNode
|
|
{
|
|
public:
|
|
class T_Attachment : public A_Node
|
|
{
|
|
private:
|
|
bool depth_;
|
|
T_String id_;
|
|
|
|
public:
|
|
T_Attachment( T_FramebufferInstrNode& parent ,
|
|
const bool depth ,
|
|
ebcl::T_SRDToken const& texId ,
|
|
P_ExpressionNode lod = { } ) noexcept
|
|
: A_Node( TN_FBATT , &parent ) ,
|
|
depth_( depth ) ,
|
|
id_( texId.stringValue( ) )
|
|
{
|
|
location() = texId.location( );
|
|
if ( lod ) {
|
|
children_.add( NewOwned< T_ArgumentNode >(
|
|
*this , std::move( lod ) ) );
|
|
}
|
|
}
|
|
|
|
bool isDepth( ) const noexcept
|
|
{ return depth_; }
|
|
|
|
T_String const& id( ) const noexcept
|
|
{ return id_; }
|
|
|
|
T_ArgumentNode* lod( ) const noexcept
|
|
{ return (T_ArgumentNode*) ( children_.size( )
|
|
? child( 0 ).get( ) : nullptr ); }
|
|
|
|
void id( T_String const& nid ,
|
|
ebcl::T_SRDLocation const& loc ) noexcept
|
|
{
|
|
id_ = nid;
|
|
location( ) = loc;
|
|
}
|
|
};
|
|
|
|
private:
|
|
T_AutoArray< uint32_t , 16 > colorAttachments_;
|
|
T_Optional< uint32_t > depthAttachment_;
|
|
|
|
bool hasAttachment( T_String const& name ) const noexcept;
|
|
|
|
public:
|
|
T_FramebufferInstrNode( T_InstrListNode& parent ,
|
|
ebcl::T_SRDToken const& identifier ) noexcept
|
|
: A_ResourceDefInstrNode( OP_FRAMEBUFFER , parent ,
|
|
identifier , E_DataType::FRAMEBUFFER )
|
|
{ }
|
|
|
|
// ---------------------------------------------------------------------
|
|
|
|
bool addColorAttachment( ebcl::T_SRDToken const& id ,
|
|
P_ExpressionNode lod = {} ) noexcept;
|
|
|
|
uint32_t colorAttachments( ) const noexcept
|
|
{ return colorAttachments_.size( ); }
|
|
|
|
T_Attachment& colorAttachment(
|
|
const uint32_t index ) const noexcept
|
|
{ return (T_Attachment&) *child( colorAttachments_[ index ] ); }
|
|
|
|
// ---------------------------------------------------------------------
|
|
|
|
bool setDepthAttachment( ebcl::T_SRDToken const& token ,
|
|
P_ExpressionNode lod = {} ) noexcept;
|
|
|
|
T_Attachment* depthAttachment( ) const noexcept
|
|
{ return depthAttachment_
|
|
? ((T_Attachment*) child( *depthAttachment_ ).get( ) )
|
|
: nullptr; }
|
|
};
|
|
|
|
// Input declaration
|
|
class T_InputInstrNode : public A_ResourceDefInstrNode
|
|
{
|
|
private:
|
|
float defValue_;
|
|
ebcl::T_SRDLocation dvLocation_;
|
|
|
|
public:
|
|
T_InputInstrNode( T_InstrListNode& parent ,
|
|
ebcl::T_SRDToken const& tName ) noexcept
|
|
: A_ResourceDefInstrNode( OP_INPUT , parent ,
|
|
tName , E_DataType::INPUT )
|
|
{}
|
|
|
|
T_InputInstrNode( T_InstrListNode& parent ,
|
|
ebcl::T_SRDToken const& tName ,
|
|
ebcl::T_SRDToken const& tDefault ) noexcept
|
|
: A_ResourceDefInstrNode( OP_INPUT , parent ,
|
|
tName , E_DataType::INPUT ) ,
|
|
defValue_( tDefault.floatValue( ) ) , dvLocation_( tDefault.location( ) )
|
|
{}
|
|
|
|
float defValue( ) const noexcept
|
|
{ return defValue_; }
|
|
ebcl::T_SRDLocation const& defValueLocation( ) const noexcept
|
|
{ return dvLocation_; }
|
|
};
|
|
|
|
// Pipeline declaration instruction
|
|
class T_PipelineInstrNode : public A_ResourceDefInstrNode
|
|
{
|
|
private:
|
|
T_StaticArray< T_String , 6 > pids_;
|
|
T_StaticArray< ebcl::T_SRDLocation , 6 > pidLocations_;
|
|
|
|
public:
|
|
T_PipelineInstrNode(
|
|
T_InstrListNode& parent ,
|
|
ebcl::T_SRDToken const& idToken ) noexcept
|
|
: A_ResourceDefInstrNode( OP_PIPELINE , parent ,
|
|
idToken , E_DataType::PIPELINE )
|
|
{ }
|
|
|
|
// Add a program identifier. The token is assumed to be a valid word,
|
|
// and the list of programs is assumed not to be full. If the identifer
|
|
// is already in the pipeline's list, the location of the first
|
|
// occurrence will be returned.
|
|
T_Optional< ebcl::T_SRDLocation > addProgram(
|
|
ebcl::T_SRDToken const& pidToken ) noexcept;
|
|
|
|
uint32_t size( ) const noexcept
|
|
{ return pids_.size( ); }
|
|
|
|
T_String const& program( const uint32_t index ) const noexcept
|
|
{ return pids_[ index ]; }
|
|
ebcl::T_SRDLocation const& pLocation( const uint32_t index ) const noexcept
|
|
{ return pidLocations_[ index ]; }
|
|
|
|
void program( const uint32_t index ,
|
|
T_String const& id ,
|
|
ebcl::T_SRDLocation const& location ) noexcept
|
|
{
|
|
pids_[ index ] = id;
|
|
pidLocations_[ index ] = location;
|
|
}
|
|
};
|
|
|
|
// Program loader instruction
|
|
class T_ProgramInstrNode : public A_ResourceDefInstrNode
|
|
{
|
|
private:
|
|
T_FSPath path_;
|
|
ebcl::T_SRDLocation pathLocation_;
|
|
|
|
public:
|
|
T_ProgramInstrNode(
|
|
T_InstrListNode& parent ,
|
|
ebcl::T_SRDToken const& idToken ,
|
|
ebcl::T_FSPath path ,
|
|
ebcl::T_SRDLocation const& pathLoc ) noexcept
|
|
: A_ResourceDefInstrNode( OP_PROGRAM , parent ,
|
|
idToken , E_DataType::PROGRAM ) ,
|
|
path_( std::move( path ) ) ,
|
|
pathLocation_( pathLoc )
|
|
{ }
|
|
|
|
T_FSPath const& path( ) const noexcept
|
|
{ return path_; }
|
|
ebcl::T_SRDLocation const& pathLocation( ) const noexcept
|
|
{ return pathLocation_; }
|
|
};
|
|
|
|
// Sampler definition
|
|
class T_SamplerInstrNode : public A_ResourceDefInstrNode
|
|
{
|
|
private:
|
|
struct T_Sampling_
|
|
{
|
|
ebcl::T_SRDLocation location;
|
|
E_TexSampling mode;
|
|
};
|
|
|
|
struct T_Mipmaps_
|
|
{
|
|
ebcl::T_SRDLocation location;
|
|
T_Optional< E_TexSampling > mode;
|
|
};
|
|
|
|
struct T_Wrapping_
|
|
{
|
|
ebcl::T_SRDLocation location;
|
|
E_TexWrap mode;
|
|
};
|
|
|
|
struct T_LOD_
|
|
{
|
|
ebcl::T_SRDLocation location;
|
|
T_Optional< uint32_t > min;
|
|
T_Optional< uint32_t > max;
|
|
};
|
|
|
|
T_Optional< T_Sampling_ > sampling_;
|
|
T_Optional< T_Mipmaps_ > mipmaps_;
|
|
T_Optional< T_Wrapping_ > wrapping_;
|
|
T_Optional< T_LOD_ > lod_;
|
|
|
|
public:
|
|
T_SamplerInstrNode(
|
|
T_InstrListNode& parent ,
|
|
ebcl::T_SRDToken const& id ) noexcept
|
|
: A_ResourceDefInstrNode( OP_SAMPLER , parent ,
|
|
id , E_DataType::SAMPLER )
|
|
{ }
|
|
|
|
// Attempt to set sampling mode, mipmap mode, wrapping mode or
|
|
// LOD minimal/maximal, returning the location of the previous
|
|
// definition if there was one.
|
|
T_Optional< ebcl::T_SRDLocation > setSampling(
|
|
E_TexSampling mode ,
|
|
ebcl::T_SRDLocation const& location ) noexcept;
|
|
T_Optional< ebcl::T_SRDLocation > setMipmapSampling(
|
|
E_TexSampling mode ,
|
|
ebcl::T_SRDLocation const& location ) noexcept;
|
|
T_Optional< ebcl::T_SRDLocation > setNoMipmap(
|
|
ebcl::T_SRDLocation const& location ) noexcept;
|
|
T_Optional< ebcl::T_SRDLocation > setWrapping(
|
|
E_TexWrap mode ,
|
|
ebcl::T_SRDLocation const& location ) noexcept;
|
|
T_Optional< ebcl::T_SRDLocation > setLOD(
|
|
ebcl::T_SRDLocation const& location ,
|
|
P_ExpressionNode min ,
|
|
P_ExpressionNode max ) noexcept;
|
|
|
|
// Get either the defined values or the defaults
|
|
E_TexSampling sampling( ) const noexcept
|
|
{ return sampling_ ? sampling_->mode : E_TexSampling::NEAREST; }
|
|
T_Optional< E_TexSampling > mipmap( ) const noexcept
|
|
{ return mipmaps_ ? mipmaps_->mode : T_Optional< E_TexSampling >{}; }
|
|
E_TexWrap wrapping( ) const noexcept
|
|
{ return wrapping_ ? wrapping_->mode : E_TexWrap::REPEAT; }
|
|
|
|
T_ArgumentNode* minLod( ) const noexcept
|
|
{ return ( T_ArgumentNode*) ( ( lod_ && lod_->min )
|
|
? child( *( lod_->min ) ).get( )
|
|
: nullptr ); }
|
|
T_ArgumentNode* maxLod( ) const noexcept
|
|
{ return ( T_ArgumentNode*) ( ( lod_ && lod_->max )
|
|
? child( *( lod_->max ) ).get( )
|
|
: nullptr ); }
|
|
};
|
|
|
|
// Texture definition
|
|
class T_TextureInstrNode : public A_ResourceDefInstrNode
|
|
{
|
|
private:
|
|
E_TexType type_;
|
|
|
|
public:
|
|
T_TextureInstrNode(
|
|
T_InstrListNode& parent ,
|
|
ebcl::T_SRDToken const& id ,
|
|
E_TexType type ) noexcept
|
|
: A_ResourceDefInstrNode( OP_TEXTURE , parent ,
|
|
id , E_DataType::TEXTURE ) ,
|
|
type_( type )
|
|
{
|
|
children_.add( P_ArgumentNode{} );
|
|
children_.add( P_ArgumentNode{} );
|
|
children_.add( P_ArgumentNode{} );
|
|
}
|
|
|
|
E_TexType texType( ) const noexcept
|
|
{ return type_; }
|
|
|
|
void setWidth( P_ExpressionNode width ) noexcept
|
|
{
|
|
if ( width ) {
|
|
child( 0 ) = NewOwned< T_ArgumentNode >(
|
|
*this , std::move( width ) );
|
|
}
|
|
}
|
|
|
|
void setHeight( P_ExpressionNode height ) noexcept
|
|
{
|
|
if ( height ) {
|
|
child( 1 ) = NewOwned< T_ArgumentNode >(
|
|
*this , std::move( height ) );
|
|
}
|
|
}
|
|
|
|
void setLODs( P_ExpressionNode lods ) noexcept
|
|
{
|
|
if ( lods ) {
|
|
child( 2 ) = NewOwned< T_ArgumentNode >(
|
|
*this , std::move( lods ) );
|
|
}
|
|
}
|
|
|
|
bool hasWidth( ) const noexcept
|
|
{ return bool( child( 0 ) ); }
|
|
T_ArgumentNode& width( ) const noexcept
|
|
{ return (T_ArgumentNode&) *child( 0 ); }
|
|
|
|
bool hasHeight( ) const noexcept
|
|
{ return bool( child( 1 ) ); }
|
|
T_ArgumentNode& height( ) const noexcept
|
|
{ return (T_ArgumentNode&) *child( 1 ); }
|
|
|
|
T_ArgumentNode* lods( ) const noexcept
|
|
{ return (T_ArgumentNode*) child( 2 ).get( ); }
|
|
};
|
|
|
|
|
|
/*= TOOL CONTROL INSTRUCTIONS ==================================================*/
|
|
|
|
// Output debugging
|
|
class T_OutputDebugInstrNode : public A_InstructionNode
|
|
{
|
|
private:
|
|
T_String idTexture_;
|
|
ebcl::T_SRDLocation locTexture_;
|
|
E_ODbgMode mode_;
|
|
ebcl::T_SRDLocation locMode_;
|
|
T_String description_;
|
|
ebcl::T_SRDLocation locDescription_;
|
|
|
|
public:
|
|
T_OutputDebugInstrNode(
|
|
T_InstrListNode& parent ,
|
|
ebcl::T_SRDToken const& texture ,
|
|
const E_ODbgMode mode ,
|
|
ebcl::T_SRDLocation const& modeLocation ,
|
|
ebcl::T_SRDToken const& description ) noexcept;
|
|
|
|
T_String const& texture( ) const noexcept
|
|
{ return idTexture_; }
|
|
ebcl::T_SRDLocation const& textureLocation( ) const noexcept
|
|
{ return locTexture_; }
|
|
|
|
E_ODbgMode mode( ) const noexcept
|
|
{ return mode_; }
|
|
ebcl::T_SRDLocation const& modeLocation( ) const noexcept
|
|
{ return locMode_; }
|
|
|
|
T_String const& description( ) const noexcept
|
|
{ return description_; }
|
|
ebcl::T_SRDLocation const& descriptionLocation( ) const noexcept
|
|
{ return locDescription_; }
|
|
};
|
|
|
|
// User interface overrides for inputs
|
|
class T_OverridesInstrNode : public A_InstructionNode
|
|
{
|
|
private:
|
|
T_OwnPtr< T_SyncOverrideSection > overrides_;
|
|
|
|
public:
|
|
T_OverridesInstrNode(
|
|
T_InstrListNode& parent ,
|
|
T_OwnPtr< T_SyncOverrideSection > overrides ) noexcept
|
|
: A_InstructionNode( OP_OVERRIDES , parent , E_InstrRestriction::FRAME ) ,
|
|
overrides_( std::move( overrides ) )
|
|
{ }
|
|
|
|
T_SyncOverrideSection& root( ) const noexcept
|
|
{ return *overrides_; }
|
|
|
|
T_OwnPtr< T_SyncOverrideSection > extractRoot( ) noexcept
|
|
{ return std::move( overrides_ ); }
|
|
};
|
|
|
|
// Profiling instruction
|
|
class T_ProfileInstrNode : public A_InstructionNode
|
|
{
|
|
private:
|
|
T_String text_;
|
|
|
|
public:
|
|
T_ProfileInstrNode(
|
|
T_InstrListNode& parent ,
|
|
T_String const& text ) noexcept
|
|
: A_InstructionNode( OP_PROFILE , parent , E_InstrRestriction::INIT ) ,
|
|
text_( text )
|
|
{
|
|
children_.add( NewOwned< T_InstrListNode >( *this ) );
|
|
}
|
|
|
|
T_String const& text( ) const
|
|
{ return text_; }
|
|
|
|
T_InstrListNode& instructions( ) const noexcept
|
|
{ return (T_InstrListNode&) *child( 0 ); }
|
|
};
|
|
|
|
|
|
/*= RENDERING INSTRUCTIONS =====================================================*/
|
|
|
|
// Clear instruction
|
|
class T_ClearInstrNode : public A_InstructionNode
|
|
{
|
|
public:
|
|
T_ClearInstrNode( T_InstrListNode& parent ) noexcept
|
|
: A_InstructionNode( OP_CLEAR , parent ,
|
|
E_InstrRestriction::INIT )
|
|
{ }
|
|
|
|
void addComponent( P_ExpressionNode expr ) noexcept
|
|
{
|
|
if ( expr ) {
|
|
children_.add( NewOwned< T_ArgumentNode >(
|
|
*this , std::move( expr ) ) );
|
|
}
|
|
}
|
|
|
|
T_ArgumentNode& component( const uint32_t index ) const noexcept
|
|
{ return (T_ArgumentNode&) *child( index ); }
|
|
};
|
|
|
|
// Fullscreen quad instruction
|
|
class T_FullscreenInstrNode : public A_InstructionNode
|
|
{
|
|
public:
|
|
T_FullscreenInstrNode( T_InstrListNode& parent ) noexcept
|
|
: A_InstructionNode( OP_FULLSCREEN , parent , E_InstrRestriction::INIT )
|
|
{ }
|
|
};
|
|
|
|
// Dispatch a compute job
|
|
class T_ComputeInstrNode : public A_InstructionNode
|
|
{
|
|
public:
|
|
T_ComputeInstrNode( T_InstrListNode& parent ) noexcept
|
|
: A_InstructionNode( OP_COMPUTE , parent )
|
|
{ }
|
|
|
|
void addComponent( P_ExpressionNode expr ) noexcept
|
|
{
|
|
if ( expr ) {
|
|
children_.add( NewOwned< T_ArgumentNode >(
|
|
*this , std::move( expr ) ) );
|
|
}
|
|
}
|
|
|
|
T_ArgumentNode& component( const uint32_t index ) const noexcept
|
|
{ return (T_ArgumentNode&) *child( index ); }
|
|
};
|
|
|
|
|
|
/*= RENDERING STATE INSTRUCTIONS ===============================================*/
|
|
|
|
// Main output selection
|
|
class T_MainOutputInstrNode : public A_InstructionNode
|
|
{
|
|
public:
|
|
T_MainOutputInstrNode( T_InstrListNode& parent ) noexcept
|
|
: A_InstructionNode( OP_MAINOUT , parent , E_InstrRestriction::INIT )
|
|
{ }
|
|
};
|
|
|
|
// Uniform setting instruction
|
|
class T_UniformsInstrNode : public A_InstructionNode
|
|
{
|
|
private:
|
|
bool integers_;
|
|
T_String progId_;
|
|
ebcl::T_SRDLocation progIdLocation_;
|
|
uint32_t uloc_;
|
|
ebcl::T_SRDLocation ulocLocation_;
|
|
|
|
public:
|
|
T_UniformsInstrNode( T_InstrListNode& parent ,
|
|
const bool integers ,
|
|
ebcl::T_SRDToken const& prog ,
|
|
ebcl::T_SRDToken const& loc ) noexcept
|
|
: A_InstructionNode{ OP_UNIFORMS , parent } , integers_{ integers } ,
|
|
progId_{ prog.stringValue( ) } , progIdLocation_{ prog.location( ) } ,
|
|
uloc_{ (uint32_t)loc.longValue( ) } , ulocLocation_{ loc.location( ) }
|
|
{ }
|
|
|
|
bool integers( ) const noexcept
|
|
{ return integers_; }
|
|
|
|
T_String const& progId( ) const noexcept
|
|
{ return progId_; }
|
|
ebcl::T_SRDLocation const& progIdLocation( ) const noexcept
|
|
{ return progIdLocation_; }
|
|
void progId( T_String const& id ,
|
|
ebcl::T_SRDLocation const& location ) noexcept
|
|
{ progId_ = id; progIdLocation_ = location; }
|
|
|
|
uint32_t uloc( ) const noexcept
|
|
{ return uloc_; }
|
|
ebcl::T_SRDLocation const& ulocLocation( ) const noexcept
|
|
{ return ulocLocation_; }
|
|
|
|
void addValue( P_ExpressionNode value ) noexcept
|
|
{
|
|
if ( value ) {
|
|
children_.add( NewOwned< T_ArgumentNode >(
|
|
*this , std::move( value ) ) );
|
|
}
|
|
}
|
|
|
|
T_ArgumentNode& value( const uint32_t index ) const noexcept
|
|
{ return (T_ArgumentNode&) *child( index ); }
|
|
};
|
|
|
|
// Use-* instructions (framebuffers, programs, pipelines)
|
|
// Also serves as the base for use-texture
|
|
class T_UseInstrNode : public A_InstructionNode
|
|
{
|
|
public:
|
|
enum E_Type {
|
|
FRAMEBUFFER , PIPELINE , PROGRAM , TEXTURE
|
|
};
|
|
|
|
private:
|
|
T_String id_;
|
|
ebcl::T_SRDLocation idLocation_;
|
|
|
|
public:
|
|
T_UseInstrNode( T_InstrListNode& parent ,
|
|
const E_Type type ,
|
|
ebcl::T_SRDToken const& identifier ) noexcept
|
|
: A_InstructionNode( ([type]() {
|
|
switch ( type ) {
|
|
case FRAMEBUFFER: return OP_USE_FRAMEBUFFER;
|
|
case PIPELINE: return OP_USE_PIPELINE;
|
|
case PROGRAM: return OP_USE_PROGRAM;
|
|
case TEXTURE: return OP_USE_TEXTURE;
|
|
}
|
|
std::abort( );
|
|
} )( ) , parent ) ,
|
|
id_( identifier.stringValue( ) ) ,
|
|
idLocation_( identifier.location( ) )
|
|
{ }
|
|
|
|
T_String const& id( ) const noexcept
|
|
{ return id_; }
|
|
ebcl::T_SRDLocation const& idLocation( ) const noexcept
|
|
{ return idLocation_; }
|
|
void id( T_String const& nid ,
|
|
ebcl::T_SRDLocation const& location ) noexcept
|
|
{ id_ = nid; idLocation_ = location; }
|
|
};
|
|
|
|
// Texture/sampler use instructions
|
|
class T_UseTextureInstrNode : public T_UseInstrNode
|
|
{
|
|
private:
|
|
uint32_t bank_;
|
|
ebcl::T_SRDLocation bankLocation_;
|
|
T_String samplerId_;
|
|
ebcl::T_SRDLocation samplerIdLocation_;
|
|
|
|
public:
|
|
T_UseTextureInstrNode( T_InstrListNode& parent ,
|
|
ebcl::T_SRDToken const& bank ,
|
|
ebcl::T_SRDToken const& identifier ,
|
|
ebcl::T_SRDToken const& sampler ) noexcept
|
|
: T_UseInstrNode( parent , TEXTURE , identifier ) ,
|
|
bank_( bank.longValue( ) ) ,
|
|
bankLocation_( bank.location( ) ) ,
|
|
samplerId_( sampler.stringValue( ) ) ,
|
|
samplerIdLocation_( sampler.location( ) )
|
|
{ }
|
|
|
|
uint32_t bank( ) const noexcept
|
|
{ return bank_; }
|
|
ebcl::T_SRDLocation const& bankLocation( ) const noexcept
|
|
{ return bankLocation_; }
|
|
|
|
T_String const& samplerId( ) const noexcept
|
|
{ return samplerId_; }
|
|
ebcl::T_SRDLocation const& samplerIdLocation( ) const noexcept
|
|
{ return samplerIdLocation_; }
|
|
void samplerId( T_String const& id ,
|
|
ebcl::T_SRDLocation const& location ) noexcept
|
|
{ samplerId_ = id; samplerIdLocation_ = location; }
|
|
};
|
|
|
|
// Viewport instruction
|
|
class T_ViewportInstrNode : public A_InstructionNode
|
|
{
|
|
public:
|
|
enum E_Parameter {
|
|
PX , PY , PWIDTH , PHEIGHT
|
|
};
|
|
|
|
public:
|
|
T_ViewportInstrNode( T_InstrListNode& parent ) noexcept
|
|
: A_InstructionNode( OP_VIEWPORT , parent ,
|
|
E_InstrRestriction::INIT )
|
|
{
|
|
children_.add( P_ArgumentNode{} );
|
|
children_.add( P_ArgumentNode{} );
|
|
children_.add( P_ArgumentNode{} );
|
|
children_.add( P_ArgumentNode{} );
|
|
}
|
|
|
|
void setParameter( const E_Parameter p , P_ExpressionNode value ) noexcept
|
|
{
|
|
if ( value ) {
|
|
children_[ int( p ) ] = NewOwned< T_ArgumentNode >(
|
|
*this , std::move( value ) );
|
|
}
|
|
}
|
|
|
|
bool hasParameter( const E_Parameter p ) const noexcept
|
|
{ return bool( children_[ int( p ) ] ); }
|
|
T_ArgumentNode& parameter( const E_Parameter p ) const noexcept
|
|
{ return (T_ArgumentNode&) *children_[ int( p ) ]; }
|
|
};
|
|
|
|
// Image unit binding
|
|
class T_ImageInstrNode : public A_InstructionNode
|
|
{
|
|
public:
|
|
enum class E_AccessMode
|
|
{
|
|
READ ,
|
|
WRITE
|
|
};
|
|
using T_AccessMode = T_Flags< E_AccessMode >;
|
|
|
|
enum E_Parameter {
|
|
P_UNIT , P_LEVEL , P_LAYER
|
|
};
|
|
|
|
private:
|
|
T_AccessMode accessMode_ = { };
|
|
T_String id_;
|
|
ebcl::T_SRDLocation idLocation_;
|
|
|
|
public:
|
|
T_ImageInstrNode( T_InstrListNode& parent ) noexcept
|
|
: A_InstructionNode( OP_IMAGE , parent )
|
|
{
|
|
children_.add( P_ArgumentNode{} );
|
|
children_.add( P_ArgumentNode{} );
|
|
children_.add( P_ArgumentNode{} );
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
T_String const& id( ) const noexcept
|
|
{ return id_; }
|
|
ebcl::T_SRDLocation const& idLocation( ) const noexcept
|
|
{ return idLocation_; }
|
|
void id( T_String const& nid ,
|
|
ebcl::T_SRDLocation const& location ) noexcept
|
|
{ id_ = nid; idLocation_ = location; }
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
T_AccessMode accessMode( ) const noexcept
|
|
{ return accessMode_; }
|
|
void accessMode( T_AccessMode mode ) noexcept
|
|
{ assert( mode ); accessMode_ = mode; }
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void setParameter( const E_Parameter p ,
|
|
P_ExpressionNode value ) noexcept
|
|
{
|
|
if ( value ) {
|
|
children_[ int( p ) ] = NewOwned< T_ArgumentNode >(
|
|
*this , std::move( value ) );
|
|
}
|
|
}
|
|
|
|
bool hasParameter( const E_Parameter p ) const noexcept
|
|
{ return bool( children_[ int( p ) ] ); }
|
|
T_ArgumentNode& parameter( const E_Parameter p ) const noexcept
|
|
{ return (T_ArgumentNode&) *children_[ int( p ) ]; }
|
|
};
|
|
|
|
|
|
/*= EXPRESSIONS ==============================================================*/
|
|
|
|
// A constant value
|
|
class T_ConstantExprNode : public A_ExpressionNode
|
|
{
|
|
private:
|
|
bool wasFloat_;
|
|
double vFloat_;
|
|
int64_t vInt_;
|
|
|
|
public:
|
|
T_ConstantExprNode( A_Node& parent ,
|
|
ebcl::T_SRDToken const& token ) noexcept
|
|
: A_ExpressionNode( EXPR_CONST , parent ) ,
|
|
wasFloat_( token.type( ) == ebcl::E_SRDTokenType::FLOAT ) ,
|
|
vFloat_( token.floatValue( ) ) ,
|
|
vInt_( token.longValue( ) )
|
|
{ location( ) = token.location( ); }
|
|
|
|
T_ConstantExprNode( A_Node& parent ,
|
|
int64_t value ) noexcept
|
|
: A_ExpressionNode( EXPR_CONST , parent ) , wasFloat_( false ) ,
|
|
vFloat_( value ) , vInt_( value )
|
|
{ }
|
|
|
|
T_ConstantExprNode( A_Node& parent ,
|
|
double value ) noexcept
|
|
: A_ExpressionNode( EXPR_CONST , parent ) , wasFloat_( true ) ,
|
|
vFloat_( value ) , vInt_( (int64_t) value )
|
|
{ }
|
|
|
|
bool wasFloat( ) const noexcept
|
|
{ return wasFloat_; }
|
|
double floatValue( ) const noexcept
|
|
{ return vFloat_; }
|
|
int64_t intValue( ) const noexcept
|
|
{ return vInt_; }
|
|
};
|
|
|
|
// An identifier used in an expression
|
|
class T_IdentifierExprNode : public A_ExpressionNode
|
|
{
|
|
private:
|
|
T_String id_;
|
|
|
|
public:
|
|
T_IdentifierExprNode( A_Node& parent ,
|
|
ebcl::T_SRDToken const& token ) noexcept
|
|
: T_IdentifierExprNode( parent , token.stringValue( ) )
|
|
{ location( ) = token.location( ); }
|
|
|
|
T_IdentifierExprNode( A_Node& parent ,
|
|
T_String const& id ) noexcept
|
|
: A_ExpressionNode( EXPR_ID , parent ) , id_( id )
|
|
{ }
|
|
|
|
T_String const& id( ) const noexcept
|
|
{ return id_; }
|
|
};
|
|
|
|
// Access to an input value
|
|
class T_InputExprNode : public A_ExpressionNode
|
|
{
|
|
private:
|
|
T_String id_;
|
|
ebcl::T_SRDLocation idLocation_;
|
|
|
|
public:
|
|
T_InputExprNode( A_Node& parent ,
|
|
ebcl::T_SRDToken const& token ) noexcept
|
|
: A_ExpressionNode( EXPR_INPUT , parent ) ,
|
|
id_( token.stringValue( ) ) ,
|
|
idLocation_( token.location( ) )
|
|
{ }
|
|
|
|
T_String const& id( ) const noexcept
|
|
{ return id_; }
|
|
ebcl::T_SRDLocation const& idLocation( ) const noexcept
|
|
{ return idLocation_; }
|
|
};
|
|
|
|
// A unary operator
|
|
class T_UnaryOperatorNode : public A_ExpressionNode
|
|
{
|
|
public:
|
|
enum E_Operator {
|
|
NEG , INV , NOT ,
|
|
SIN , COS , TAN ,
|
|
SQRT , EXP , LN
|
|
};
|
|
|
|
private:
|
|
E_Operator op_;
|
|
|
|
public:
|
|
T_UnaryOperatorNode(
|
|
A_Node& parent ,
|
|
const E_Operator op ) noexcept;
|
|
|
|
E_Operator op( ) const noexcept
|
|
{ return op_; }
|
|
|
|
void setArgument( P_ExpressionNode argument ) noexcept
|
|
{ child( 0 ) = std::move( argument ); }
|
|
|
|
bool hasArgument( ) const noexcept
|
|
{ return bool( child( 0 ) ); }
|
|
|
|
A_ExpressionNode& argument( ) const noexcept
|
|
{ return (A_ExpressionNode&) *child( 0 ); }
|
|
};
|
|
|
|
// A binary operator
|
|
class T_BinaryOperatorNode : public A_ExpressionNode
|
|
{
|
|
public:
|
|
enum E_Operator {
|
|
ADD , SUB ,
|
|
MUL , DIV ,
|
|
POW ,
|
|
|
|
CMP_EQ , CMP_NE ,
|
|
CMP_GT , CMP_GE ,
|
|
CMP_LT , CMP_LE ,
|
|
};
|
|
|
|
private:
|
|
E_Operator op_;
|
|
|
|
public:
|
|
T_BinaryOperatorNode(
|
|
A_Node& parent ,
|
|
const E_Operator op ) noexcept;
|
|
|
|
E_Operator op( ) const noexcept
|
|
{ return op_; }
|
|
|
|
void setLeft( P_ExpressionNode left ) noexcept
|
|
{ child( 0 ) = std::move( left ); }
|
|
void setRight( P_ExpressionNode right ) noexcept
|
|
{ child( 1 ) = std::move( right ); }
|
|
|
|
bool hasLeft( ) const noexcept
|
|
{ return bool( child( 0 ) ); }
|
|
bool hasRight( ) const noexcept
|
|
{ return bool( child( 1 ) ); }
|
|
|
|
A_ExpressionNode& left( ) const noexcept
|
|
{ return (A_ExpressionNode&) *child( 0 ); }
|
|
A_ExpressionNode& right( ) const noexcept
|
|
{ return (A_ExpressionNode&) *child( 1 ); }
|
|
};
|
|
|
|
|
|
} // namespace opast
|