Parser - Various new instructions implemented

This commit is contained in:
Emmanuel BENOîT 2017-11-09 18:24:39 +01:00
parent c9155abd12
commit 9cf7d8c434
3 changed files with 421 additions and 43 deletions

149
demo.srd
View file

@ -1,27 +1,82 @@
(init
# Compute viewport size
(if (gt width height)
(if (cmp-gt width height)
(
(set vp-height height)
(set vp-width (mul height (div 16 9)))
(set vp-x (div (sub width vp-width) 2))
(set vp-height $height)
(set vp-width (mul $height (div 16 9)))
(set vp-x (div (sub $width $vp-width) 2))
(set vp-y 0)
)(
(set vp-width width)
(set vp-height (div width (div 16 9)))
(set vp-y (div (sub height vp-height) 2))
(set vp-width $width)
(set vp-height (div $width (div 16 9)))
(set vp-y (div (sub $height $vp-height) 2))
(set vp-x 0)
)
)
(program prg-fullscreen "fullscreen.v.glsl")
(call scene-init)
(call dof-init)
)
(frame
(profiling "Frame render"
{ FIXME: other stages }
(call dof-main { FIXME: args here })
(call scene-main)
(call dof-main tx-scene-output tx-scene-depth)
)
)
################################################################################
# Scene
(fn scene-init ()
(texture tx-scene-output rgb-f16 vp-width vp-height)
(texture tx-scene-depth r-f16 vp-width vp-height)
{ NOT IMPLEMENTED
(framebuffer rt-scene
(colors tx-scene-output tx-scene-depth))
}
(program prg-scene-p1 "scene.f.glsl")
# NOT IMPLEMENTED (set-uniforms prg-scene-p1 1 $vp-width $vp-height)
(pipeline pl-scene-p1 prg-fullscreen prg-scene-p1)
{ NOT IMPLEMENTED
(odbg tx-scene-output hdr "Scene output")
(odbg tx-scene-depth depth "Scene depth")
}
)
(fn scene-main ()
(profiling "Scene render"
{ NOT IMPLEMENTED
(set-uniforms prg-scene-p1 0 $time)
(set-uniforms prg-scene-p1 2
(get-input "camera-pos-x")
(get-input "camera-pos-y")
(get-input "camera-pos-z")
)
(set-uniforms prg-scene-p1 3
(get-input "camera-lookat-x")
(get-input "camera-lookat-y")
(get-input "camera-lookat-z")
)
(set-uniforms prg-scene-p1 4
(get-input "camera-up-x")
(get-input "camera-up-y")
(get-input "camera-up-z")
)
(set-uniforms prg-scene-p1 5
(get-input "camera-nearplane")
)
# FIXME MOAR UNIFORMS!
(use-pipeline pl-scene-p1)
(use-framebuffer rt-scene)
}
(viewport 0 0 $vp-width $vp-height)
(fullscreen)
)
)
@ -30,33 +85,43 @@
(fn dof-init ()
# Sampler used for the inputs
(sampler dof-sampler
(mipmaps no)
(wrapping clamp-edge)
(sampling linear)
(lod 0 0)
)
{ NOT IMPLEMENTED
(sampler dof-sampler
(mipmaps no)
(wrapping clamp-edge)
(sampling linear)
(lod 0 0)
)
}
# Texture & RT for pass 1
(texture tx-dof-pass1 rgb-f16 vp-width vp-height)
(framebuffer rt-dof-pass1 (colors tx-dof-pass1))
{ NOT IMPLEMENTED
(framebuffer rt-dof-pass1 (colors tx-dof-pass1))
}
# Texture & RT for pass 2
(texture tx-dof-pass2 rgb-f16 vp-width vp-height)
(framebuffer rt-dof-pass2 (colors tx-dof-pass2))
(alias tx-dof-output tx-dof-pass2)
{ NOT IMPLEMENTED
(framebuffer rt-dof-pass2 (colors tx-dof-pass2))
}
# MAYBE ? (alias tx-dof-output tx-dof-pass2)
# Output debugging
(odbg tx-dof-pass1 hdr "DoF - First pass")
(odbg tx-dof-pass2 hdr "DoF - Output")
{ NOT IMPLEMENTED
(odbg tx-dof-pass1 hdr "DoF - First pass")
(odbg tx-dof-pass2 hdr "DoF - Output")
}
# Programs
(program prg-dof-pass1 "dof-pass1.f.glsl")
(program prg-dof-pass2 "dof-pass2.f.glsl")
(set-uniforms-integer prg-dof-pass1 0 1)
(set-uniforms-integer prg-dof-pass1 1 1)
(set-uniforms-integer prg-dof-pass2 0 1)
(set-uniforms-integer prg-dof-pass2 1 1)
{ NOT IMPLEMENTED
(set-uniforms-integer prg-dof-pass1 0 1)
(set-uniforms-integer prg-dof-pass1 1 1)
(set-uniforms-integer prg-dof-pass2 0 1)
(set-uniforms-integer prg-dof-pass2 1 1)
}
# Pipelines
(pipeline pl-dof-pass1 prg-fullscreen prg-dof-pass1)
@ -70,24 +135,28 @@
(input dof-samples 16)
# Input overrides
(ui-overrides "Post-processing" "Depth of Field"
(float dof-sharp-distance (min 0) (max 1000) (step .1))
(float dof-sharp-range (min 0) (max 500) (step .1))
(float dof-falloff (min 0) (max 500) (step .1))
(float dof-max-blur (min 1) (max 64) (step .1))
(int dof-samples (min 1) (max 64) (step .1))
)
{ NOT IMPLEMENTED
(ui-overrides "Post-processing" "Depth of Field"
(float dof-sharp-distance (min 0) (max 1000) (step .1))
(float dof-sharp-range (min 0) (max 500) (step .1))
(float dof-falloff (min 0) (max 500) (step .1))
(float dof-max-blur (min 1) (max 64) (step .1))
(int dof-samples (min 1) (max 64) (step .1))
)
}
)
(fn dof-set-uniforms (prog)
(set-uniforms prog 2 (
(get-input dof-sharp-distance)
(get-input dof-sharp-range)
(get-input dof-falloff)
(get-input dof-max-blur)
))
(set-uniforms prog 3 ((get-input dof-samples)))
(set-uniforms prog 4 (vp-width vp-height time))
{ NOT IMPLEMENTED
(set-uniforms prog 2
(get-input dof-sharp-distance)
(get-input dof-sharp-range)
(get-input dof-falloff)
(get-input dof-max-blur)
)
(set-uniforms prog 3 (get-input dof-samples))
(set-uniforms prog 4 $vp-width $vp-height $time)
}
)
(fn dof-main (in-image in-depth)
@ -104,8 +173,10 @@
# Second pass
(call dof-set-uniforms prg-dof-pass2)
(use-texture 0 tx-dof-pass1 dof-sampler)
(use-pipeline pl-dof-pass2)
(use-framebuffer rt-dof-pass2)
(viewport 0 0 $vp-width $vp-height)
(fullscreen)
)
)

