From 3de255aad0ffd1a72bc065b41f23a8f0d2b4709c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Emmanuel=20Beno=C3=AEt?= <tseeker@nocternity.net>
Date: Tue, 14 Nov 2017 22:04:00 +0100
Subject: [PATCH] Started using new control code + bugfixes

The program is loaded and its init part is run. Many bugs were fixed in
the process, including various new bugs in the shaders manager.
---
 demo.cc         | 129 ++++++++++++++++++++++++++++++++++++++++++++----
 demo.hh         |  28 +++++++----
 demo.srd        |   6 +--
 ebcl            |   2 +-
 main.cc         |   1 +
 opcomp.cc       |  11 +++--
 opparser.cc     |   8 +--
 ops.cc          |  65 +++++++++++++++++-------
 rendertarget.cc |   3 +-
 shaders.cc      |  11 +++--
 10 files changed, 209 insertions(+), 55 deletions(-)

diff --git a/demo.cc b/demo.cc
index c4290aa..7986671 100644
--- a/demo.cc
+++ b/demo.cc
@@ -1,17 +1,21 @@
 #include "externals.hh"
 #include "demo.hh"
 #include "sync.hh"
+#include "rendertarget.hh"
 #include "globals.hh"
+#include <ebcl/Files.hh>
+#include <ebcl/SRDText.hh>
 
 
-T_Demo::T_Demo( __rd__ const uint32_t width ,
-		__rd__ const uint32_t height )
+T_Demo::T_Demo( const uint32_t width ,
+		const uint32_t height )
 	: width( width ) , height( height )
 { }
 
 
 bool T_Demo::initialise( )
 {
+#if 0
 	raymarcher = std::make_unique< T_Raymarcher >(
 			width , height );
 	dof = std::make_unique< T_DoFPass >(
@@ -31,6 +35,11 @@ bool T_Demo::initialise( )
 	Globals::Sync( ).addInput( "dof-max-blur" , 16 );
 	Globals::Sync( ).addInput( "dof-samples" , 16 );
 	Globals::Sync( ).updateCurveCaches( );
+#endif
+
+	if ( !program ) {
+		loadProgram( );
+	}
 
 	return true;
 }
@@ -44,17 +53,25 @@ void T_Demo::makeUI( )
 			ImGuiSetCond_Once );
 	ImGui::Begin( "Demo controls" );
 
+#if 0
 	raymarcher->makeUI( );
 	dof->makeUI( );
 	bloom->makeUI( );
 	combine->makeUI( );
 	fxaa->makeUI( );
