Parser - Sampler definition instruction

This commit is contained in:
Emmanuel BENOîT 2017-11-10 17:18:29 +01:00
parent 7e5b69e714
commit 46972c7e60
4 changed files with 356 additions and 12 deletions

View file

@ -80,23 +80,21 @@
(fn dof-init ()
# Sampler used for the inputs
{ 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)
(texture tx-dof-pass1 rgb-f16 $vp-width $vp-height)
(framebuffer rt-dof-pass1 tx-dof-pass1)
# Texture & RT for pass 2
(texture tx-dof-pass2 rgb-f16 vp-width vp-height)
(texture tx-dof-pass2 rgb-f16 $vp-width $vp-height)
(framebuffer rt-dof-pass2 tx-dof-pass2)
# MAYBE ? (alias tx-dof-output tx-dof-pass2)
# TODO MAYBE ? (alias tx-dof-output tx-dof-pass2)
# Output debugging
(odbg tx-dof-pass1 hdr "DoF - First pass")
@ -158,7 +156,6 @@
# 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)

View file

@ -174,6 +174,23 @@ A_Node* opast::ASTVisitorBrowser(
break;
}
// 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;
}
// Uniforms instruction
case A_Node::OP_UNIFORMS:
{
@ -381,3 +398,61 @@ T_OutputDebugInstrNode::T_OutputDebugInstrNode(
description_( description.stringValue( ) ) ,
locDescription_( description.location( ) )
{ }
/*= 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 {};
}

View file

@ -29,6 +29,7 @@ class A_Node
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
@ -602,6 +603,89 @@ class T_ProgramInstrNode : public A_InstructionNode
{ return idLocation_; }
};
// Sampler definition
class T_SamplerInstrNode : public A_InstructionNode
{
private:
struct T_Sampling_
{
T_SRDLocation location;
E_TexSampling mode;
};
struct T_Mipmaps_
{
T_SRDLocation location;
T_Optional< E_TexSampling > mode;
};
struct T_Wrapping_
{
T_SRDLocation location;
E_TexWrap mode;
};
struct T_LOD_
{
T_SRDLocation location;
P_ExpressionNode min;
P_ExpressionNode max;
};
T_String id_;
T_SRDLocation idLocation_;
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 ,
T_SRDToken const& id ) noexcept
: A_InstructionNode( OP_SAMPLER , parent ) ,
id_( id.stringValue( ) ) ,
idLocation_( id.location( ) )
{ }
T_String const& id( ) const noexcept
{ return id_; }
T_SRDLocation const& idLocation( ) const noexcept
{ return idLocation_; }
// 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< T_SRDLocation > setSampling(
E_TexSampling mode ,
T_SRDLocation const& location ) noexcept;
T_Optional< T_SRDLocation > setMipmapSampling(
E_TexSampling mode ,
T_SRDLocation const& location ) noexcept;
T_Optional< T_SRDLocation > setNoMipmap(
T_SRDLocation const& location ) noexcept;
T_Optional< T_SRDLocation > setWrapping(
E_TexWrap mode ,
T_SRDLocation const& location ) noexcept;
T_Optional< T_SRDLocation > setLOD(
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; }
A_ExpressionNode* minLod( ) const noexcept
{ return lod_ ? lod_->min.get( ) : nullptr; }
A_ExpressionNode* maxLod( ) const noexcept
{ return lod_ ? lod_->max.get( ) : nullptr; }
};
// Setting a global variable
class T_SetInstrNode : public A_InstructionNode
{

View file

@ -22,6 +22,7 @@ struct T_ParserImpl_
PIPELINE ,
PROFILE ,
PROGRAM ,
SAMPLER ,
SET ,
TEXTURE ,
UNIFORMS_FLT ,
@ -48,6 +49,7 @@ struct T_ParserImpl_
add( "pipeline" , E_InstrType::PIPELINE );
add( "profiling" , E_InstrType::PROFILE );
add( "program" , E_InstrType::PROGRAM );
add( "sampler" , E_InstrType::SAMPLER );
add( "set" , E_InstrType::SET );
add( "texture" , E_InstrType::TEXTURE );
add( "uniforms" , E_InstrType::UNIFORMS_FLT );
@ -193,6 +195,21 @@ struct T_ParserImpl_
M_DPARSER_( Pipeline );
M_DPARSER_( Profile );
M_DPARSER_( Program );
M_DPARSER_( Sampler );
void parseSamplerSampling(
T_SamplerInstrNode& instruction ,
T_SRDList const& input );
void parseSamplerMipmaps(
T_SamplerInstrNode& instruction ,
T_SRDList const& input );
void parseSamplerWrapping(
T_SamplerInstrNode& instruction ,
T_SRDList const& input );
void parseSamplerLOD(
T_SamplerInstrNode& instruction ,
T_SRDList const& input );
M_DPARSER_( Set );
M_DPARSER_( Texture );
@ -473,6 +490,7 @@ void T_ParserImpl_::parseInstructions(
M_CASE_( PIPELINE , Pipeline );
M_CASE_( PROFILE , Profile );
M_CASE_( PROGRAM , Program );
M_CASE_( SAMPLER , Sampler );
M_CASE_( SET , Set );
M_CASE_( TEXTURE , Texture );
M_CASE_( UNIFORMS_FLT , Uniforms );
@ -797,6 +815,176 @@ M_INSTR_( Program )
/*----------------------------------------------------------------------------*/
M_INSTR_( Sampler )
{
const auto ni{ input.size( ) };
if ( ni == 1 || input[ 0 ].type( ) != E_SRDTokenType::WORD ) {
errors.addNew( "sampler identifier expected" ,
input[ ni == 1 ? 0 : 1 ].location( ) );
return;
}
auto& instr{ instructions.add< T_SamplerInstrNode >( input[ 1 ] ) };
instr.location( ) = input[ 0 ].location( );
for ( auto i = 2u ; i < ni ; i ++ ) {
T_SRDToken const& token( input[ i ] );
if ( token.type( ) != E_SRDTokenType::LIST || token.list( ).empty( ) ) {
errors.addNew( "list expected" , token.location( ) );
continue;
}
T_SRDToken const& et( token.list( )[ 0 ] );
if ( et.type( ) != E_SRDTokenType::WORD ) {
errors.addNew( "'sampling', 'mipmaps', 'wrapping' or 'lod' expected" ,
et.location( ) );
continue;
}
T_String const& etn( et.stringValue( ) );
if ( etn == "sampling" ) {
parseSamplerSampling( instr , token.list( ) );
} else if ( etn == "mipmaps" ) {
parseSamplerMipmaps( instr , token.list( ) );
} else if ( etn == "wrapping" ) {
parseSamplerWrapping( instr , token.list( ) );
} else if ( etn == "lod" ) {
parseSamplerLOD( instr , token.list( ) );
} else {
errors.addNew( "'sampling', 'mipmaps', 'wrapping' or 'lod' expected" ,
et.location( ) );
}
}
}
void T_ParserImpl_::parseSamplerSampling(
T_SamplerInstrNode& instruction ,
T_SRDList const& input )
{
if ( input.size( ) == 1 || input[ 1 ].type( ) != E_SRDTokenType::WORD ) {
errors.addNew( "sampling mode expected" ,
input[ input.size( ) == 1 ? 0 : 1 ].location( ) );
return;
}
bool ok = true;
T_String const& sMode{ input[ 1 ].stringValue( ) };
E_TexSampling smp{ E_TexSampling::NEAREST };
if ( sMode == "linear" ) {
smp = E_TexSampling::LINEAR;
} else if ( sMode != "nearest" ) {
errors.addNew( "'nearest' or 'linear' expected" , input[ 1 ].location( ) );
ok = false;
}
if ( input.size( ) > 2 ) {
errors.addNew( "too many arguments" , input[ 2 ].location( ) );
}
const auto prev{ instruction.setSampling( smp , input[ 0 ].location( ) ) };
if ( prev && ok ) {
T_StringBuilder sb;
sb << "sampling mode already set at " << *prev;
errors.addNew( std::move( sb ) , input[ 0 ].location( ) );
}
}
void T_ParserImpl_::parseSamplerMipmaps(
T_SamplerInstrNode& instruction ,
T_SRDList const& input )
{
if ( input.size( ) == 1 || input[ 1 ].type( ) != E_SRDTokenType::WORD ) {
errors.addNew( "mipmap sampling mode expected" ,
input[ input.size( ) == 1 ? 0 : 1 ].location( ) );
return;
}
bool ok = true;
T_String const& sMode{ input[ 1 ].stringValue( ) };
T_Optional< E_TexSampling > smp{ };
if ( sMode == "linear" ) {
smp = E_TexSampling::LINEAR;
} else if ( sMode == "nearest" ) {
smp = E_TexSampling::NEAREST;
} else if ( sMode != "no" ) {
errors.addNew( "'no', 'nearest' or 'linear' expected" , input[ 1 ].location( ) );
ok = false;
}
if ( input.size( ) > 2 ) {
errors.addNew( "too many arguments" , input[ 2 ].location( ) );
}
const auto prev{ smp
? instruction.setMipmapSampling( *smp , input[ 0 ].location( ) )
: instruction.setNoMipmap( input[ 0 ].location( ) ) };
if ( prev && ok ) {
T_StringBuilder sb;
sb << "mipmap sampling mode already set at " << *prev;
errors.addNew( std::move( sb ) , input[ 0 ].location( ) );
}
}
void T_ParserImpl_::parseSamplerWrapping(
T_SamplerInstrNode& instruction ,
T_SRDList const& input )
{
if ( input.size( ) == 1 || input[ 1 ].type( ) != E_SRDTokenType::WORD ) {
errors.addNew( "wrapping mode expected" ,
input[ input.size( ) == 1 ? 0 : 1 ].location( ) );
return;
}
bool ok = true;
T_String const& sMode{ input[ 1 ].stringValue( ) };
E_TexWrap smp{ E_TexWrap::REPEAT };
if ( sMode == "clamp-border" ) {
smp = E_TexWrap::CLAMP_BORDER;
} else if ( sMode == "clamp-edge" ) {
smp = E_TexWrap::CLAMP_EDGE;
} else if ( sMode != "repeat" ) {
errors.addNew( "'repeat', 'clamp-border' or 'clamp-edge' expected" ,
input[ 1 ].location( ) );
ok = false;
}
if ( input.size( ) > 2 ) {
errors.addNew( "too many arguments" , input[ 2 ].location( ) );
}
const auto prev{ instruction.setWrapping( smp , input[ 0 ].location( ) ) };
if ( prev && ok ) {
T_StringBuilder sb;
sb << "wrapping mode already set at " << *prev;
errors.addNew( std::move( sb ) , input[ 0 ].location( ) );
}
}
void T_ParserImpl_::parseSamplerLOD(
T_SamplerInstrNode& instruction ,
T_SRDList const& input )
{
if ( input.size( ) < 3 ) {
errors.addNew( "min/max LODs expected" , input[ 0 ].location( ) );
return;
}
if ( input.size( ) > 3 ) {
errors.addNew( "too many arguments" , input[ 2 ].location( ) );
}
P_ExpressionNode min{ parseExpression( instruction , input[ 1 ] ) };
P_ExpressionNode max{ parseExpression( instruction , input[ 2 ] ) };
const auto prev{ instruction.setLOD( input[ 0 ].location( ) ,
std::move( min ) , std::move( max ) ) };
if ( prev ) {
T_StringBuilder sb;
sb << "min/max LOD already set at " << *prev;
errors.addNew( std::move( sb ) , input[ 0 ].location( ) );
}
}
/*----------------------------------------------------------------------------*/
M_INSTR_( Set )
{
bool ok{ true };