163
opast.cc
View file

@ -97,8 +97,11 @@ A_Node* opast::ASTVisitorBrowser(
// Nodes that do not have children
case A_Node::EXPR_ID: case A_Node::EXPR_CONST:
case A_Node::EXPR_INPUT:
case A_Node::OP_PROGRAM: case A_Node::OP_PIPELINE:
case A_Node::OP_INPUT:
case A_Node::OP_INPUT: case A_Node::OP_FULLSCREEN:
case A_Node::OP_USE_FRAMEBUFFER: case A_Node::OP_USE_PIPELINE:
case A_Node::OP_USE_PROGRAM: case A_Node::OP_USE_TEXTURE:
break;
// Profile instruction
@ -168,6 +171,24 @@ A_Node* opast::ASTVisitorBrowser(
break;
}
// 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;
}
}
return nullptr;
}
@ -314,6 +335,7 @@ struct T_ParserImpl_
{
enum class E_InstrType {
CALL ,
FULLSCREEN ,
IF ,
INPUT ,
PIPELINE ,
@ -321,6 +343,11 @@ struct T_ParserImpl_
PROGRAM ,
SET ,
TEXTURE ,
USE_FRAMEBUFFER ,
USE_PIPELINE ,
USE_PROGRAM ,
USE_TEXTURE ,
VIEWPORT ,
};
const T_KeyValueTable< T_String , E_InstrType > instrMap{ ([]() {
@ -330,6 +357,7 @@ struct T_ParserImpl_
} };
add( "call" , E_InstrType::CALL );
add( "fullscreen" , E_InstrType::FULLSCREEN );
add( "if" , E_InstrType::IF );
add( "input" , E_InstrType::INPUT );
add( "pipeline" , E_InstrType::PIPELINE );
@ -337,6 +365,11 @@ struct T_ParserImpl_
add( "program" , E_InstrType::PROGRAM );
add( "set" , E_InstrType::SET );
add( "texture" , E_InstrType::TEXTURE );
add( "use-framebuffer" , E_InstrType::USE_FRAMEBUFFER );
add( "use-pipeline" , E_InstrType::USE_PIPELINE );
add( "use-program" , E_InstrType::USE_PROGRAM );
add( "use-texture" , E_InstrType::USE_TEXTURE );
add( "viewport" , E_InstrType::VIEWPORT );
return temp;
})( ) };
@ -451,6 +484,15 @@ struct T_ParserImpl_
M_DPARSER_( Program );
M_DPARSER_( Set );
M_DPARSER_( Texture );
M_DPARSER_( UseFramebuffer );
M_DPARSER_( UsePipeline );
M_DPARSER_( UseProgram );
void parseUseCommon(
T_InstrListNode& instructions ,
T_SRDList const& input ,
T_UseInstrNode::E_Type type ) noexcept;
M_DPARSER_( UseTexture );
M_DPARSER_( Viewport );
#undef M_DPARSER_
@ -711,6 +753,15 @@ void T_ParserImpl_::parseInstructions(
M_CASE_( PROGRAM , Program );
M_CASE_( SET , Set );
M_CASE_( TEXTURE , Texture );
M_CASE_( USE_FRAMEBUFFER , UseFramebuffer );
M_CASE_( USE_PIPELINE , UsePipeline );
M_CASE_( USE_PROGRAM , UseProgram );
M_CASE_( USE_TEXTURE , UseTexture );
M_CASE_( VIEWPORT , Viewport );
case E_InstrType::FULLSCREEN:
instructions.add< T_FullscreenInstrNode >( ).location( ) = iname.location( );
break;
}
#undef M_CASE_
}
@ -983,6 +1034,102 @@ M_INSTR_( Texture )
/*----------------------------------------------------------------------------*/
M_INSTR_( UseFramebuffer )
{
parseUseCommon( instructions , input , T_UseInstrNode::FRAMEBUFFER );
}
M_INSTR_( UsePipeline )
{
parseUseCommon( instructions , input , T_UseInstrNode::PIPELINE );
}
M_INSTR_( UseProgram )
{
parseUseCommon( instructions , input , T_UseInstrNode::PROGRAM );
}
void T_ParserImpl_::parseUseCommon(
T_InstrListNode& instructions ,
T_SRDList const& input ,
T_UseInstrNode::E_Type type ) noexcept
{
if ( input.size( ) == 1 || input[ 1 ].type( ) != E_SRDTokenType::WORD ) {
errors.addNew( "resource identifier expected" ,
input[ input.size( ) == 1 ? 0 : 1 ].location( ) );
return;
}
if ( input.size( ) > 2 ) {
errors.addNew( "too many arguments" , input[ 2 ].location( ) );
}
auto& instr{ instructions.add< T_UseInstrNode >( type , input[ 1 ] ) };
instr.location( ) = input[ 0 ].location( );
}
/*----------------------------------------------------------------------------*/
M_INSTR_( UseTexture )
{
if ( input.size( ) == 1 || !input[ 1 ].isInteger( ) ) {
errors.addNew( "bank number expected" ,
input[ input.size( ) == 1 ? 0 : 1 ].location( ) );
return;
}
if ( input[ 1 ].longValue( ) < 0 || input[ 1 ].longValue( ) > UINT32_MAX ) {
errors.addNew( "invalid bank number" , input[ 1 ].location( ) );
return;
}
if ( input.size( ) == 2 || input[ 2 ].type( ) != E_SRDTokenType::WORD ) {
errors.addNew( "texture identifier expected" ,
input[ input.size( ) == 2 ? 0 : 2 ].location( ) );
return;
}
if ( input.size( ) == 3 || input[ 3 ].type( ) != E_SRDTokenType::WORD ) {
errors.addNew( "sampler identifier expected" ,
input[ input.size( ) == 3 ? 0 : 3 ].location( ) );
return;
}
if ( input.size( ) > 4 ) {
errors.addNew( "too many arguments" , input[ 4 ].location( ) );
}
auto& instr{ instructions.add< T_UseTextureInstrNode >(
input[ 1 ] , input[ 2 ] , input[ 3 ] ) };
instr.location( ) = input[ 0 ].location( );
}
/*----------------------------------------------------------------------------*/
M_INSTR_( Viewport )
{
auto& instr{ instructions.add< T_ViewportInstrNode >( ) };
instr.location( ) = input[ 0 ].location( );
for ( auto i = 1u ; i < 5 ; i ++ ) {
T_ViewportInstrNode::E_Parameter p{
T_ViewportInstrNode::E_Parameter( i ) };
if ( input.size( ) < i ) {
T_StringBuilder sb;
sb << "missing ";
switch ( p ) {
case T_ViewportInstrNode::PX: sb << "X"; break;
case T_ViewportInstrNode::PY: sb << "Y"; break;
case T_ViewportInstrNode::PWIDTH: sb << "width"; break;
case T_ViewportInstrNode::PHEIGHT: sb << "height"; break;
}
sb << " parameter";
errors.addNew( std::move( sb ) , input[ 0 ].location( ) );
return;
} else {
instr.setParameter( p , parseExpression( instr , input[ i ] ) );
}
}
}
/*----------------------------------------------------------------------------*/
P_ExpressionNode T_ParserImpl_::parseExpression(
A_Node& parent ,
T_SRDToken const& token ) noexcept
@ -1012,6 +1159,20 @@ P_ExpressionNode T_ParserImpl_::parseOperation(
return {};
}
if ( opId.stringValue( ) == "get-input" ) {
if ( opList.size( ) == 1 || !opList[ 1 ].isText( ) ) {
errors.addNew( "input identifier expected" ,
opList[ opList.size( ) == 1 ? 0 : 1 ].location( ) );
return { };
}
if ( opList.size( ) > 2 ) {
errors.addNew( "too many arguments" , opList[ 2 ].location( ) );
}
auto node{ NewOwned< T_InputExprNode >( parent , opList[ 1 ] ) };
node->location( ) = opList[ 0 ].location( );
return node;
}
if ( binOpMap.contains( opId.stringValue( ) ) ) {
return parseBinOp( parent , opList ,
*binOpMap.get( opId.stringValue( ) ) );

152
opast.hh
View file

@ -25,12 +25,19 @@ class A_Node
//
OP_CALL , // Function call
OP_COND , // Conditional instruction
OP_FULLSCREEN , // Draw a fullscreen quad
OP_INPUT , // Input declaration
OP_PIPELINE , // Shader pipeline declaration
OP_PROFILE , // Profiling block
OP_PROGRAM , // Shader program declaration
OP_SET , // Set instruction
OP_TEXTURE , // Define texture
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 ,
@ -45,6 +52,7 @@ class A_Node
EXPR_CMP_LT , EXPR_CMP_LE ,
//
EXPR_ID , // Variable access
EXPR_INPUT , // Input value access
EXPR_CONST , // Numeric constant
};
@ -361,6 +369,15 @@ class T_CondInstrNode : public A_InstructionNode
{ return *defaultCase_; }
};
// Fullscreen quad instruction
class T_FullscreenInstrNode : public A_InstructionNode
{
public:
T_FullscreenInstrNode( T_InstrListNode& parent ) noexcept
: A_InstructionNode( OP_FULLSCREEN , parent , E_InstrRestriction::INIT )
{ }
};
// Input declaration
class T_InputInstrNode : public A_InstructionNode
{
@ -421,6 +438,11 @@ class T_PipelineInstrNode : public A_InstructionNode
idLocation_{ }
{ }
T_String const& id( ) const noexcept
{ return id_; }
T_SRDLocation const& idLocation( ) const noexcept
{ return idLocation_; }
// 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
@ -482,6 +504,11 @@ class T_ProgramInstrNode : public A_InstructionNode
path_( pathToken.stringValue( ) ) ,
pathLocation_( pathToken.location( ) )
{ }
T_String const& id( ) const noexcept
{ return id_; }
T_SRDLocation const& idLocation( ) const noexcept
{ return idLocation_; }
};
// Setting a global variable
@ -495,12 +522,12 @@ class T_SetInstrNode : public A_InstructionNode
public:
T_SetInstrNode( T_InstrListNode& parent ,
T_SRDToken const& idToken ) noexcept
: A_InstructionNode( OP_PROGRAM , parent ) ,
: A_InstructionNode( OP_SET , parent ) ,
id_( idToken.stringValue( ) ) ,
idLocation_( idToken.location( ) )
{ }
T_String const& identifier( ) const noexcept
T_String const& id( ) const noexcept
{ return id_; }
T_SRDLocation const& idLocation( ) const noexcept
{ return idLocation_; }
@ -528,11 +555,16 @@ class T_TextureInstrNode : public A_InstructionNode
T_InstrListNode& parent ,
T_SRDToken const& id ,
E_TexType type ) noexcept
: A_InstructionNode( OP_PROGRAM , parent , E_InstrRestriction::FRAME ) ,
: A_InstructionNode( OP_TEXTURE , parent , E_InstrRestriction::FRAME ) ,
id_( id.stringValue( ) ) , idLocation_( id.location( ) ) ,
type_( type )
{ }
T_String const& id( ) const noexcept
{ return id_; }
T_SRDLocation const& idLocation( ) const noexcept
{ return idLocation_; }
void setWidth( P_ExpressionNode width ) noexcept
{ width_ = std::move( width ); }
bool hasWidth( ) const noexcept
@ -548,6 +580,99 @@ class T_TextureInstrNode : public A_InstructionNode
{ return *height_; }
};
// 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_;
T_SRDLocation idLocation_;
public:
T_UseInstrNode( T_InstrListNode& parent ,
const E_Type type ,
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_; }
T_SRDLocation const& idLocation( ) const noexcept
{ return idLocation_; }
};
// Texture/sampler use instructions
class T_UseTextureInstrNode : public T_UseInstrNode
{
private:
uint32_t bank_;
T_SRDLocation bankLocation_;
T_String samplerId_;
T_SRDLocation samplerIdLocation_;
public:
T_UseTextureInstrNode( T_InstrListNode& parent ,
T_SRDToken const& bank ,
T_SRDToken const& identifier ,
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_; }
T_SRDLocation const& bankLocation( ) const noexcept
{ return bankLocation_; }
T_String const& samplerId( ) const noexcept
{ return samplerId_; }
T_SRDLocation const& samplerIdLocation( ) const noexcept
{ return samplerIdLocation_; }
};
// Viewport instruction
class T_ViewportInstrNode : public A_InstructionNode
{
public:
enum E_Parameter {
PX , PY , PWIDTH , PHEIGHT
};
private:
P_ExpressionNode parameters_[ 4 ];
public:
T_ViewportInstrNode( T_InstrListNode& parent ) noexcept
: A_InstructionNode( OP_VIEWPORT , parent ,
E_InstrRestriction::INIT )
{ }
void setParameter( const E_Parameter p , P_ExpressionNode height ) noexcept
{ parameters_[ int( p ) ] = std::move( height ); }
bool hasParameter( const E_Parameter p ) const noexcept
{ return bool( parameters_[ int( p ) ] ); }
A_ExpressionNode& parameter( const E_Parameter p ) const noexcept
{ return *parameters_[ int( p ) ]; }
};
/*============================================================================*/
// A constant value
@ -608,6 +733,27 @@ class T_IdentifierExprNode : public A_ExpressionNode
{ return id_; }
};
// Access to an input value
class T_InputExprNode : public A_ExpressionNode
{
private:
T_String id_;
T_SRDLocation idLocation_;
public:
T_InputExprNode( A_Node& parent ,
T_SRDToken const& token ) noexcept
: A_ExpressionNode( EXPR_INPUT , parent ) ,
id_( token.stringValue( ) ) ,
idLocation_( token.location( ) )
{ }
T_String const& id( ) const noexcept
{ return id_; }
T_SRDLocation const& idLocation( ) const noexcept
{ return idLocation_; }
};
// A unary operator
class T_UnaryOperatorNode : public A_ExpressionNode
{