Parser - Sampler definition instruction
This commit is contained in:
parent
7e5b69e714
commit
46972c7e60
4 changed files with 356 additions and 12 deletions
21
demo.srd
21
demo.srd
|
@ -80,23 +80,21 @@
|
||||||
|
|
||||||
(fn dof-init ()
|
(fn dof-init ()
|
||||||
# Sampler used for the inputs
|
# Sampler used for the inputs
|
||||||
{ NOT IMPLEMENTED
|
(sampler dof-sampler
|
||||||
(sampler dof-sampler
|
(mipmaps no)
|
||||||
(mipmaps no)
|
(wrapping clamp-edge)
|
||||||
(wrapping clamp-edge)
|
(sampling linear)
|
||||||
(sampling linear)
|
(lod 0 0)
|
||||||
(lod 0 0)
|
)
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
# Texture & RT for pass 1
|
# 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)
|
(framebuffer rt-dof-pass1 tx-dof-pass1)
|
||||||
|
|
||||||
# Texture & RT for pass 2
|
# 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)
|
(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
|
# Output debugging
|
||||||
(odbg tx-dof-pass1 hdr "DoF - First pass")
|
(odbg tx-dof-pass1 hdr "DoF - First pass")
|
||||||
|
@ -158,7 +156,6 @@
|
||||||
# Second pass
|
# Second pass
|
||||||
(call dof-set-uniforms prg-dof-pass2)
|
(call dof-set-uniforms prg-dof-pass2)
|
||||||
(use-texture 0 tx-dof-pass1 dof-sampler)
|
(use-texture 0 tx-dof-pass1 dof-sampler)
|
||||||
|
|
||||||
(use-pipeline pl-dof-pass2)
|
(use-pipeline pl-dof-pass2)
|
||||||
(use-framebuffer rt-dof-pass2)
|
(use-framebuffer rt-dof-pass2)
|
||||||
(viewport 0 0 $vp-width $vp-height)
|
(viewport 0 0 $vp-width $vp-height)
|
||||||
|
|
75
opast.cc
75
opast.cc
|
@ -174,6 +174,23 @@ A_Node* opast::ASTVisitorBrowser(
|
||||||
break;
|
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
|
// Uniforms instruction
|
||||||
case A_Node::OP_UNIFORMS:
|
case A_Node::OP_UNIFORMS:
|
||||||
{
|
{
|
||||||
|
@ -381,3 +398,61 @@ T_OutputDebugInstrNode::T_OutputDebugInstrNode(
|
||||||
description_( description.stringValue( ) ) ,
|
description_( description.stringValue( ) ) ,
|
||||||
locDescription_( description.location( ) )
|
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 {};
|
||||||
|
}
|
||||||
|
|
84
opast.hh
84
opast.hh
|
@ -29,6 +29,7 @@ class A_Node
|
||||||
OP_PIPELINE , // Shader pipeline declaration
|
OP_PIPELINE , // Shader pipeline declaration
|
||||||
OP_PROFILE , // Profiling block
|
OP_PROFILE , // Profiling block
|
||||||
OP_PROGRAM , // Shader program declaration
|
OP_PROGRAM , // Shader program declaration
|
||||||
|
OP_SAMPLER , // Define sampler
|
||||||
OP_SET , // Set instruction
|
OP_SET , // Set instruction
|
||||||
OP_TEXTURE , // Define texture
|
OP_TEXTURE , // Define texture
|
||||||
OP_UNIFORMS , // Set uniforms
|
OP_UNIFORMS , // Set uniforms
|
||||||
|
@ -602,6 +603,89 @@ class T_ProgramInstrNode : public A_InstructionNode
|
||||||
{ return idLocation_; }
|
{ 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
|
// Setting a global variable
|
||||||
class T_SetInstrNode : public A_InstructionNode
|
class T_SetInstrNode : public A_InstructionNode
|
||||||
{
|
{
|
||||||
|
|
188
opparser.cc
188
opparser.cc
|
@ -22,6 +22,7 @@ struct T_ParserImpl_
|
||||||
PIPELINE ,
|
PIPELINE ,
|
||||||
PROFILE ,
|
PROFILE ,
|
||||||
PROGRAM ,
|
PROGRAM ,
|
||||||
|
SAMPLER ,
|
||||||
SET ,
|
SET ,
|
||||||
TEXTURE ,
|
TEXTURE ,
|
||||||
UNIFORMS_FLT ,
|
UNIFORMS_FLT ,
|
||||||
|
@ -48,6 +49,7 @@ struct T_ParserImpl_
|
||||||
add( "pipeline" , E_InstrType::PIPELINE );
|
add( "pipeline" , E_InstrType::PIPELINE );
|
||||||
add( "profiling" , E_InstrType::PROFILE );
|
add( "profiling" , E_InstrType::PROFILE );
|
||||||
add( "program" , E_InstrType::PROGRAM );
|
add( "program" , E_InstrType::PROGRAM );
|
||||||
|
add( "sampler" , E_InstrType::SAMPLER );
|
||||||
add( "set" , E_InstrType::SET );
|
add( "set" , E_InstrType::SET );
|
||||||
add( "texture" , E_InstrType::TEXTURE );
|
add( "texture" , E_InstrType::TEXTURE );
|
||||||
add( "uniforms" , E_InstrType::UNIFORMS_FLT );
|
add( "uniforms" , E_InstrType::UNIFORMS_FLT );
|
||||||
|
@ -193,6 +195,21 @@ struct T_ParserImpl_
|
||||||
M_DPARSER_( Pipeline );
|
M_DPARSER_( Pipeline );
|
||||||
M_DPARSER_( Profile );
|
M_DPARSER_( Profile );
|
||||||
M_DPARSER_( Program );
|
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_( Set );
|
||||||
M_DPARSER_( Texture );
|
M_DPARSER_( Texture );
|
||||||
|
|
||||||
|
@ -473,6 +490,7 @@ void T_ParserImpl_::parseInstructions(
|
||||||
M_CASE_( PIPELINE , Pipeline );
|
M_CASE_( PIPELINE , Pipeline );
|
||||||
M_CASE_( PROFILE , Profile );
|
M_CASE_( PROFILE , Profile );
|
||||||
M_CASE_( PROGRAM , Program );
|
M_CASE_( PROGRAM , Program );
|
||||||
|
M_CASE_( SAMPLER , Sampler );
|
||||||
M_CASE_( SET , Set );
|
M_CASE_( SET , Set );
|
||||||
M_CASE_( TEXTURE , Texture );
|
M_CASE_( TEXTURE , Texture );
|
||||||
M_CASE_( UNIFORMS_FLT , Uniforms );
|
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 )
|
M_INSTR_( Set )
|
||||||
{
|
{
|
||||||
bool ok{ true };
|
bool ok{ true };
|
||||||
|
|
Loading…
Reference in a new issue