demotool/control.hh
Emmanuel BENOîT 210be3a852 Main script runs
Fixed a few more bugs, and now the main script runs without crashing. It
fails to produce any output, however.
2017-11-14 23:44:13 +01:00

553 lines
10 KiB
C++

#pragma once
#include "sync.hh"
#include "opast.hh"
struct T_Rendertarget;
namespace ops {
using namespace ebcl;
enum E_OpType
{
OP_END ,
//
OP_CALL ,
OP_RET ,
//
OP_SKIP ,
OP_COND_SKIP ,
//
OP_RES_STACK ,
OP_PUSH ,
OP_POP ,
OP_DUP ,
//
OP_LOAD ,
OP_STORE ,
OP_SLOAD ,
OP_CONST ,
OP_OFFSET ,
//
OP_GET_INPUT ,
//
OP_FP_LOAD ,
OP_FP_STORE ,
OP_FP_SLOAD ,
OP_FP_SSTORE ,
OP_FP_SSTORE_INT ,
//
OP_FP_CMP ,
OP_FP_ADD ,
OP_FP_SUB ,
OP_FP_MUL ,
OP_FP_DIV ,
OP_FP_POW ,
//
OP_FP_NEG ,
OP_FP_INV ,
OP_FP_NOT ,
OP_FP_SIN ,
OP_FP_COS ,
OP_FP_TAN ,
OP_FP_SQRT ,
OP_FP_EXP ,
OP_FP_LN ,
//
OP_GEN_ASSETS ,
OP_INIT_PIPELINE ,
OP_INIT_PROGRAM ,
OP_INIT_SAMPLER ,
OP_INIT_TEXTURE ,
OP_FB_ATTACH ,
//
OP_USE_FRAMEBUFFER ,
OP_FB_TOGGLE ,
OP_USE_PIPELINE ,
OP_USE_PROGRAM ,
OP_USE_TEXTURE ,
OP_UNIFORMS ,
OP_VIEWPORT ,
//
OP_FULLSCREEN ,
OP_CLEAR ,
//
OP_UI_PENTER ,
OP_UI_PEXIT ,
OP_UI_INPUT_DFT ,
OP_UI_ODBG ,
};
M_LSHIFT_OP( T_StringBuilder , E_OpType );
uint32_t ArgumentsFor( E_OpType op ) noexcept;
int32_t DeltaMainStack( E_OpType op ) noexcept;
int32_t DeltaFPUStack( E_OpType op ) noexcept;
struct T_Op
{
static constexpr int MAX_ARGS = 2;
E_OpType op;
T_SRDLocation location;
uint32_t args[ MAX_ARGS ];
T_Op( const E_OpType op ,
T_SRDLocation const& location ,
const uint32_t arg0 = 0 ) noexcept
: op( op ) , location( location ) ,
args{ arg0 }
{ }
T_Op( const E_OpType op ,
T_SRDLocation const& location ,
std::initializer_list< uint32_t > a ) noexcept
: op( op ) , location( location )
{
assert( a.size( ) <= MAX_ARGS );
auto it = a.begin( );
for ( auto i = 0u ; i < a.size( ) ; i ++ , ++it ) {
args[ i ] = *it;
}
}
};
M_LSHIFT_OP( T_StringBuilder , T_Op const& );
union T_OpValue
{
int32_t i;
uint32_t u;
float f;
constexpr T_OpValue( ) : i{ 0 } {}
constexpr T_OpValue( uint32_t u ) : u{ u } {}
constexpr T_OpValue( float f ) : f{ f } {}
};
struct T_OpProgram
{
T_MultiArray< T_Op > ops; // All operations
uint32_t init , // Index of initialisation function
frame; // Index of frame rendering function
T_Array< T_OpValue > constants; // Constants values
uint32_t nVariables{ 0 }; // Amount of variables
T_Array< T_String > inputs; // Input definitions
uint32_t nPrograms{ 0 } , // Amount of programs
nFramebuffers{ 0 } , // Amount of framebuffers
nPipelines{ 0 } , // Amount of pipelines
nSamplers{ 0 } , // Amount of samplers
nTextures{ 0 }; // Amount of textures
T_Array< T_String > progNames; // GLSL program files
T_Array< T_String > uiStrings; // UI strings for profiling, etc.
};
using P_OpProgram = T_OwnPtr< T_OpProgram >;
class T_Compiler : public A_PrivateImplementation
{
public:
T_Compiler( ) noexcept;
P_OpProgram compile(
opast::T_ParserOutput const& input ) noexcept;
};
struct T_OpContext
{
T_OpProgram& program; // The program
uint32_t instrPtr; // Instruction pointer
bool aborted{ false }; // Did the program fail?
T_Array< T_OpValue > values; // VM data
T_Array< T_OpValue > stack; // Main VM stack
T_Array< float > initialInputs; // Initial input values
T_OpValue wreg; // Work register
double x87stack[ 8 ]; // x87 FPU emulation stack
uint32_t x87sp; // x87 FPU emulation stack pointer
// Allocated resources
T_Array< T_OwnPtr< T_Rendertarget > > framebuffers;
T_Array< T_OwnPtr< T_ShaderProgram > > programs;
T_Array< T_OwnPtr< T_ShaderPipeline > > pipelines;
T_Array< T_OwnPtr< T_TextureSampler > > samplers;
T_Array< T_OwnPtr< T_Texture > > textures;
T_Array< T_String > profiling; // Profiling sections that have been started
int32_t curFb{ -1 }; // Index of current framebuffer
enum E_RunTarget {
R_INIT ,
R_RENDER
};
explicit T_OpContext( T_OpProgram& program ) noexcept;
void run( E_RunTarget target ,
float time ,
float width ,
float height );
private:
void ensureStack( T_Op const& op ,
uint32_t min );
void ensureFpuStack( T_Op const& op ,
uint32_t minStacked ,
uint32_t minFree );
void checkAddress( T_Op const& op ,
uint32_t address );
};
class X_OpFailure : public std::exception
{
public:
X_OpFailure( ) = delete;
DEF_COPY( X_OpFailure );
DEF_MOVE( X_OpFailure );
X_OpFailure(
T_Op const& op ,
T_String error ) noexcept;
T_Op const& op( ) const noexcept
{ return *op_; }
T_String const& error( ) const noexcept
{ return error_; }
char const* what( ) const noexcept override;
private:
T_Op const* op_;
T_String error_;
T_String fullMessage_;
};
} // namespace ops
/*= FIXME OLD VERSION BELOW ====================================================*/
namespace cops {
struct T_Program;
struct T_Context
{
T_Program const* program;
T_KeyValueTable< T_String , float > vars;
T_Array< float > opStack;
T_Context& store(
T_String const& name ,
const float value );
};
class X_OpFailure : public std::exception
{
public:
X_OpFailure( ) = delete;
DEF_COPY( X_OpFailure );
DEF_MOVE( X_OpFailure );
X_OpFailure(
T_String const& source ,
uint32_t line ,
T_String&& error ) noexcept;
T_String const& source( ) const noexcept
{ return source_; }
uint32_t line( ) const noexcept
{ return line_; }
T_String const& error( ) const noexcept
{ return error_; }
char const* what( ) const noexcept override;
private:
T_String source_;
uint32_t line_;
T_String error_;
T_String fullMessage_;
};
/*--------------------------------------------------------------------*/
enum E_Op
{
OP_LOAD_CONSTANT ,
OP_LOAD_VARIABLE ,
OP_LOAD_INPUT ,
OP_STORE_VARIABLE ,
//
OP_ADD , OP_MUL ,
OP_NEG , OP_INV ,
//
OP_DUP , OP_XCHG ,
//
OP_SET_UNIFORM ,
OP_USE_PIPELINE ,
OP_USE_TEXTURE ,
OP_USE_FRAMEBUFFER ,
OP_SET_VIEWPORT ,
//
OP_CLEAR ,
OP_FULLSCREEN ,
//
OP_CALL
};
struct T_Op
{
explicit T_Op(
const E_Op op );
virtual ~T_Op( ) = 0;
E_Op op( ) const noexcept
{ return op_; }
virtual void execute(
T_Context& ctx ) const = 0;
T_String source{};
uint32_t line{0};
protected:
X_OpFailure error(
ebcl::T_StringBuilder& message ) const noexcept;
X_OpFailure error(
T_String const& message ) const noexcept;
private:
E_Op op_;
};
using P_Op = T_OwnPtr< T_Op >;
using T_Operations = T_Array< P_Op >;
template< typename T >
inline T_Operations& operator <<(
T_Operations& ops ,
T&& item )
{
ops.add( NewOwned< T >( std::move( item ) ) );
return ops;
}
void Execute(
T_Operations const& operations ,
T_Context& context );
/*--------------------------------------------------------------------*/
struct T_Function
{
T_String name;
uint32_t arguments;
T_Operations operations;
T_Function( T_String const& name ,
const uint32_t arguments )
: name( name ) , arguments( arguments )
{ }
DEF_COPY( T_Function );
DEF_MOVE( T_Function );
};
struct T_Program
{
T_ObjectTable< T_String , T_Function > functions;
T_Operations main;
T_Program( )
: functions( []( T_Function const& f ) -> T_String {
return f.name;
} )
{ }
T_Operations& function(
T_String const& name ,
const uint32_t args );
void execute( T_Context& context )
{
context.program = this;
Execute( main , context );
}
};
/*====================================================================*/
struct OPLoadConstant : public T_Op
{
explicit OPLoadConstant(
const float constant );
void execute(
T_Context& ctx ) const override;
float constant;
};
struct OPLoadVariable : public T_Op
{
explicit OPLoadVariable(
T_String const& variable );
void execute(
T_Context& ctx ) const override;
T_String variable;
};
struct OPLoadInput : public T_Op
{
explicit OPLoadInput(
T_String const& input );
void execute(
T_Context& ctx ) const override;
T_String input;
};
struct OPStoreVariable : public T_Op
{
explicit OPStoreVariable(
T_String const& variable );
void execute(
T_Context& ctx ) const override;
T_String variable;
};
/*--------------------------------------------------------------------*/
struct OPAdd : public T_Op
{
OPAdd( ) : T_Op( OP_ADD ) {}
void execute(
T_Context& ctx ) const override;
};
struct OPMul : public T_Op
{
OPMul( ) : T_Op( OP_MUL ) {}
void execute(
T_Context& ctx ) const override;
};
struct OPNeg : public T_Op
{
OPNeg( ) : T_Op( OP_NEG ) {}
void execute(
T_Context& ctx ) const override;
};
struct OPInv : public T_Op
{
OPInv( ) : T_Op( OP_INV ) {}
void execute(
T_Context& ctx ) const override;
};
/*--------------------------------------------------------------------*/
struct OPDup : public T_Op
{
explicit OPDup( uint32_t stackIndex = 0 );
void execute(
T_Context& ctx ) const override;
uint32_t stackIndex;
};
struct OPXchg : public T_Op
{
explicit OPXchg( uint32_t stackIndex = 1 );
void execute(
T_Context& ctx ) const override;
uint32_t stackIndex;
};
/*--------------------------------------------------------------------*/
struct OPSetUniform : public T_Op
{
OPSetUniform(
const uint32_t count ,
const bool integer );
void execute(
T_Context& ctx ) const override;
uint32_t count;
bool integer;
};
struct OPUsePipeline : public T_Op
{
explicit OPUsePipeline(
const uint32_t index );
void execute(
T_Context& ctx ) const override;
uint32_t pipeline;
};
struct OPUseTexture : public T_Op
{
OPUseTexture(
const uint32_t binding ,
const uint32_t texture ,
const uint32_t sampler = 0 );
void execute(
T_Context& ctx ) const override;
uint32_t binding;
uint32_t texture;
uint32_t sampler;
};
struct OPUseFramebuffer : public T_Op
{
explicit OPUseFramebuffer(
const uint32_t framebuffer );
void execute(
T_Context& ctx ) const override;
uint32_t framebuffer;
};
struct OPSetViewport : public T_Op
{
OPSetViewport( ) : T_Op( OP_SET_VIEWPORT ) { }
void execute(
T_Context& ctx ) const override;
};
/*--------------------------------------------------------------------*/
struct OPClear : public T_Op
{
OPClear( ) : T_Op( OP_CLEAR ) { }
void execute(
T_Context& ctx ) const override;
};
struct OPFullscreen : public T_Op
{
OPFullscreen( ) : T_Op( OP_FULLSCREEN ) { }
void execute(
T_Context& ctx ) const override;
};
/*--------------------------------------------------------------------*/
struct OPCall : public T_Op
{
explicit OPCall(
T_String const& function );
void execute(
T_Context& ctx ) const override;
T_String function;
};
} // namespace cops