Finished implementation of the emulator
It's probably full of bugs so meh
This commit is contained in:
parent
6deb59d884
commit
c05ab54ca7
7 changed files with 404 additions and 20 deletions
12
control.hh
12
control.hh
|
@ -2,6 +2,8 @@
|
||||||
#include "sync.hh"
|
#include "sync.hh"
|
||||||
#include "opast.hh"
|
#include "opast.hh"
|
||||||
|
|
||||||
|
struct T_Rendertarget;
|
||||||
|
|
||||||
namespace ops {
|
namespace ops {
|
||||||
|
|
||||||
using namespace ebcl;
|
using namespace ebcl;
|
||||||
|
@ -25,6 +27,7 @@ enum E_OpType
|
||||||
OP_STORE ,
|
OP_STORE ,
|
||||||
OP_SLOAD ,
|
OP_SLOAD ,
|
||||||
OP_CONST ,
|
OP_CONST ,
|
||||||
|
OP_OFFSET ,
|
||||||
//
|
//
|
||||||
OP_FP_LOAD ,
|
OP_FP_LOAD ,
|
||||||
OP_FP_STORE ,
|
OP_FP_STORE ,
|
||||||
|
@ -49,6 +52,7 @@ enum E_OpType
|
||||||
OP_FP_EXP ,
|
OP_FP_EXP ,
|
||||||
OP_FP_LN ,
|
OP_FP_LN ,
|
||||||
//
|
//
|
||||||
|
OP_GEN_ASSETS ,
|
||||||
OP_INIT_PIPELINE ,
|
OP_INIT_PIPELINE ,
|
||||||
OP_INIT_PROGRAM ,
|
OP_INIT_PROGRAM ,
|
||||||
OP_INIT_SAMPLER ,
|
OP_INIT_SAMPLER ,
|
||||||
|
@ -166,7 +170,15 @@ struct T_OpContext
|
||||||
double x87stack[ 8 ]; // x87 FPU emulation stack
|
double x87stack[ 8 ]; // x87 FPU emulation stack
|
||||||
uint32_t x87sp; // x87 FPU emulation stack pointer
|
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
|
T_Array< T_String > profiling; // Profiling sections that have been started
|
||||||
|
int32_t curFb{ -1 }; // Index of current framebuffer
|
||||||
|
|
||||||
enum E_RunTarget {
|
enum E_RunTarget {
|
||||||
R_INIT ,
|
R_INIT ,
|
||||||
|
|
26
opcomp.cc
26
opcomp.cc
|
@ -334,6 +334,28 @@ bool T_CompilerImpl_::compileNode(
|
||||||
}
|
}
|
||||||
|
|
||||||
case A_Node::DECL_INIT:
|
case A_Node::DECL_INIT:
|
||||||
|
{
|
||||||
|
A_FuncNode& fn( (A_FuncNode&) node );
|
||||||
|
processFunction( exit , 0 , fn.locals( ) , node.location( ) );
|
||||||
|
if ( output->nFramebuffers ) {
|
||||||
|
addInstruction( OP_OFFSET , fiFramebuffers , node.location( ) );
|
||||||
|
addInstruction( OP_GEN_ASSETS , { 0 , output->nFramebuffers } , node.location( ) );
|
||||||
|
}
|
||||||
|
if ( output->nPipelines ) {
|
||||||
|
addInstruction( OP_OFFSET , fiPipelines , node.location( ) );
|
||||||
|
addInstruction( OP_GEN_ASSETS , { 1 , output->nPipelines } , node.location( ) );
|
||||||
|
}
|
||||||
|
if ( output->nSamplers ) {
|
||||||
|
addInstruction( OP_OFFSET , fiSamplers , node.location( ) );
|
||||||
|
addInstruction( OP_GEN_ASSETS , { 2 , output->nSamplers } , node.location( ) );
|
||||||
|
}
|
||||||
|
if ( output->nTextures ) {
|
||||||
|
addInstruction( OP_OFFSET , fiTextures , node.location( ) );
|
||||||
|
addInstruction( OP_GEN_ASSETS , { 3 , output->nTextures } , node.location( ) );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case A_Node::DECL_FRAME:
|
case A_Node::DECL_FRAME:
|
||||||
{
|
{
|
||||||
A_FuncNode& fn( (A_FuncNode&) node );
|
A_FuncNode& fn( (A_FuncNode&) node );
|
||||||
|
@ -448,7 +470,7 @@ bool T_CompilerImpl_::compileNode(
|
||||||
pn.pLocation( i ) );
|
pn.pLocation( i ) );
|
||||||
}
|
}
|
||||||
processIdentifier( funcIndex , pn.id( ) , pn.location( ) );
|
processIdentifier( funcIndex , pn.id( ) , pn.location( ) );
|
||||||
addInstruction( OP_INIT_PIPELINE , pn.size( ) , pn.location( ) );
|
addInstruction( OP_INIT_PIPELINE , pn.size( ) - 1 , pn.location( ) );
|
||||||
sdMain -= pn.size( );
|
sdMain -= pn.size( );
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -519,7 +541,7 @@ bool T_CompilerImpl_::compileNode(
|
||||||
sdMain --;
|
sdMain --;
|
||||||
}
|
}
|
||||||
if ( id ) {
|
if ( id ) {
|
||||||
addInstruction( OP_FB_TOGGLE , { id , 1 } , fan.location( ) );
|
addInstruction( OP_FB_TOGGLE , { id - 1 , 1 } , fan.location( ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
271
ops.cc
271
ops.cc
|
@ -1,8 +1,9 @@
|
||||||
#include "externals.hh"
|
#include "externals.hh"
|
||||||
#include "control.hh"
|
#include "control.hh"
|
||||||
#include "globals.hh"
|
#include "globals.hh"
|
||||||
#include "sync.hh"
|
|
||||||
#include "profiling.hh"
|
#include "profiling.hh"
|
||||||
|
#include "rendertarget.hh"
|
||||||
|
#include "sync.hh"
|
||||||
|
|
||||||
using namespace ops;
|
using namespace ops;
|
||||||
using namespace ebcl;
|
using namespace ebcl;
|
||||||
|
@ -98,6 +99,7 @@ static T_KeyValueTable< E_OpType , T_OpInfo > OpInfoTable_{ ([]() {
|
||||||
infos.add( E_OpType::OP_STORE , T_OpInfo{ "store" , 1 } );
|
infos.add( E_OpType::OP_STORE , T_OpInfo{ "store" , 1 } );
|
||||||
infos.add( E_OpType::OP_SLOAD , T_OpInfo{ "load-stack" , 1 } );
|
infos.add( E_OpType::OP_SLOAD , T_OpInfo{ "load-stack" , 1 } );
|
||||||
infos.add( E_OpType::OP_CONST , T_OpInfo{ "const" , 1 } );
|
infos.add( E_OpType::OP_CONST , T_OpInfo{ "const" , 1 } );
|
||||||
|
infos.add( E_OpType::OP_OFFSET , T_OpInfo{ "offset" , 1 } );
|
||||||
//
|
//
|
||||||
infos.add( E_OpType::OP_FP_LOAD , T_OpInfo{ "fp-load" , 1 , OpStackFPU{ 1 } } );
|
infos.add( E_OpType::OP_FP_LOAD , T_OpInfo{ "fp-load" , 1 , OpStackFPU{ 1 } } );
|
||||||
infos.add( E_OpType::OP_FP_SLOAD , T_OpInfo{ "fp-load-stack" , 1 , OpStackFPU{ 1 } } );
|
infos.add( E_OpType::OP_FP_SLOAD , T_OpInfo{ "fp-load-stack" , 1 , OpStackFPU{ 1 } } );
|
||||||
|
@ -122,6 +124,7 @@ static T_KeyValueTable< E_OpType , T_OpInfo > OpInfoTable_{ ([]() {
|
||||||
infos.add( E_OpType::OP_FP_EXP , T_OpInfo{ "fp-exp" , 0 } );
|
infos.add( E_OpType::OP_FP_EXP , T_OpInfo{ "fp-exp" , 0 } );
|
||||||
infos.add( E_OpType::OP_FP_LN , T_OpInfo{ "fp-ln" , 0 } );
|
infos.add( E_OpType::OP_FP_LN , T_OpInfo{ "fp-ln" , 0 } );
|
||||||
//
|
//
|
||||||
|
infos.add( E_OpType::OP_GEN_ASSETS , T_OpInfo{ "gen-assets" , 2 } );
|
||||||
infos.add( E_OpType::OP_INIT_PIPELINE , T_OpInfo{ "pipeline" , 1 , OpStackMain{ -1 } } );
|
infos.add( E_OpType::OP_INIT_PIPELINE , T_OpInfo{ "pipeline" , 1 , OpStackMain{ -1 } } );
|
||||||
infos.add( E_OpType::OP_INIT_PROGRAM , T_OpInfo{ "program" , 1 } );
|
infos.add( E_OpType::OP_INIT_PROGRAM , T_OpInfo{ "program" , 1 } );
|
||||||
infos.add( E_OpType::OP_INIT_TEXTURE , T_OpInfo{ "texture" , 2 , OpStackMain{ -3 } } );
|
infos.add( E_OpType::OP_INIT_TEXTURE , T_OpInfo{ "texture" , 2 , OpStackMain{ -3 } } );
|
||||||
|
@ -228,6 +231,12 @@ T_OpContext::T_OpContext(
|
||||||
values.resize( ts );
|
values.resize( ts );
|
||||||
initialInputs.resize( program.inputs.size( ) );
|
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 );
|
||||||
|
|
||||||
for ( auto i = 0u ; i < nc ; i ++ ) {
|
for ( auto i = 0u ; i < nc ; i ++ ) {
|
||||||
values[ i + 3 ] = program.constants[ nc ];
|
values[ i + 3 ] = program.constants[ nc ];
|
||||||
}
|
}
|
||||||
|
@ -324,6 +333,7 @@ void T_OpContext::run(
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OP_CONST:
|
case OP_CONST:
|
||||||
|
case OP_OFFSET:
|
||||||
wreg = instr.args[ 0 ];
|
wreg = instr.args[ 0 ];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -505,11 +515,216 @@ void T_OpContext::run(
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------
|
||||||
|
|
||||||
// TODO resource init
|
case OP_GEN_ASSETS:
|
||||||
|
{
|
||||||
|
auto idx = 0u;
|
||||||
|
switch ( instr.args[ 0 ] ) {
|
||||||
|
case 3: idx += program.nSamplers;
|
||||||
|
// fallthrough
|
||||||
|
case 2: idx += program.nPrograms + program.nPipelines;
|
||||||
|
// fallthrough
|
||||||
|
case 1: idx += program.nFramebuffers;
|
||||||
|
// fallthrough
|
||||||
|
case 0: idx += 3 + program.nVariables + program.constants.size( ); break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw X_OpFailure( instr , "invalid argument" );
|
||||||
|
}
|
||||||
|
|
||||||
|
auto count = 0u;
|
||||||
|
switch ( instr.args[ 0 ] ) {
|
||||||
|
case 3: count = program.nTextures; break;
|
||||||
|
case 2: count = program.nSamplers; break;
|
||||||
|
case 1: count = program.nPipelines; break;
|
||||||
|
case 0: count = program.nFramebuffers; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for ( auto i = 0u ; i < count ; i ++ ) {
|
||||||
|
values[ idx + i ].u = i + 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case OP_INIT_PIPELINE:
|
||||||
|
{
|
||||||
|
ensureStack( instr , 2 + instr.args[ 0 ] );
|
||||||
|
|
||||||
|
const auto sv( stack.last( ).u );
|
||||||
|
stack.removeLast( );
|
||||||
|
if ( sv == 0 || sv > pipelines.size( ) ) {
|
||||||
|
throw X_OpFailure{ instr , "invalid pipeline" };
|
||||||
|
}
|
||||||
|
const auto plIndex( sv - 1 );
|
||||||
|
|
||||||
|
T_String progNames[ 6 ];
|
||||||
|
for ( auto i = 0u ; i <= instr.args[ 0 ] ; i ++ ) {
|
||||||
|
const auto prIndex( stack.last( ).u );
|
||||||
|
stack.removeLast( );
|
||||||
|
if ( !prIndex ) {
|
||||||
|
throw X_OpFailure{ instr , "pipeline uses uninitialised program" };
|
||||||
|
}
|
||||||
|
progNames[ i ] = programs[ prIndex - 1 ]->name( );
|
||||||
|
}
|
||||||
|
|
||||||
|
pipelines[ plIndex ] = NewOwned< T_ShaderPipeline >(
|
||||||
|
Globals::Shaders( ).pipeline( progNames , instr.args[ 0 ] + 1 ) );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case OP_INIT_PROGRAM:
|
||||||
|
{
|
||||||
|
if ( instr.args[ 0 ] >= program.progNames.size( ) ) {
|
||||||
|
throw X_OpFailure{ instr , "invalid argument" };
|
||||||
|
}
|
||||||
|
programs.add( NewOwned< T_ShaderProgram >(
|
||||||
|
Globals::Shaders( ).program( program.progNames[ instr.args[ 0 ] ] ) ) );
|
||||||
|
wreg = programs.size( );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case OP_INIT_SAMPLER:
|
||||||
|
{
|
||||||
|
ensureStack( instr , 3 );
|
||||||
|
const auto sv( stack.last( ).u );
|
||||||
|
stack.removeLast( );
|
||||||
|
if ( sv == 0 || sv > samplers.size( ) ) {
|
||||||
|
throw X_OpFailure{ instr , "invalid sampler" };
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto samplerIndex( sv - 1 );
|
||||||
|
if ( !samplers[ samplerIndex ] ) {
|
||||||
|
samplers[ samplerIndex ] = NewOwned< T_TextureSampler >( );
|
||||||
|
}
|
||||||
|
|
||||||
|
const float max( stack.last( ).f );
|
||||||
|
stack.removeLast( );
|
||||||
|
const float min( stack.last( ).f );
|
||||||
|
stack.removeLast( );
|
||||||
|
|
||||||
|
samplers[ samplerIndex ]->sampling( E_TexSampling( ( instr.args[ 0 ] & 4 ) >> 2 ) )
|
||||||
|
.wrap( E_TexWrap( instr.args[ 1 ] ) )
|
||||||
|
.lod( min , max );
|
||||||
|
if ( ( instr.args[ 0 ] & 2 ) == 0 ) {
|
||||||
|
samplers[ samplerIndex ]->noMipmap( );
|
||||||
|
} else {
|
||||||
|
samplers[ samplerIndex ]->mipmap( E_TexSampling( instr.args[ 0 ] & 1 ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case OP_INIT_TEXTURE:
|
||||||
|
{
|
||||||
|
ensureStack( instr , 3 + ( instr.args[ 1 ] ? 1 : 0 ) );
|
||||||
|
|
||||||
|
const auto sv( stack.last( ).u );
|
||||||
|
stack.removeLast( );
|
||||||
|
if ( sv == 0 || sv > textures.size( ) ) {
|
||||||
|
throw X_OpFailure{ instr , "invalid texture" };
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto index( sv - 1 );
|
||||||
|
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 );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case OP_FB_ATTACH:
|
||||||
|
{
|
||||||
|
// instr[ 0 ] = id (0 for depth attachment, 1+ for color attachments)
|
||||||
|
// instr[ 1 ] = has LOD?
|
||||||
|
// stack: TOP < TEX ( < LOD if has LOD )
|
||||||
|
ensureStack( instr , 1 + ( instr.args[ 1 ] ? 1 : 0 ) );
|
||||||
|
if ( curFb < 0 ) {
|
||||||
|
throw X_OpFailure{ instr , "no framebuffer selected" };
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto svt( stack.last( ).u );
|
||||||
|
stack.removeLast( );
|
||||||
|
if ( svt == 0 || svt > textures.size( ) || !textures[ svt - 1 ] ) {
|
||||||
|
throw X_OpFailure{ instr , "invalid texture" };
|
||||||
|
}
|
||||||
|
const auto& texture( *textures[ svt - 1 ] );
|
||||||
|
|
||||||
|
const uint32_t lod( instr.args[ 1 ] ? uint32_t( stack.last( ).f ) : 0 );
|
||||||
|
if ( instr.args[ 1 ] ) {
|
||||||
|
stack.removeLast( );
|
||||||
|
}
|
||||||
|
framebuffers[ curFb ]->attach( texture , lod , instr.args[ 0 ] );
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------
|
||||||
|
|
||||||
// TODO resource usage
|
case OP_USE_TEXTURE:
|
||||||
|
{
|
||||||
|
ensureStack( instr , 2 );
|
||||||
|
|
||||||
|
const auto svt( stack.last( ).u );
|
||||||
|
stack.removeLast( );
|
||||||
|
if ( svt == 0 || svt > textures.size( ) || !textures[ svt - 1 ] ) {
|
||||||
|
throw X_OpFailure{ instr , "invalid texture" };
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto svs( stack.last( ).u );
|
||||||
|
stack.removeLast( );
|
||||||
|
if ( svs == 0 || svs > samplers.size( ) || !samplers[ svs - 1 ] ) {
|
||||||
|
throw X_OpFailure{ instr , "invalid sampler" };
|
||||||
|
}
|
||||||
|
|
||||||
|
Globals::Textures( ).bind( instr.args[ 0 ] ,
|
||||||
|
*textures[ svt - 1 ] , *samplers[ svs - 1 ] );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case OP_USE_PIPELINE:
|
||||||
|
{
|
||||||
|
ensureStack( instr , 1 );
|
||||||
|
|
||||||
|
const auto sv( stack.last( ).u );
|
||||||
|
stack.removeLast( );
|
||||||
|
if ( sv == 0 || sv > pipelines.size( ) || !pipelines[ sv - 1 ] ) {
|
||||||
|
throw X_OpFailure{ instr , "invalid pipeline" };
|
||||||
|
}
|
||||||
|
pipelines[ sv - 1 ]->enable( );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case OP_USE_PROGRAM:
|
||||||
|
{
|
||||||
|
ensureStack( instr , 1 );
|
||||||
|
|
||||||
|
const auto sv( stack.last( ).u );
|
||||||
|
stack.removeLast( );
|
||||||
|
if ( sv == 0 || sv > programs.size( ) || !programs[ sv - 1 ] ) {
|
||||||
|
throw X_OpFailure{ instr , "invalid program" };
|
||||||
|
}
|
||||||
|
programs[ sv - 1 ]->enable( );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case OP_FB_TOGGLE:
|
||||||
|
{
|
||||||
|
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 ] );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case OP_UNIFORMS:
|
case OP_UNIFORMS:
|
||||||
{
|
{
|
||||||
|
@ -518,10 +733,23 @@ void T_OpContext::run(
|
||||||
const auto ss( stack.size( ) );
|
const auto ss( stack.size( ) );
|
||||||
T_OpValue values[ 4 ];
|
T_OpValue values[ 4 ];
|
||||||
for ( auto i = 0u ; i <= instr.args[ 0 ] ; i ++ ) {
|
for ( auto i = 0u ; i <= instr.args[ 0 ] ; i ++ ) {
|
||||||
values[ i ] = stack[ ss - 2 - i ];
|
values[ i ] = stack[ ss - 3 - i ];
|
||||||
}
|
}
|
||||||
// FIXME can't actually finish this, I'm stupid.
|
|
||||||
|
|
||||||
|
const auto sv( stack.last( ).u );
|
||||||
|
if ( sv == 0 || sv > programs.size( ) || !programs[ sv - 1 ] ) {
|
||||||
|
throw X_OpFailure{ instr , "invalid program" };
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef void (*F_SetUniform_)( int , int , int , void* );
|
||||||
|
void const* const funcs[] = {
|
||||||
|
&glProgramUniform1fv , &glProgramUniform2fv , &glProgramUniform3fv , &glProgramUniform4fv ,
|
||||||
|
&glProgramUniform1iv , &glProgramUniform2iv , &glProgramUniform3iv , &glProgramUniform4iv ,
|
||||||
|
};
|
||||||
|
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 );
|
||||||
|
stack.resize( ss - 3 - instr.args[ 0 ] );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -535,6 +763,26 @@ void T_OpContext::run(
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case OP_USE_FRAMEBUFFER:
|
||||||
|
{
|
||||||
|
ensureStack( instr , 1 );
|
||||||
|
const auto sv( stack.last( ).u );
|
||||||
|
stack.removeLast( );
|
||||||
|
if ( sv == 0 ) {
|
||||||
|
glBindFramebuffer( GL_FRAMEBUFFER , 0 );
|
||||||
|
curFb = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto index( sv - 1 );
|
||||||
|
if ( !framebuffers[ index ] ) {
|
||||||
|
framebuffers[ index ] = NewOwned< T_Rendertarget >( );
|
||||||
|
}
|
||||||
|
glBindFramebuffer( GL_FRAMEBUFFER , framebuffers[ index ]->id( ) );
|
||||||
|
curFb = index;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------
|
||||||
|
|
||||||
case OP_FULLSCREEN:
|
case OP_FULLSCREEN:
|
||||||
|
@ -571,6 +819,19 @@ void T_OpContext::run(
|
||||||
initialInputs[ instr.args[ 0 ] ] = values[ instr.args[ 1 ] ].f;
|
initialInputs[ instr.args[ 0 ] ] = values[ instr.args[ 1 ] ].f;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case OP_UI_ODBG:
|
||||||
|
{
|
||||||
|
ensureStack( instr , 1 );
|
||||||
|
const auto svt( stack.last( ).u );
|
||||||
|
stack.removeLast( );
|
||||||
|
if ( svt == 0 || svt > textures.size( ) || !textures[ svt - 1 ] ) {
|
||||||
|
throw X_OpFailure{ instr , "invalid texture" };
|
||||||
|
}
|
||||||
|
Globals::ODbg( ).registerTexture( *textures[ svt - 1 ] ,
|
||||||
|
E_ODbgMode( instr.args[ 0 ] ) ,
|
||||||
|
program.uiStrings[ instr.args[ 1 ] ] );
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
instrPtr ++;
|
instrPtr ++;
|
||||||
|
|
|
@ -7,8 +7,8 @@ T_RendertargetSetup::T_RendertargetSetup( )
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
T_RendertargetSetup& T_RendertargetSetup::add(
|
T_RendertargetSetup& T_RendertargetSetup::add(
|
||||||
__rw__ T_Texture& texture ,
|
T_Texture& texture ,
|
||||||
__rd__ const uint32_t level )
|
const uint32_t level )
|
||||||
{
|
{
|
||||||
checkAttachment( texture , level );
|
checkAttachment( texture , level );
|
||||||
colorAttachments_.add( T_Attachment_{ texture , level } );
|
colorAttachments_.add( T_Attachment_{ texture , level } );
|
||||||
|
@ -17,7 +17,7 @@ T_RendertargetSetup& T_RendertargetSetup::add(
|
||||||
|
|
||||||
|
|
||||||
T_RendertargetSetup& T_RendertargetSetup::depth(
|
T_RendertargetSetup& T_RendertargetSetup::depth(
|
||||||
__rw__ T_Texture& texture )
|
T_Texture& texture )
|
||||||
{
|
{
|
||||||
assert( !depthAttachment_ );
|
assert( !depthAttachment_ );
|
||||||
checkAttachment( texture , 0 );
|
checkAttachment( texture , 0 );
|
||||||
|
@ -27,8 +27,8 @@ T_RendertargetSetup& T_RendertargetSetup::depth(
|
||||||
|
|
||||||
|
|
||||||
void T_RendertargetSetup::checkAttachment(
|
void T_RendertargetSetup::checkAttachment(
|
||||||
__rw__ T_Texture const& texture ,
|
T_Texture const& texture ,
|
||||||
__rd__ const uint32_t level )
|
const uint32_t level )
|
||||||
{
|
{
|
||||||
const uint32_t tw( texture.width( ) >> level ) ,
|
const uint32_t tw( texture.width( ) >> level ) ,
|
||||||
th( texture.height( ) >> level );
|
th( texture.height( ) >> level );
|
||||||
|
@ -87,16 +87,38 @@ T_Rendertarget T_RendertargetSetup::create( )
|
||||||
|
|
||||||
/*============================================================================*/
|
/*============================================================================*/
|
||||||
|
|
||||||
|
T_Rendertarget::T_Rendertarget( )
|
||||||
|
{
|
||||||
|
glGenFramebuffers( 1 , &id_ );
|
||||||
|
nCats_ = width_ = height_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void T_Rendertarget::attach(
|
||||||
|
T_Texture const& texture ,
|
||||||
|
const uint32_t lod ,
|
||||||
|
const uint32_t id )
|
||||||
|
{
|
||||||
|
const uint32_t attId( id ? ( GL_COLOR_ATTACHMENT0 + id - 1 ) : GL_DEPTH_ATTACHMENT );
|
||||||
|
glFramebufferTexture( GL_FRAMEBUFFER ,
|
||||||
|
attId ,
|
||||||
|
texture.id( ) ,
|
||||||
|
lod );
|
||||||
|
if ( width_ == 0 ) {
|
||||||
|
width_ = texture.width( ) >> lod;
|
||||||
|
height_ = texture.width( ) >> lod;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
T_Rendertarget::T_Rendertarget(
|
T_Rendertarget::T_Rendertarget(
|
||||||
__rd__ const uint32_t id ,
|
const uint32_t id ,
|
||||||
__rd__ const uint32_t nCats ,
|
const uint32_t nCats ,
|
||||||
__rd__ const uint32_t width ,
|
const uint32_t width ,
|
||||||
__rd__ const uint32_t height )
|
const uint32_t height )
|
||||||
: id_( id ) , nCats_( nCats ) , width_( width ) , height_( height )
|
: id_( id ) , nCats_( nCats ) , width_( width ) , height_( height )
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
T_Rendertarget::T_Rendertarget(
|
T_Rendertarget::T_Rendertarget(
|
||||||
__rw__ T_Rendertarget&& other ) noexcept
|
T_Rendertarget&& other ) noexcept
|
||||||
: id_( 0 ) , nCats_( other.nCats_ ) , width_( other.width_ ) ,
|
: id_( 0 ) , nCats_( other.nCats_ ) , width_( other.width_ ) ,
|
||||||
height_( other.height_ )
|
height_( other.height_ )
|
||||||
{
|
{
|
||||||
|
@ -104,7 +126,7 @@ T_Rendertarget::T_Rendertarget(
|
||||||
}
|
}
|
||||||
|
|
||||||
T_Rendertarget& T_Rendertarget::operator =(
|
T_Rendertarget& T_Rendertarget::operator =(
|
||||||
__rw__ T_Rendertarget&& other ) noexcept
|
T_Rendertarget&& other ) noexcept
|
||||||
{
|
{
|
||||||
swap( id_ , other.id_ );
|
swap( id_ , other.id_ );
|
||||||
swap( nCats_ , other.nCats_ );
|
swap( nCats_ , other.nCats_ );
|
||||||
|
@ -148,6 +170,23 @@ bool T_Rendertarget::activate( )
|
||||||
return id_ != 0;
|
return id_ != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void T_Rendertarget::toggle(
|
||||||
|
const uint32_t id ,
|
||||||
|
const bool active )
|
||||||
|
{
|
||||||
|
assert( id > 0 );
|
||||||
|
const auto realId( GL_COLOR_ATTACHMENT0 + id - 1 );
|
||||||
|
const int32_t idx( buffers_.indexOf( realId ) );
|
||||||
|
if ( active && idx < 0 ) {
|
||||||
|
buffers_.add( realId );
|
||||||
|
} else if ( !active && idx >= 0 ) {
|
||||||
|
buffers_.removeSwap( idx );
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
glDrawBuffers( buffers_.size( ) , &buffers_[ 0 ] );
|
||||||
|
}
|
||||||
|
|
||||||
void T_Rendertarget::MainOutput( )
|
void T_Rendertarget::MainOutput( )
|
||||||
{
|
{
|
||||||
auto const& dspSize( ImGui::GetIO( ).DisplaySize );
|
auto const& dspSize( ImGui::GetIO( ).DisplaySize );
|
||||||
|
|
|
@ -49,9 +49,9 @@ struct T_RendertargetSetup
|
||||||
|
|
||||||
struct T_Rendertarget
|
struct T_Rendertarget
|
||||||
{
|
{
|
||||||
T_Rendertarget( ) = delete;
|
|
||||||
T_Rendertarget( T_Rendertarget const& ) = delete;
|
T_Rendertarget( T_Rendertarget const& ) = delete;
|
||||||
|
|
||||||
|
T_Rendertarget( );
|
||||||
T_Rendertarget(
|
T_Rendertarget(
|
||||||
const GLuint id ,
|
const GLuint id ,
|
||||||
const uint32_t nCats ,
|
const uint32_t nCats ,
|
||||||
|
@ -64,6 +64,11 @@ struct T_Rendertarget
|
||||||
|
|
||||||
~T_Rendertarget( );
|
~T_Rendertarget( );
|
||||||
|
|
||||||
|
void attach( T_Texture const& texture ,
|
||||||
|
uint32_t lod ,
|
||||||
|
uint32_t id );
|
||||||
|
void toggle( uint32_t id , bool active );
|
||||||
|
|
||||||
bool activate( );
|
bool activate( );
|
||||||
|
|
||||||
GLuint id( ) const { return id_; }
|
GLuint id( ) const { return id_; }
|
||||||
|
|
32
shaders.cc
32
shaders.cc
|
@ -700,6 +700,38 @@ T_ShaderPipeline T_ShaderManager::pipeline(
|
||||||
return T_ShaderPipeline{ p.idString };
|
return T_ShaderPipeline{ p.idString };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
T_ShaderPipeline T_ShaderManager::pipeline(
|
||||||
|
T_String const* shaderNames ,
|
||||||
|
uint32_t count )
|
||||||
|
{
|
||||||
|
if ( count < 1 || count > 5 ) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const T_String id( ([shaderNames,count] () {
|
||||||
|
T_StringBuilder sb;
|
||||||
|
for ( auto i = 0u ; i < count ; i ++ ) {
|
||||||
|
sb << shaderNames[ i ] << '|';
|
||||||
|
}
|
||||||
|
sb << '\0';
|
||||||
|
return T_String{ std::move( sb.data( ) ) };
|
||||||
|
} )() );
|
||||||
|
|
||||||
|
auto const* existing( pipelines_.get( id ) );
|
||||||
|
if ( existing ) {
|
||||||
|
return T_ShaderPipeline{ existing->idString };
|
||||||
|
}
|
||||||
|
|
||||||
|
pipelines_.add( T_Pipeline_{ id , shaderNames , count } );
|
||||||
|
auto& p( *pipelines_.get( id ) );
|
||||||
|
for ( auto i = 0u ; i < count ; i ++ ) {
|
||||||
|
loadProgram( p.idString , shaderNames[ i ] );
|
||||||
|
}
|
||||||
|
initPipeline( p );
|
||||||
|
|
||||||
|
return T_ShaderPipeline{ p.idString };
|
||||||
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
void T_ShaderManager::update( )
|
void T_ShaderManager::update( )
|
||||||
|
|
15
shaders.hh
15
shaders.hh
|
@ -181,6 +181,9 @@ struct T_ShaderManager
|
||||||
T_ShaderProgram program( T_String const& name );
|
T_ShaderProgram program( T_String const& name );
|
||||||
T_ShaderPipeline pipeline(
|
T_ShaderPipeline pipeline(
|
||||||
std::initializer_list< T_String > shaders );
|
std::initializer_list< T_String > shaders );
|
||||||
|
T_ShaderPipeline pipeline(
|
||||||
|
T_String const* shaderNames ,
|
||||||
|
uint32_t count );
|
||||||
|
|
||||||
void update( );
|
void update( );
|
||||||
|
|
||||||
|
@ -194,12 +197,22 @@ struct T_ShaderManager
|
||||||
T_String idString;
|
T_String idString;
|
||||||
uint32_t references = 0;
|
uint32_t references = 0;
|
||||||
GLuint id = 0;
|
GLuint id = 0;
|
||||||
T_Array< T_String > programs{ 8 };
|
T_Array< T_String > programs{ 6 };
|
||||||
|
|
||||||
T_Pipeline_( T_String const& id ,
|
T_Pipeline_( T_String const& id ,
|
||||||
std::initializer_list< T_String > shaders )
|
std::initializer_list< T_String > shaders )
|
||||||
: idString{ id } , programs{ shaders }
|
: idString{ id } , programs{ shaders }
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
T_Pipeline_( T_String const& id ,
|
||||||
|
T_String const* const shaderNames ,
|
||||||
|
const uint32_t count ) noexcept
|
||||||
|
: idString{ id }
|
||||||
|
{
|
||||||
|
for ( auto i = 0u ; i < count ; i ++ ) {
|
||||||
|
programs.add( shaderNames[ i ] );
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct T_Program_
|
struct T_Program_
|
||||||
|
|
Loading…
Reference in a new issue