+#else
+	ImGui::Text( "lol, gtfo" );
+#endif
 
 	ImGui::End( );
 }
 
 void T_Demo::render( )
 {
+	if ( !context ) {
+		runInit( );
+	}
+
 	auto& sync( Globals::Sync( ) );
 	if ( playing ) {
 		const float time = SDL_GetTicks( ) * 1e-3;
@@ -66,28 +83,122 @@ void T_Demo::render( )
 	}
 	playingPrevious = playing;
 
+#if 0
 	raymarcher->render( );
 	dof->render( );
 	bloom->render( );
 	combine->render( );
 	fxaa->render( );
+#endif
 }
 
 void T_Demo::handleDND(
-		__rd__	ImVec2 const& move ,
-		__rd__	const bool hasCtrl ,
-		__rd__	const bool hasShift ,
-		__rd__	const bool lmb		// Left mouse button
+		ImVec2 const& move ,
+		const bool hasCtrl ,
+		const bool hasShift ,
+		const bool lmb		// Left mouse button
 	)
 {
+#if 0
 	raymarcher->camera( ).handleDND( move , hasCtrl , hasShift , lmb );
+#endif
 }
 
 void T_Demo::handleWheel(
-		__rd__	const float wheel ,
-		__rd__	const bool hasCtrl ,
-		__rd__	const bool hasShift
+		const float wheel ,
+		const bool hasCtrl ,
+		const bool hasShift
 	)
 {
+#if 0
 	raymarcher->camera( ).handleWheel( wheel , hasCtrl , hasShift );
+#endif
+}
+
+namespace {
+
+/*============================================================================*/
+
+
+void PrintStreamError(
+		char const* const prefix ,
+		T_String const& name ,
+		ebcl::X_StreamError const& error )
+{
+	T_StringBuilder sb;
+	sb << prefix << " '" << name << "': " << error.what( );
+	if ( error.code( ) == ebcl::E_StreamError::SYSTEM_ERROR ) {
+		sb << " (error code " << error.systemError( ) << ")";
+	}
+	sb << '\n' << '\0';
+	fprintf( stderr , "%s" , sb.data( ) );
+}
+
+void WriteSRDError(
+		T_StringBuilder& sb ,
+		ebcl::T_SRDError const& error )
+{
+	sb << error.location( ) << " - " << error.error( ) << "\n";
+}
+
+
+/*============================================================================*/
+
+} // namespace
+
+
+bool T_Demo::loadProgram( )
+{
+	using namespace ebcl;
+	const T_String inputName( T_String::Pooled( "demo.srd" ) );
+	T_File input( inputName , E_FileMode::READ_ONLY );
+	try {
+		input.open( );
+	} catch ( X_StreamError const& e ) {
+		PrintStreamError( "Could not open" , inputName , e );
+		return false;
+	}
+
+	// Load SRD data
+	T_SRDMemoryTarget srdOut;
+	srdOut.clearComments( true ).clearFlushToken( true );
+	try {
+		T_SRDTextReader srdReader{ srdOut };
+		T_FileInputStream fis{ input };
+		srdReader.read( inputName , fis );
+	} catch ( X_StreamError const& e ) {
+		PrintStreamError( "Could not open" , inputName , e );
+		return false;
+
+	} catch ( X_SRDErrors const& e ) {
+		T_StringBuilder sb;
+		const auto nErrors( e.errors.size( ) );
+		for ( auto i = 0u ; i < nErrors ; i ++ ) {
+			WriteSRDError( sb , e.errors[ i ] );
+		}
+		sb << "No parsing happened due to format errors\n" << '\0';
+		fprintf( stderr , "%s" , sb.data( ) );
+		return false;
+	}
+
+	// Parse the fuck
+	opast::T_Parser parser;
+	if ( parser.parse( srdOut.list( ) ) ) {
+		printf( "Parser successful. Compiling...\n" );
+		ops::T_Compiler compiler;
+		program = compiler.compile( *parser.result( ) );
+		return true;
+	}
+	return false;
+}
+
+
+void T_Demo::runInit( )
+{
+	context = NewOwned< ops::T_OpContext >( *program );
+	try {
+		context->run( ops::T_OpContext::R_INIT , 0 , width , height );
+	} catch ( ops::X_OpFailure const& fail ) {
+		printf( "FAILED TO RUN INIT!\n\t%s\n" , fail.what( ) );
+	}
 }
diff --git a/demo.hh b/demo.hh
index ecb0652..789307c 100644
--- a/demo.hh
+++ b/demo.hh
@@ -1,5 +1,6 @@
 #pragma once
 
+#if 0
 #include "raymarcher.hh"
 #include "dof.hh"
 #include "bloom.hh"
@@ -7,6 +8,8 @@
 #include "fxaa.hh"
 #include "profiling.hh"
 #include "sync.hh"
+#endif
+#include "control.hh"
 
 
 struct T_Demo
@@ -17,23 +20,26 @@ struct T_Demo
 
 	// ---------------------------------------------------------------------
 
-	T_Demo( __rd__ const uint32_t width ,
-			__rd__ const uint32_t height );
+	T_Demo( const uint32_t width ,
+			const uint32_t height );
 
 	bool initialise( );
 	void makeUI( );
 	void render( );
 
