diff --git a/Makefile b/Makefile index 35bc677..794368c 100644 --- a/Makefile +++ b/Makefile @@ -13,6 +13,8 @@ DEMO = \ main.cc \ imgui_impl_sdl.cc \ \ + filewatcher.cc \ + window.cc \ utilities.cc \ texture.cc \ rendertarget.cc \ @@ -20,6 +22,7 @@ DEMO = \ shaders.cc \ camera.cc \ demo.cc \ + globals.cc \ \ raymarcher.cc \ \ diff --git a/bloom.cc b/bloom.cc index ee24bac..387361f 100644 --- a/bloom.cc +++ b/bloom.cc @@ -1,6 +1,7 @@ #include "externals.hh" #include "bloom.hh" #include "profiling.hh" +#include "globals.hh" namespace { static const std::string Name_( "BLOOOOM!" ); @@ -11,12 +12,11 @@ namespace { T_BloomPass::T_BloomPass( - __rw__ T_FilesWatcher& watcher , __rw__ T_Texture& input ) : input_( input ) , - spHighpass_( GL_FRAGMENT_SHADER , watcher ) , - spDownsample_( GL_FRAGMENT_SHADER , watcher ) , - spBlur_( GL_FRAGMENT_SHADER , watcher ) , + spHighpass_( GL_FRAGMENT_SHADER ) , + spDownsample_( GL_FRAGMENT_SHADER ) , + spBlur_( GL_FRAGMENT_SHADER ) , // txBlur0_( input.width( ) , input.height( ) , E_TexType::RGB16F , BloomLevels ) , txBlur1_( input.width( ) , input.height( ) , E_TexType::RGB16F , BloomLevels ) , @@ -46,7 +46,7 @@ void T_BloomPass::render( ) { PSTART( ); - auto& tm( T_TextureManagement::TM( ) ); + auto& tm( Globals::Textures( ) ); if ( spHighpass_.activate( ) && rtBlur0_[ 0 ].activate( ) ) { enum { U_TEXTURE = 0 , diff --git a/bloom.hh b/bloom.hh index 7f8465d..dfadf11 100644 --- a/bloom.hh +++ b/bloom.hh @@ -15,8 +15,7 @@ struct T_BloomPass T_BloomPass( T_BloomPass const& ) = delete; T_BloomPass( T_BloomPass&& ) = delete; - T_BloomPass( __rw__ T_FilesWatcher& watcher , - __rw__ T_Texture& input ); + T_BloomPass( __rw__ T_Texture& input ); void render( ); void makeUI( ); diff --git a/combine.cc b/combine.cc index bc39761..60c39e4 100644 --- a/combine.cc +++ b/combine.cc @@ -2,6 +2,7 @@ #include "combine.hh" #include "bloom.hh" #include "profiling.hh" +#include "globals.hh" namespace { static const std::string Name_( "Combine" ); @@ -12,11 +13,10 @@ namespace { T_CombinePass::T_CombinePass( - __rw__ T_FilesWatcher& watcher , __rw__ T_Texture& image , __rw__ T_Texture& bloom ) : txImage_( image ) , txBloom_( bloom ) , - program_( GL_FRAGMENT_SHADER , watcher ) , + program_( GL_FRAGMENT_SHADER ) , bloomStrength_( 0.45 ) , bloomAttenuation_( 0.3 ) { @@ -31,7 +31,7 @@ void T_CombinePass::render( ) glClearColor( 1 , 0 , 1 , 1 ); glClear( GL_COLOR_BUFFER_BIT ); if ( program_.activate( ) ) { - auto& tm( T_TextureManagement::TM( ) ); + auto& tm( Globals::Textures( ) ); tm.bind( 0 , txImage_ ); tm.bind( 1 , txBloom_ ); glUniform1i( 0 , 0 ); diff --git a/combine.hh b/combine.hh index 825e9bd..6406b31 100644 --- a/combine.hh +++ b/combine.hh @@ -10,8 +10,7 @@ struct T_CombinePass T_CombinePass( T_CombinePass const& ) = delete; T_CombinePass( T_CombinePass&& ) = delete; - T_CombinePass( __rw__ T_FilesWatcher& watcher , - __rw__ T_Texture& image , + T_CombinePass( __rw__ T_Texture& image , __rw__ T_Texture& bloom ); void render( ); diff --git a/demo.cc b/demo.cc index 8f901ba..329a52a 100644 --- a/demo.cc +++ b/demo.cc @@ -2,22 +2,21 @@ #include "demo.hh" -T_Demo::T_Demo( __rw__ T_FilesWatcher& watcher , - __rd__ const uint32_t width , +T_Demo::T_Demo( __rd__ const uint32_t width , __rd__ const uint32_t height ) - : watcher( watcher ) , width( width ) , height( height ) + : width( width ) , height( height ) { } bool T_Demo::initialise( ) { raymarcher = std::make_unique< T_Raymarcher >( - watcher , width , height ); - dof = std::make_unique< T_DoFPass >( watcher , + width , height ); + dof = std::make_unique< T_DoFPass >( raymarcher->output( ) , raymarcher->depth( ) ); - bloom = std::make_unique< T_BloomPass >( watcher , + bloom = std::make_unique< T_BloomPass >( raymarcher->output( ) ); - combine = std::make_unique< T_CombinePass >( watcher , + combine = std::make_unique< T_CombinePass >( dof->output( ) , bloom->output( ) ); return true; } diff --git a/demo.hh b/demo.hh index 03bb471..b646c56 100644 --- a/demo.hh +++ b/demo.hh @@ -15,8 +15,7 @@ struct T_Demo // --------------------------------------------------------------------- - T_Demo( __rw__ T_FilesWatcher& watcher , - __rd__ const uint32_t width , + T_Demo( __rd__ const uint32_t width , __rd__ const uint32_t height ); bool initialise( ); @@ -37,7 +36,6 @@ struct T_Demo // --------------------------------------------------------------------- - T_FilesWatcher& watcher; const uint32_t width; const uint32_t height; diff --git a/dof.cc b/dof.cc index 416027b..d0f2db5 100644 --- a/dof.cc +++ b/dof.cc @@ -1,6 +1,7 @@ #include "externals.hh" #include "dof.hh" #include "profiling.hh" +#include "globals.hh" namespace { static const std::string Name_( "DoF" ); @@ -11,12 +12,11 @@ namespace { T_DoFPass::T_DoFPass( - __rw__ T_FilesWatcher& watcher , __rw__ T_Texture& imageInput , __rw__ T_Texture& depthInput ) : imageInput_( imageInput ) , depthInput_( depthInput ) , - spPass1_( GL_FRAGMENT_SHADER , watcher ) , - spPass2_( GL_FRAGMENT_SHADER , watcher ) , + spPass1_( GL_FRAGMENT_SHADER ) , + spPass2_( GL_FRAGMENT_SHADER ) , txPass1_( imageInput.width( ) , imageInput.height( ) , E_TexType::RGB16F ) , txOutput_( imageInput.width( ) , imageInput.height( ) , @@ -48,7 +48,7 @@ void T_DoFPass::render( ) U_RES_TIME = 4 }; - auto& tm( T_TextureManagement::TM( ) ); + auto& tm( Globals::Textures( ) ); if ( spPass1_.activate( ) && rtPass1_.activate( ) ) { glUniform1i( U_INPUT , 0 ); glUniform1i( U_DEPTH , 1 ); diff --git a/dof.hh b/dof.hh index fec5e32..37a5219 100644 --- a/dof.hh +++ b/dof.hh @@ -9,8 +9,7 @@ struct T_DoFPass T_DoFPass( T_DoFPass const& ) = delete; T_DoFPass( T_DoFPass&& ) = delete; - T_DoFPass( __rw__ T_FilesWatcher& watcher , - __rw__ T_Texture& imageInput , + T_DoFPass( __rw__ T_Texture& imageInput , __rw__ T_Texture& depthInput ); void render( ); diff --git a/filewatcher.cc b/filewatcher.cc new file mode 100644 index 0000000..b76d92e --- /dev/null +++ b/filewatcher.cc @@ -0,0 +1,120 @@ +#include "externals.hh" +#include "filewatcher.hh" +#include "utilities.hh" + + +/*= T_FilesWatcher ===========================================================*/ + +T_FilesWatcher::T_FilesWatcher( ) + : fd( inotify_init1( O_NONBLOCK ) ) +{ } + +T_FilesWatcher::T_FilesWatcher( T_FilesWatcher&& other ) noexcept + : fd( 0 ) , watched( std::move( other.watched ) ) +{ + std::swap( fd , other.fd ); + other.watched.clear( ); + for ( T_WatchedFiles* wf : watched ) { + if ( wf ) { + wf->watcher = this; + } + } +} + +T_FilesWatcher::~T_FilesWatcher( ) +{ + if ( fd ) { + close( fd ); + } + for ( T_WatchedFiles* wf : watched ) { + if ( wf ) { + wf->watcher = nullptr; + } + } +} + +void T_FilesWatcher::check( ) +{ + for ( T_WatchedFiles* wf : watched ) { + if ( wf ) { + wf->triggered = false; + } + } + + inotify_event ie; + while ( read( fd , &ie , sizeof( ie ) ) == sizeof( ie ) ) { + if ( ( ie.mask & ( IN_CLOSE_WRITE | IN_DELETE_SELF ) ) == 0 ) { + continue; + } + + for ( T_WatchedFiles* wf : watched ) { + if ( !wf || wf->triggered ) { + continue; + } + auto const& idl( wf->identifiers ); + if ( find( idl , ie.wd ) != idl.end( ) ) { + wf->triggered = true; + wf->callback( ); + } + } + } +} + +/*= T_WatchedFiles ===========================================================*/ + +T_WatchedFiles::T_WatchedFiles( T_WatchedFiles&& other ) noexcept + : watcher( other.watcher ) , callback( other.callback ) , + triggered( other.triggered ) , + identifiers( std::move( other.identifiers ) ) +{ + if ( watcher ) { + other.watcher = nullptr; + *( find( watcher->watched , &other ) ) = this; + } +} + +T_WatchedFiles::T_WatchedFiles( + __rw__ T_FilesWatcher& watcher , + __rd__ const F_OnFileChanges callback ) + : watcher( &watcher ) , callback( callback ) , triggered( false ) +{ + watcher.watched.push_back( this ); +} + +T_WatchedFiles::~T_WatchedFiles( ) +{ + clear( ); + if ( watcher ) { + watcher->watched.erase( find( watcher->watched , this ) ); + } +} + +void T_WatchedFiles::clear( ) +{ + if ( watcher ) { + const auto fd( watcher->fd ); + for ( int wd : identifiers ) { + inotify_rm_watch( fd , wd ); + } + } + identifiers.clear( ); +} + +bool T_WatchedFiles::watch( + __rd__ std::string const& file ) +{ + static constexpr auto inFlags( IN_CLOSE_WRITE | IN_DELETE_SELF ); + if ( watcher ) { + const auto wd( inotify_add_watch( watcher->fd , + file.c_str( ) , inFlags ) ); + if ( wd == -1 ) { + return false; + } + if ( find( identifiers , wd ) == identifiers.end( ) ) { + identifiers.push_back( wd ); + } + return true; + } + return false; +} + diff --git a/filewatcher.hh b/filewatcher.hh new file mode 100644 index 0000000..51b4219 --- /dev/null +++ b/filewatcher.hh @@ -0,0 +1,55 @@ +#pragma once +#ifndef REAL_BUILD +# include "externals.hh" +#endif + + +/*= T_FilesWatcher / T_WatchedFiles ==========================================*/ + +struct T_FilesWatcher; +struct T_WatchedFiles; +using F_OnFileChanges = std::function< void( void ) >; + +struct T_FilesWatcher +{ + friend struct T_WatchedFiles; + + T_FilesWatcher( T_FilesWatcher const& ) = delete; + + T_FilesWatcher( ); + T_FilesWatcher( T_FilesWatcher&& ) noexcept; + ~T_FilesWatcher( ); + + void check( ); + + private: + int fd; + std::vector< T_WatchedFiles* > watched; +}; + +/*----------------------------------------------------------------------------*/ + +struct T_WatchedFiles +{ + friend struct T_FilesWatcher; + + T_WatchedFiles( ) = delete; + T_WatchedFiles( T_WatchedFiles const& ) = delete; + + T_WatchedFiles( T_WatchedFiles&& ) noexcept; + T_WatchedFiles( + __rw__ T_FilesWatcher& watcher , + __rd__ const F_OnFileChanges callback ); + + ~T_WatchedFiles( ); + + void clear( ); + bool watch( __rd__ std::string const& file ); + + private: + T_FilesWatcher* watcher; + const F_OnFileChanges callback; + bool triggered; + std::vector< int > identifiers; +}; + diff --git a/globals.cc b/globals.cc new file mode 100644 index 0000000..172e455 --- /dev/null +++ b/globals.cc @@ -0,0 +1,34 @@ +#include "externals.hh" +#include "globals.hh" + +#include "filewatcher.hh" +#include "profiling.hh" +#include "texture.hh" +#include "shaders.hh" +#include "window.hh" + + +std::unique_ptr< T_FilesWatcher > Globals::watcher_; +std::unique_ptr< T_Window > Globals::window_; +std::unique_ptr< T_Profiler > Globals::profiler_; +std::unique_ptr< T_TextureManager > Globals::textures_; +std::unique_ptr< T_ShaderManager > Globals::shaders_; + + +void Globals::Init( ) +{ + watcher_ = std::make_unique< T_FilesWatcher >( ); + window_ = std::make_unique< T_Window >( ); + profiler_ = std::make_unique< T_Profiler >( ); + textures_ = std::make_unique< T_TextureManager >( ); + shaders_ = std::make_unique< T_ShaderManager >( ); +} + +void Globals::Shutdown( ) +{ + shaders_.reset( ); + textures_.reset( ); + profiler_.reset( ); + window_.reset( ); + watcher_.reset( ); +} diff --git a/globals.hh b/globals.hh new file mode 100644 index 0000000..19f516a --- /dev/null +++ b/globals.hh @@ -0,0 +1,31 @@ +#pragma once +#ifndef REAL_BUILD +# include "externals.hh" +#endif + + +struct T_Window; +struct T_FilesWatcher; +struct T_Profiler; +struct T_TextureManager; +struct T_ShaderManager; + + +struct Globals +{ + static void Init( ); + static void Shutdown( ); + + static T_FilesWatcher& Watcher( ) { return *watcher_; } + static T_Window& Window( ) { return *window_; } + static T_Profiler& Profiler( ) { return *profiler_; } + static T_TextureManager& Textures( ) { return *textures_; } + static T_ShaderManager& Shaders( ) { return *shaders_; } + + private: + static std::unique_ptr< T_FilesWatcher > watcher_; + static std::unique_ptr< T_Window > window_; + static std::unique_ptr< T_Profiler > profiler_; + static std::unique_ptr< T_ShaderManager > shaders_; + static std::unique_ptr< T_TextureManager > textures_; +}; diff --git a/main.cc b/main.cc index 822c102..51ff500 100644 --- a/main.cc +++ b/main.cc @@ -2,7 +2,11 @@ #include "imgui_impl_sdl.h" #include "demo.hh" +#include "globals.hh" #include "profiling.hh" +#include "window.hh" +#include "shaders.hh" +// FIXME ^^ /*= T_Main ===================================================================*/ @@ -15,16 +19,11 @@ struct T_Main void mainLoop( ); private: - const std::string projectFile; - SDL_Window * window; - SDL_GLContext gl; - bool done = false; bool capture = false; ImVec2 mouseInitial; ImVec2 mouseMove; - T_FilesWatcher watcher; std::unique_ptr< T_ShaderProgram > spCopy; std::unique_ptr< T_Demo > demo; @@ -43,30 +42,13 @@ struct T_Main T_Main::T_Main( ) { - SDL_Init( SDL_INIT_VIDEO | SDL_INIT_TIMER ); - - // Setup window - SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER , 1 ); - SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE , 24 ); - SDL_GL_SetAttribute( SDL_GL_STENCIL_SIZE , 8 ); - SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION , 2 ); - SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION , 2 ); - SDL_DisplayMode current; - SDL_GetCurrentDisplayMode( 0 , ¤t ); - window = SDL_CreateWindow( "DEMO", - SDL_WINDOWPOS_CENTERED , SDL_WINDOWPOS_CENTERED , - 1280 , 720 , - SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE ); - gl = SDL_GL_CreateContext( window ); - glewInit(); - ImGui_ImplSdl_Init( window ); - + Globals::Init( ); initProgram( ); } void T_Main::mainLoop( ) { - auto& p( T_Profiler::Profiler ); + auto& p( Globals::Profiler( ) ); while ( !done ) { if ( demo ) { auto const& dspSize( ImGui::GetIO( ).DisplaySize ); @@ -80,15 +62,15 @@ void T_Main::mainLoop( ) glFinish( ); p.startFrame( ); - T_Profiler::Profiler.start( "Full frame" ); + p.start( "Full frame" ); startIteration( ); if ( !done ) { handleCapture( ); makeUI( ); - watcher.check( ); render( ); - T_Profiler::Profiler.end( "Full frame" ); - SDL_GL_SwapWindow( window ); + p.end( "Full frame" ); + Globals::Window( ).swap( ); + Globals::Watcher( ).check( ); p.endFrame( ); } } @@ -97,11 +79,7 @@ void T_Main::mainLoop( ) T_Main::~T_Main( ) { demo.reset( ); - T_TextureManagement::Shutdown( ); - ImGui_ImplSdl_Shutdown( ); - SDL_GL_DeleteContext( gl ); - SDL_DestroyWindow( window ); - SDL_Quit( ); + Globals::Shutdown( ); } /*----------------------------------------------------------------------------*/ @@ -115,9 +93,9 @@ void T_Main::initDemo( ) } printf( "init w/ dspsize %dx%d\n" , int( dspSize.x ) , int( dspSize.y ) ); - demo = std::make_unique< T_Demo >( watcher , dspSize.x , dspSize.y ); + demo = std::make_unique< T_Demo >( dspSize.x , dspSize.y ); if ( demo->initialise( ) ) { - T_Profiler::Profiler.clear( ); + Globals::Profiler( ).clear( ); } else { demo.reset( ); } @@ -140,7 +118,7 @@ void T_Main::startIteration( ) } } - ImGui_ImplSdl_NewFrame( window , capture , mouseInitial ); + Globals::Window( ).startFrame( capture , mouseInitial ); ImGui::GetIO( ).MouseDrawCursor = true; } @@ -159,9 +137,7 @@ void T_Main::handleCapture( ) capture = false; ImGui::CaptureMouseFromApp( false ); SDL_SetRelativeMouseMode( SDL_FALSE ); - SDL_WarpMouseInWindow( window , - int( mouseInitial.x ) , - int( mouseInitial.y ) ); + Globals::Window( ).warpMouse( mouseInitial ); ImGui::SetMouseCursor( ImGuiMouseCursor_Arrow ); } else if ( capture ) { ImGui::SetMouseCursor( ImGuiMouseCursor_Move ); @@ -188,31 +164,31 @@ void T_Main::makeUI( ) ImGuiSetCond_Once ); ImGui::SetNextWindowPos( ImVec2( ) , ImGuiSetCond_Once ); ImGui::Begin( "Yay! Demo!" ); - ImGui::Checkbox( "Profiler" , &T_Profiler::Profiler.uiEnabled( ) ); + ImGui::Checkbox( "Profiler" , &Globals::Profiler( ).uiEnabled( ) ); if ( demo ) { demo->makeUI( ); } ImGui::End( ); - T_Profiler::Profiler.makeUI( ); + Globals::Profiler( ).makeUI( ); } void T_Main::render( ) { if ( demo ) { - T_Profiler::Profiler.start( "Render" ); + Globals::Profiler( ).start( "Render" ); demo->render( ); - glFinish( ); T_Profiler::Profiler.end( "Render" ); + glFinish( ); Globals::Profiler( ).end( "Render" ); } glUseProgram( 0 ); - T_TextureManagement::TM( ).reset( ); + Globals::Textures( ).reset( ); ImGui::Render( ); } void T_Main::initProgram( ) { - spCopy = std::make_unique< T_ShaderProgram >( GL_FRAGMENT_SHADER , watcher ); + spCopy = std::make_unique< T_ShaderProgram >( GL_FRAGMENT_SHADER ); spCopy->addFile( "copy.glsl" ); spCopy->load( ); } @@ -223,20 +199,10 @@ void T_Main::initProgram( ) int main( int , char** ) { T_Main m; +#if 0 + testLoadShaderFile( ); +#else m.mainLoop( ); - -#if 0 - // Frame time history - const int nFrameTimes = 200; - float frameTimes[ nFrameTimes ]; - memset( frameTimes , 0 , sizeof( float ) * nFrameTimes ); #endif -#if 0 - // Update frame time history - memmove( frameTimes , &frameTimes[ 1 ] , - ( nFrameTimes - 1 ) * sizeof( float ) ); - frameTimes[ nFrameTimes - 1 ] = 1000.0f / ImGui::GetIO( ).Framerate; -#endif - return 0; } diff --git a/programs.cc b/programs.cc index 8a65fd5..ce91d82 100644 --- a/programs.cc +++ b/programs.cc @@ -1,5 +1,6 @@ #include "externals.hh" #include "programs.hh" +#include "globals.hh" /*= T_ShaderCode =============================================================*/ @@ -144,9 +145,8 @@ GLuint T_ShaderCode::createProgram( /*= T_ShaderProgram ==========================================================*/ T_ShaderProgram::T_ShaderProgram( - __rd__ const GLenum programType , - __rw__ T_FilesWatcher& watcher ) - : files_( watcher , [this] { load( ); } ) , + __rd__ const GLenum programType ) + : files_( Globals::Watcher( ) , [this] { load( ); } ) , programType_( programType ) , program_( 0 ) { } @@ -245,12 +245,11 @@ namespace { std::unique_ptr< T_ShaderProgram > FsQuad_; } -T_ShaderProgram const& T_ShaderProgram::FullscreenQuad( - __rw__ T_FilesWatcher& watcher ) +T_ShaderProgram const& T_ShaderProgram::FullscreenQuad( ) { if ( !FsQuad_ ) { FsQuad_ = std::make_unique< T_ShaderProgram >( - GL_VERTEX_SHADER , watcher ); + GL_VERTEX_SHADER ); FsQuad_->addFile( "fsquad.glsl" ); FsQuad_->load( ); } diff --git a/programs.hh b/programs.hh index c6636d3..99981b6 100644 --- a/programs.hh +++ b/programs.hh @@ -1,6 +1,6 @@ #pragma once -#include "utilities.hh" +#include "filewatcher.hh" /*= T_ShaderCode =============================================================*/ @@ -40,9 +40,7 @@ struct T_ShaderProgram T_ShaderProgram( T_ShaderProgram const& ) = delete; T_ShaderProgram( T_ShaderProgram&& ) = delete; - T_ShaderProgram( - __rd__ GLenum programType , - __rw__ T_FilesWatcher& watcher ); + T_ShaderProgram( __rd__ GLenum programType ); ~T_ShaderProgram( ); void addChunk( __rd__ std::string const& string ); @@ -53,8 +51,7 @@ struct T_ShaderProgram GLuint id( ) const { return program_; } - static T_ShaderProgram const& FullscreenQuad( - __rw__ T_FilesWatcher& watcher ); + static T_ShaderProgram const& FullscreenQuad( ); private: T_WatchedFiles files_; diff --git a/raymarcher.cc b/raymarcher.cc index 641f201..ef86630 100644 --- a/raymarcher.cc +++ b/raymarcher.cc @@ -12,10 +12,9 @@ namespace { T_Raymarcher::T_Raymarcher( - __rw__ T_FilesWatcher& watcher , __rd__ const uint32_t width , __rd__ const uint32_t height ) - : camera_( ) , program_( GL_FRAGMENT_SHADER , watcher ) , + : camera_( ) , program_( GL_FRAGMENT_SHADER ) , txOutput_( width , height , E_TexType::RGB16F ) , txDepth_( width , height , E_TexType::R16F ) , rtOutput_( T_RendertargetSetup( ) diff --git a/raymarcher.hh b/raymarcher.hh index 3aff311..57b7d3a 100644 --- a/raymarcher.hh +++ b/raymarcher.hh @@ -12,8 +12,7 @@ struct T_Raymarcher T_Raymarcher( T_Raymarcher const& ) = delete; T_Raymarcher( T_Raymarcher&& ) = delete; - T_Raymarcher( __rw__ T_FilesWatcher& watcher , - __rd__ const uint32_t width , + T_Raymarcher( __rd__ const uint32_t width , __rd__ const uint32_t height ); void render( ); diff --git a/shaders.cc b/shaders.cc index 414958c..05d4a81 100644 --- a/shaders.cc +++ b/shaders.cc @@ -1,5 +1,6 @@ #include "externals.hh" #include "shaders.hh" +#include "globals.hh" namespace { @@ -14,6 +15,8 @@ const std::map< std::string , E_ShaderInput > InputTypes_( ([] { t.emplace( "vertex" , E_ShaderInput::VERTEX ); t.emplace( "fragment" , E_ShaderInput::FRAGMENT ); t.emplace( "compute" , E_ShaderInput::COMPUTE ); + t.emplace( "geo" , E_ShaderInput::GEOMETRY ); + t.emplace( "geometry" , E_ShaderInput::GEOMETRY ); return t; })()); @@ -313,34 +316,62 @@ void T_CodeBuilder_::next( ) /*============================================================================*/ +T_ShaderCodeLoader::T_ShaderCodeLoader( + __rw__ T_FilesWatcher& watcher ) + : watcher_( watcher ) +{ +} + bool T_ShaderCodeLoader::load( __rd__ std::string const& name , __wr__ T_Frankenshader& code ) { T_CodeBuilder_ cb( *this , name , code ); - return cb.buildCode( ); + const bool rv( cb.buildCode( ) ); + + // Update dependencies + for ( auto const& dep : code.files ) { + deps_[ name ].insert( dep.first ); + } + + return rv; } T_ShaderInput const* T_ShaderCodeLoader::getInput( __rd__ std::string const& name ) { - auto pos( files.find( name ) ); - if ( pos != files.end( ) ) { + auto pos( inputs_.find( name ) ); + if ( pos != inputs_.end( ) ) { return pos->second.get( ); } T_ShaderInput ni; if ( !ni.load( "shaders/" + name ) ) { return nullptr; } - files.emplace( name , std::make_unique< T_ShaderInput >( - std::move( ni ) ) ); - return files.find( name )->second.get( ); + inputs_.emplace( name , std::make_unique< T_ShaderInput >( std::move( ni ) ) ); + return inputs_.find( name )->second.get( ); } void T_ShaderCodeLoader::removeInput( __rd__ std::string const& name ) { - files.erase( name ); + inputs_.erase( name ); +} + +void T_ShaderCodeLoader::onFileUpdated( + __rd__ std::string const& name ) +{ + inputs_.erase( name ); + auto& deps( deps_[ name ] ); + for ( auto const& dep : deps ) { + pending_.insert( dep ); + } +} + + +bool T_ShaderPipeline::valid( ) const noexcept +{ + return Globals::Shaders( ).pipelines_[ smIndex_ ].id != 0; } @@ -348,7 +379,7 @@ void T_ShaderCodeLoader::removeInput( void testLoadShaderFile( ) { const std::string source( "test-loader.glsl" ); - T_ShaderCodeLoader loader; + T_ShaderCodeLoader loader( Globals::Watcher( ) ); T_Frankenshader code; if ( loader.load( source , code ) ) { printf( "SUCCESS! TYPE = %d\n" , int( code.type ) ); diff --git a/shaders.hh b/shaders.hh index a09a0c4..7d1c582 100644 --- a/shaders.hh +++ b/shaders.hh @@ -1,4 +1,5 @@ #pragma once +#include "filewatcher.hh" #include "utilities.hh" @@ -32,7 +33,8 @@ enum class E_ShaderInput { LIBRARY , // Library (will only be loaded once) // "Main" shader source files - VERTEX , FRAGMENT , COMPUTE + VERTEX , FRAGMENT , GEOMETRY , + COMPUTE }; // Preprocessing errors @@ -56,7 +58,8 @@ using P_ShaderInput = std::unique_ptr< T_ShaderInput >; // Type of shader enum class E_ShaderType { - VERTEX , FRAGMENT , COMPUTE + VERTEX , FRAGMENT , COMPUTE , + __COUNT__ }; @@ -83,9 +86,42 @@ struct T_Frankenshader }; using P_Frankenshader = std::unique_ptr< T_Frankenshader >; +// A shader program +struct T_ShaderProgram2 // FIXME: name +{ + ~T_ShaderProgram2( ) // XXX pipelines, notify loader + { if ( valid( ) ) glDeleteProgram( id_ ); } + + + bool valid( ) const noexcept + { return id_ != 0; } + std::string const& name( ) const noexcept + { return name_; } + GLuint id( ) const noexcept + { return id_; } + + bool activate( ) const + { + if ( valid( ) ) { + glUseProgram( id_ ); + GL_CHECK( return false ); + } + return valid( ); + } + + private: + std::string name_; + E_ShaderType type_; + GLuint id_; +}; + // XXX test for the loader struct T_ShaderCodeLoader { + T_ShaderCodeLoader( ) = delete; + explicit T_ShaderCodeLoader( + __rw__ T_FilesWatcher& watcher ); + bool load( __rd__ std::string const& name , __wr__ T_Frankenshader& code ); @@ -93,7 +129,55 @@ struct T_ShaderCodeLoader void removeInput( __rd__ std::string const& name ); private: - std::map< std::string , P_ShaderInput > files; + T_FilesWatcher& watcher_; + + std::set< std::string > pending_; + std::map< std::string , P_ShaderInput > inputs_; + std::map< std::string , P_Frankenshader > code_; + std::map< std::string , std::set< std::string > > deps_; + + void onFileUpdated( __rd__ std::string const& name ); +}; + + +struct T_ShaderPipeline +{ + bool valid( ) const noexcept; + void enable( ) const; + + private: + uint32_t smIndex_; +}; + + +struct T_ShaderManager +{ + friend struct T_ShaderPipeline; + + T_ShaderPipeline pipeline( + __rd__ std::initializer_list< std::string > shaders ); + + private: + struct T_Pipeline_ + { + uint32_t references; + std::string idString; + GLuint id; + int32_t programs[ size_t( E_ShaderType::__COUNT__ ) ]; + }; + + struct T_Program_ + { + uint32_t references; + std::string name; + E_ShaderType type; + GLuint id; + }; + + std::vector< T_Pipeline_ > pipelines_; + std::map< std::string , uint32_t > pipelineIndex_; + + std::vector< T_Program_ > program_; }; diff --git a/texture.cc b/texture.cc index ddbd603..26b2326 100644 --- a/texture.cc +++ b/texture.cc @@ -256,25 +256,10 @@ void T_TextureSampler::setSamplingMode( ) const /*============================================================================*/ -constexpr uint32_t T_TextureManagement::MaxUnits; -std::unique_ptr< T_TextureManagement > T_TextureManagement::instance_; +constexpr uint32_t T_TextureManager::MaxUnits; -T_TextureManagement& T_TextureManagement::TM( ) -{ - if ( !instance_ ) { - instance_.reset( new T_TextureManagement( ) ); - } - return *instance_; -} - -void T_TextureManagement::Shutdown( ) -{ - instance_.reset( ); -} - - -T_TextureManagement::T_TextureManagement( ) +T_TextureManager::T_TextureManager( ) { std::shared_ptr< T_TextureSampler > tsam; @@ -295,7 +280,7 @@ T_TextureManagement::T_TextureManagement( ) samplers_[ "linear-border" ] = tsam; } -T_TextureSampler const* T_TextureManagement::sampler( +T_TextureSampler const* T_TextureManager::sampler( __rd__ std::string const& name ) const { auto pos( samplers_.find( name ) ); @@ -305,7 +290,7 @@ T_TextureSampler const* T_TextureManagement::sampler( return (*pos).second.get( ); } -void T_TextureManagement::bind( +void T_TextureManager::bind( __rd__ const uint32_t unit , __rd__ T_Texture const& texture ) { @@ -320,7 +305,7 @@ void T_TextureManagement::bind( glBindSampler( unit , 0 ); } -void T_TextureManagement::bind( +void T_TextureManager::bind( __rd__ const uint32_t unit , __rd__ T_Texture const& texture , __rd__ T_TextureSampler const& sampler ) @@ -336,7 +321,7 @@ void T_TextureManagement::bind( glBindSampler( unit , sampler.id( ) ); } -void T_TextureManagement::reset( ) +void T_TextureManager::reset( ) { for ( auto i = 0u ; i < MaxUnits ; i ++ ) { auto& u( bindings_[ i ] ); diff --git a/texture.hh b/texture.hh index 40c1f6e..cff5002 100644 --- a/texture.hh +++ b/texture.hh @@ -103,15 +103,14 @@ struct T_TextureSampler }; -struct T_TextureManagement +struct T_TextureManager { static constexpr uint32_t MaxUnits = 8; - NO_COPY( T_TextureManagement ); - NO_MOVE( T_TextureManagement ); + T_TextureManager( ); - static T_TextureManagement& TM( ); - static void Shutdown( ); + NO_COPY( T_TextureManager ); + NO_MOVE( T_TextureManager ); void reset( ); T_TextureSampler const* sampler( @@ -124,10 +123,6 @@ struct T_TextureManagement __rd__ T_TextureSampler const& sampler ); private: - static std::unique_ptr< T_TextureManagement > instance_; - - T_TextureManagement( ); - struct T_Binding_ { GLuint texture = 0; diff --git a/utilities.cc b/utilities.cc index cecf429..04b5b08 100644 --- a/utilities.cc +++ b/utilities.cc @@ -39,119 +39,3 @@ void anglesToMatrix( matrix[7] = s[0]*c[1]; matrix[8] = c[0]*c[1]; } - - -/*= T_FilesWatcher ===========================================================*/ - -T_FilesWatcher::T_FilesWatcher( ) - : fd( inotify_init1( O_NONBLOCK ) ) -{ } - -T_FilesWatcher::T_FilesWatcher( T_FilesWatcher&& other ) noexcept - : fd( 0 ) , watched( std::move( other.watched ) ) -{ - std::swap( fd , other.fd ); - other.watched.clear( ); - for ( T_WatchedFiles* wf : watched ) { - if ( wf ) { - wf->watcher = this; - } - } -} - -T_FilesWatcher::~T_FilesWatcher( ) -{ - if ( fd ) { - close( fd ); - } - for ( T_WatchedFiles* wf : watched ) { - if ( wf ) { - wf->watcher = nullptr; - } - } -} - -void T_FilesWatcher::check( ) -{ - for ( T_WatchedFiles* wf : watched ) { - if ( wf ) { - wf->triggered = false; - } - } - - inotify_event ie; - while ( read( fd , &ie , sizeof( ie ) ) == sizeof( ie ) ) { - if ( ( ie.mask & ( IN_CLOSE_WRITE | IN_DELETE_SELF ) ) == 0 ) { - continue; - } - - for ( T_WatchedFiles* wf : watched ) { - if ( !wf || wf->triggered ) { - continue; - } - auto const& idl( wf->identifiers ); - if ( find( idl , ie.wd ) != idl.end( ) ) { - wf->triggered = true; - wf->callback( ); - } - } - } -} - -/*= T_WatchedFiles ===========================================================*/ - -T_WatchedFiles::T_WatchedFiles( T_WatchedFiles&& other ) noexcept - : watcher( other.watcher ) , callback( other.callback ) , - triggered( other.triggered ) , - identifiers( std::move( other.identifiers ) ) -{ - if ( watcher ) { - other.watcher = nullptr; - *( find( watcher->watched , &other ) ) = this; - } -} - -T_WatchedFiles::T_WatchedFiles( - __rw__ T_FilesWatcher& watcher , - __rd__ const F_OnFileChanges callback ) - : watcher( &watcher ) , callback( callback ) , triggered( false ) -{ - watcher.watched.push_back( this ); -} - -T_WatchedFiles::~T_WatchedFiles( ) -{ - clear( ); - if ( watcher ) { - watcher->watched.erase( find( watcher->watched , this ) ); - } -} - -void T_WatchedFiles::clear( ) -{ - if ( watcher ) { - const auto fd( watcher->fd ); - for ( int wd : identifiers ) { - inotify_rm_watch( fd , wd ); - } - } - identifiers.clear( ); -} - -bool T_WatchedFiles::watch( - __rd__ std::string const& file ) -{ - static constexpr auto inFlags( IN_CLOSE_WRITE | IN_DELETE_SELF ); - if ( watcher ) { - const auto wd( inotify_add_watch( watcher->fd , - file.c_str( ) , inFlags ) ); - if ( wd == -1 ) { - return false; - } - if ( find( identifiers , wd ) == identifiers.end( ) ) { - identifiers.push_back( wd ); - } - return true; - } - return false; -} diff --git a/utilities.hh b/utilities.hh index eeda6f0..a113218 100644 --- a/utilities.hh +++ b/utilities.hh @@ -58,53 +58,3 @@ inline auto find( { return std::find( collection.begin( ) , collection.end( ) , item ); } - - -/*= T_FilesWatcher / T_WatchedFiles ==========================================*/ - -struct T_FilesWatcher; -struct T_WatchedFiles; -using F_OnFileChanges = std::function< void( void ) >; - -struct T_FilesWatcher -{ - friend struct T_WatchedFiles; - - T_FilesWatcher( T_FilesWatcher const& ) = delete; - - T_FilesWatcher( ); - T_FilesWatcher( T_FilesWatcher&& ) noexcept; - ~T_FilesWatcher( ); - - void check( ); - - private: - int fd; - std::vector< T_WatchedFiles* > watched; -}; - -/*----------------------------------------------------------------------------*/ - -struct T_WatchedFiles -{ - friend struct T_FilesWatcher; - - T_WatchedFiles( ) = delete; - T_WatchedFiles( T_WatchedFiles const& ) = delete; - - T_WatchedFiles( T_WatchedFiles&& ) noexcept; - T_WatchedFiles( - __rw__ T_FilesWatcher& watcher , - __rd__ const F_OnFileChanges callback ); - - ~T_WatchedFiles( ); - - void clear( ); - bool watch( __rd__ std::string const& file ); - - private: - T_FilesWatcher* watcher; - const F_OnFileChanges callback; - bool triggered; - std::vector< int > identifiers; -}; diff --git a/window.cc b/window.cc new file mode 100644 index 0000000..d57b2ca --- /dev/null +++ b/window.cc @@ -0,0 +1,56 @@ +#include "externals.hh" +#include "window.hh" +#include "imgui_impl_sdl.h" + + +T_Window::T_Window( ) +{ + SDL_Init( SDL_INIT_VIDEO | SDL_INIT_TIMER ); + + SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER , 1 ); + SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE , 24 ); + SDL_GL_SetAttribute( SDL_GL_STENCIL_SIZE , 8 ); + SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION , 2 ); + SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION , 2 ); + + SDL_DisplayMode current; + SDL_GetCurrentDisplayMode( 0 , ¤t ); + window = SDL_CreateWindow( "DEMO", + SDL_WINDOWPOS_CENTERED , SDL_WINDOWPOS_CENTERED , + 1280 , 720 , + SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE ); + gl = SDL_GL_CreateContext( window ); + glewInit( ); + if ( !GLEW_VERSION_4_5 ) { + fprintf( stderr , "OpenGL 4.5 required\n" ); + exit( 1 ); + } + + ImGui_ImplSdl_Init( window ); +} + +T_Window::~T_Window( ) +{ + ImGui_ImplSdl_Shutdown( ); + SDL_GL_DeleteContext( gl ); + SDL_DestroyWindow( window ); + SDL_Quit( ); +} + +void T_Window::startFrame( + __rd__ const bool capture , + __rd__ ImVec2 const& mouseInitial ) const +{ + ImGui_ImplSdl_NewFrame( window , capture , mouseInitial ); +} + +void T_Window::warpMouse( + __rd__ ImVec2 const& pos ) const +{ + SDL_WarpMouseInWindow( window , pos.x , pos.y ); +} + +void T_Window::swap( ) const +{ + SDL_GL_SwapWindow( window ); +} diff --git a/window.hh b/window.hh new file mode 100644 index 0000000..aab9ca6 --- /dev/null +++ b/window.hh @@ -0,0 +1,22 @@ +#pragma once +#ifndef REAL_BUILD +# include "externals.hh" +#endif + + +struct T_Window +{ + T_Window( ); + ~T_Window( ); + + void startFrame( __rd__ const bool capture , + __rd__ ImVec2 const& mouseInitial ) const; + void warpMouse( __rd__ ImVec2 const& pos ) const; + + void swap( ) const; + + private: + SDL_Window * window; + SDL_GLContext gl; +}; +