+	bool loadProgram( );
+	void runInit( );
+
 	void handleDND(
-			__rd__	ImVec2 const& move ,
-			__rd__	const bool hasCtrl ,
-			__rd__	const bool hasShift ,
-			__rd__	const bool lmb		// Left mouse button
+			ImVec2 const& move ,
+			const bool hasCtrl ,
+			const bool hasShift ,
+			const bool lmb		// Left mouse button
 		);
 	void handleWheel(
-			__rd__	const float wheel ,
-			__rd__	const bool hasCtrl ,
-			__rd__	const bool hasShift
+			const float wheel ,
+			const bool hasCtrl ,
+			const bool hasShift
 		);
 
 	// ---------------------------------------------------------------------
@@ -43,11 +49,15 @@ struct T_Demo
 
 	bool playing = false;
 
+#if 0
 	std::unique_ptr< T_Raymarcher > raymarcher;
 	std::unique_ptr< T_DoFPass > dof;
 	std::unique_ptr< T_BloomPass > bloom;
 	std::unique_ptr< T_CombinePass > combine;
 	std::unique_ptr< T_FXAAPass > fxaa;
+#endif
+	T_OwnPtr< ops::T_OpProgram > program;
+	T_OwnPtr< ops::T_OpContext > context;
 
     private:
 	bool playingPrevious = false;
diff --git a/demo.srd b/demo.srd
index 987b74b..76579d8 100644
--- a/demo.srd
+++ b/demo.srd
@@ -37,8 +37,8 @@
 # Scene
 
 (fn scene-init ()
-	(texture tx-scene-output rgb-f16 vp-width vp-height)
-	(texture tx-scene-depth r-f16 vp-width vp-height)
+	(texture tx-scene-output rgb-f16 $vp-width $vp-height)
+	(texture tx-scene-depth r-f16 $vp-width $vp-height)
 	(framebuffer rt-scene
 		(color tx-scene-output)
 		(color tx-scene-depth))
@@ -408,7 +408,7 @@
 	(program prg-fxaa "fxaa.f.glsl")
 	(pipeline pl-fxaa prg-fullscreen prg-fxaa)
 	(uniforms-i prg-fxaa 0 0)
-	(uniforms-i prg-fxaa 1 $vp-width $vp-height)
+	(uniforms prg-fxaa 1 $vp-width $vp-height)
 
 	(sampler smp-fxaa
 		(sampling linear)
diff --git a/ebcl b/ebcl
index 9f666ee..1ce16d6 160000
--- a/ebcl
+++ b/ebcl
@@ -1 +1 @@
-Subproject commit 9f666eea4946dd3de23203f6c829a540a2708565
+Subproject commit 1ce16d63cbed4b152cd113121ecb06fb8358b9f1
diff --git a/main.cc b/main.cc
index 343cb17..4da915e 100644
--- a/main.cc
+++ b/main.cc
@@ -7,6 +7,7 @@
 #include "window.hh"
 #include "shaders.hh"
 #include "odbg.hh"
+#include "rendertarget.hh"
 
 using ebcl::T_Optional;
 
diff --git a/opcomp.cc b/opcomp.cc
index 3fd0aec..28c1369 100644
--- a/opcomp.cc
+++ b/opcomp.cc
@@ -171,6 +171,9 @@ void T_CompilerImpl_::gatherConstants( ) noexcept
 		constants.add( value.u );
 		return true;
 	} );
+	for ( auto i = 0u ; i < constants.size( ) ; i ++ ) {
+		output->constants.add( constants[ i ] );
+	}
 
 #ifdef INVASIVE_TRACES
 	printf( "%d constants\n" , constants.size( ) );
@@ -431,14 +434,14 @@ bool T_CompilerImpl_::compileNode(
 			const auto ppos( condJumps.last( ).prevCase );
 			const auto diff( cpos - ppos );
 			assert( diff > 1 );
-			output->ops.get( funcIndex , ppos ).args[ 1 ] = diff - 1;
+			output->ops.get( funcIndex , ppos ).args[ 0 ] = diff - 1;
 		} else {
 			// If there is a previous skip location, insert the skip instruction
 			if ( !condJumps.last( ).caseEnds.empty( ) ) {
 				addInstruction( OP_SKIP , 0 , node.location( ) );
 				const auto ppos( condJumps.last( ).prevCase );
 				assert( output->ops.get( funcIndex , ppos ).op == OP_COND_SKIP );
-				output->ops.get( funcIndex , ppos ).args[ 1 ] ++;
+				output->ops.get( funcIndex , ppos ).args[ 0 ] ++;
 			}
 
 			// Add the conditional skip
@@ -455,7 +458,7 @@ bool T_CompilerImpl_::compileNode(
 			addInstruction( OP_SKIP , 0 , node.location( ) );
 			const auto ppos( condJumps.last( ).prevCase );
 			assert( output->ops.get( funcIndex , ppos ).op == OP_COND_SKIP );
-			output->ops.get( funcIndex , ppos ).args[ 1 ] ++;
+			output->ops.get( funcIndex , ppos ).args[ 0 ] ++;
 		}
 		break;
 
@@ -723,7 +726,7 @@ bool T_CompilerImpl_::compileNode(
 			T_OpValue value;
 			value.f = dynamic_cast< T_ConstantExprNode& >( node ).floatValue( );
 			addInstruction( OP_FP_LOAD ,
-					constants.indexOf( value.u ) + 3 ,
+					constants.indexOf( value.u ) + 3 + output->nVariables ,
 					node.location( ) );
 		}
 		break;
diff --git a/opparser.cc b/opparser.cc
index 4a71043..2b72f34 100644
--- a/opparser.cc
+++ b/opparser.cc
@@ -781,7 +781,7 @@ void T_ParserImpl_::checkIdentifier(
 		errors.addNew( "unknown identifier" , location );
 	} else if ( dt != expected ) {
 		T_StringBuilder esb;
-		esb << E_DataType::TEXTURE << " expected, " << dt << " found instead";
+		esb << expected << " expected, " << dt << " found instead";
 		errors.addNew( std::move( esb ) , location );
 	}
 }
@@ -1648,15 +1648,15 @@ M_INSTR_( Texture )
 		errors.addNew( "width expected" , input[ 0 ].location( ) );
 	}
 	if ( input.size( ) > 4 ) {
-		instr.setHeight( parseExpression( instr , input[ 3 ] ) );
+		instr.setHeight( parseExpression( instr , input[ 4 ] ) );
 	} else {
 		errors.addNew( "height expected" , input[ 0 ].location( ) );
 	}
 	if ( input.size( ) > 5 ) {
-		instr.setLODs( parseExpression( instr , input[ 4 ] ) );
+		instr.setLODs( parseExpression( instr , input[ 5 ] ) );
 	}
 	if ( input.size( ) > 6 ) {
-		errors.addNew( "too many arguments" , input[ 5 ].location( ) );
+		errors.addNew( "too many arguments" , input[ 6 ].location( ) );
 	}
 }
 
diff --git a/ops.cc b/ops.cc
index 2588ea4..db78837 100644
--- a/ops.cc
+++ b/ops.cc
@@ -206,8 +206,8 @@ X_OpFailure::X_OpFailure(
 	: op_( &op ) , error_( std::move( error ) )
 {
 	T_StringBuilder sb;
-	sb << "operation (" << op << ") failed; source: " << op.location
-		<< '\0';
+	sb << "operation (" << op << ") failed: "
+		<< error_ << "; source: " << op.location << '\0';
 	fullMessage_ = std::move( sb );
 }
 
@@ -226,19 +226,20 @@ T_OpContext::T_OpContext(
 
 	const auto nc{ program.constants.size( ) };
 	const auto ts{ 3 + nc + program.nVariables
-		+ program.nPrograms + program.nPipelines
-		+ program.nSamplers + program.nTextures };
+		+ program.nFramebuffers + program.nPrograms
+		+ program.nPipelines + program.nSamplers
+		+ program.nTextures };
 	values.resize( ts );
 	initialInputs.resize( program.inputs.size( ) );
 
 	framebuffers.resize( program.nFramebuffers );
 	pipelines.resize( program.nPipelines );
-	programs.resize( program.nPrograms );
 	samplers.resize( program.nSamplers );
 	textures.resize( program.nTextures );
 
+	memset( &values[ 0 ] , 0 , values.size( ) * 4 );
 	for ( auto i = 0u ; i < nc ; i ++ ) {
-		values[ i + 3 ] = program.constants[ nc ];
+		values[ i + 3 + program.nVariables ] = program.constants[ i ];
 	}
 }
 
@@ -276,13 +277,40 @@ void T_OpContext::run(
 	values[ 0 ] = time;
 	values[ 1 ] = width;
 	values[ 2 ] = height;
+
 	stack.clear( );
 	stack.add( 0xffffffff );
 
 	while ( !stack.empty( ) ) {
-//		if ( instrPtr >= program.ops.
 		auto const& instr{ program.ops[ instrPtr ] };
 
+//#define YOUR_MUM_IS_A_TRACE
+#ifdef YOUR_MUM_IS_A_TRACE
+		printf( "VALUES\n00" );
+		for ( auto i = 0u ; i < values.size( ) ; i ++ ) {
+			printf( "    %08x" , values[ i ].u );
+			if ( i % 4 == 3 ) {
+				printf( "\n%02x" , i + 1 );
+			}
+		}
+		if ( values.size( ) % 4 != 0 ) {
+			printf( "\n" );
+		}
+
+		T_StringBuilder sb;
+		sb << "EXECUTE " << instrPtr << ":\t(" << instr << ") {"
+			<< instr.location << "}\nSTACK:";
+		for ( auto i = 0u ; i < stack.size( ) ; i ++ ) {
+			sb << ' ' << stack[ i ].u;
+		}
+		sb << "\nFPU STACK:";
+		for ( auto i = 0u ; i < x87sp ; i ++ ) {
+			sb << ' ' << x87stack[ i ];
+		}
+		sb << '\n' << '\0';
+		printf( "%s" , sb.data( ) );
+#endif
+
 		switch ( instr.op ) {
 
 		    case OP_END:
@@ -445,7 +473,7 @@ void T_OpContext::run(
 			if ( x87stack[ x87sp - 1 ] == 0 ) {
 				throw X_OpFailure{ instr , "arithmetic error" };
 			}
-			x87stack[ x87sp - 2 ] *= x87stack[ x87sp - 1 ];
+			x87stack[ x87sp - 2 ] /= x87stack[ x87sp - 1 ];
 			x87sp --;
 			break;
 		    }
@@ -647,14 +675,14 @@ void T_OpContext::run(
 			}
 
 			const auto index( sv - 1 );
+			const uint32_t w( stack.last( ).f );
+			stack.removeLast( );
+			const uint32_t h( stack.last( ).f );
+			stack.removeLast( );
 			const uint32_t lods( instr.args[ 1 ] ? stack.last( ).f : 1 );
 			if ( instr.args[ 1 ] ) {
 				stack.removeLast( );
 			}
-			const uint32_t h( stack.last( ).f );
-			stack.removeLast( );
-			const uint32_t w( stack.last( ).f );
-			stack.removeLast( );
 
 			textures[ index ] = NewOwned< T_Texture >(
 					w , h , E_TexType( instr.args[ 0 ] ) , lods );
@@ -741,10 +769,7 @@ void T_OpContext::run(
 			if ( curFb < 0 ) {
 				throw X_OpFailure{ instr , "no framebuffer selected" };
 			}
-			if ( instr.args[ 0 ] == 0 ) {
-				throw X_OpFailure{ instr , "invalid argument" };
-			}
-			framebuffers[ curFb ]->toggle( instr.args[ 0 ] + 1 , instr.args[ 1 ] );
+			framebuffers[ curFb ]->toggle( instr.args[ 0 ] , instr.args[ 1 ] );
 			break;
 		    }
 
@@ -755,7 +780,11 @@ void T_OpContext::run(
 			const auto ss( stack.size( ) );
 			T_OpValue values[ 4 ];
 			for ( auto i = 0u ; i <= instr.args[ 0 ] ; i ++ ) {
-				values[ i ] = stack[ ss - 3 - i ];
+				if ( instr.args[ 1 ] ) {
+					values[ i ] = uint32_t( stack[ ss - 3 - i ].f );
+				} else {
+					values[ i ] = stack[ ss - 3 - i ];
+				}
 			}
 
 			const auto sv( stack.last( ).u );
@@ -770,7 +799,7 @@ void T_OpContext::run(
 			};
 			const F_SetUniform_ func{ *(F_SetUniform_*) funcs[
 				instr.args[ 0 ] + ( instr.args[ 1 ] ? 4 : 0 ) ] };
-			func( programs[ sv ]->id( ) , stack[ ss - 2 ].u , 1 , values );
+			func( programs[ sv - 1 ]->id( ) , stack[ ss - 2 ].u , 1 , values );
 			stack.resize( ss - 3 - instr.args[ 0 ] );
 			break;
 		    }
diff --git a/rendertarget.cc b/rendertarget.cc
index fcaa883..2ef5d32 100644
--- a/rendertarget.cc
+++ b/rendertarget.cc
@@ -174,8 +174,7 @@ void T_Rendertarget::toggle(
 		const uint32_t id ,
 		const bool active )
 {
-	assert( id > 0 );
-	const auto realId( GL_COLOR_ATTACHMENT0 + id - 1 );
+	const auto realId( GL_COLOR_ATTACHMENT0 + id );
 	const int32_t idx( buffers_.indexOf( realId ) );
 	if ( active && idx < 0 ) {
 		buffers_.add( realId );
diff --git a/shaders.cc b/shaders.cc
index 151ccac..52dc530 100644
--- a/shaders.cc
+++ b/shaders.cc
@@ -287,7 +287,7 @@ T_ShaderProgram::T_ShaderProgram(
 T_ShaderProgram::~T_ShaderProgram( )
 {
 	if ( id_ ) {
-		Globals::Shaders( ).dereferenceProgram( id_ );
+		Globals::Shaders( ).dereferenceProgram( id_ - 1 );
 	}
 }
 
@@ -296,7 +296,7 @@ T_ShaderProgram& T_ShaderProgram::operator=(
 {
 	if ( this != &other ) {
 		if ( id_ ) {
-			Globals::Shaders( ).dereferenceProgram( id_ );
+			Globals::Shaders( ).dereferenceProgram( id_ - 1 );
 		}
 		id_ = other.id_;
 		if ( id_ ) {
@@ -311,7 +311,7 @@ T_ShaderProgram& T_ShaderProgram::operator=(
 {
 	if ( this != &other ) {
 		if ( id_ ) {
-			Globals::Shaders( ).dereferenceProgram( id_ );
+			Globals::Shaders( ).dereferenceProgram( id_ - 1 );
 		}
 		id_ = other.id_;
 		other.id_ = T_String{};
@@ -666,7 +666,8 @@ T_ShaderProgram T_ShaderManager::program(
 {
 	loadProgram( name );
 	assert( programIndex_.contains( name ) );
-	return T_ShaderProgram( *programIndex_.get( name ) );
+	assert( programs_[ *programIndex_.get( name ) ].name == name );
+	return T_ShaderProgram( *programIndex_.get( name ) + 1 );
 }
 
 T_ShaderPipeline T_ShaderManager::pipeline(
@@ -844,7 +845,7 @@ bool T_ShaderManager::useExistingProgram(
 void T_ShaderManager::loadProgram(
 		T_String const& name )
 {
-	if ( useExistingProgram( name ) ) {
+	if ( !useExistingProgram( name ) ) {
 		initProgramRecord( name );
 	}
 }