diff --git a/uniforms.cc b/uniforms.cc index 722305d..3d90a00 100644 --- a/uniforms.cc +++ b/uniforms.cc @@ -1,4 +1,5 @@ #include "externals.hh" +#include "utilities.hh" #include "uniforms.hh" @@ -203,3 +204,144 @@ uint32_t T_UniformSet::position( assert( ePos != packed_[ ci ].positions.end( ) ); return ePos->second; } + + +/*= T_UniformStorage =========================================================*/ + +T_UniformStorage::T_UniformStorage( + __rw__ T_UniformSet&& uniforms ) + : uniforms_( std::move( uniforms ) ) +{ + values_.resize( uniforms_.opaqueElements( ) + + uniforms_.vectorElements( ) , 0 ); + + uint32_t pos = 0; + for ( auto i = 0 ; i < int( E_UniformCategory::__COUNT__ ) ; i ++ ) { + starts_[ i ] = pos; + pos += uniforms_.inCategory( E_UniformCategory( i ) ); + } +} + +float* T_UniformStorage::getf( + __rd__ std::string const& name ) +{ + auto const& dPos( uniforms_.declarations( ).find( name ) ); + if ( dPos == uniforms_.declarations( ).end( ) ) { + return nullptr; + } + auto const& decl( dPos->second ); + + const auto cat( GetUniformCategory( decl.type ) ); + const auto pos( starts_[ int( cat ) ] + uniforms_.position( name ) ); + return reinterpret_cast< float* >( &values_[ pos ] ); +} + +int* T_UniformStorage::geti( + __rd__ std::string const& name ) +{ + auto const& dPos( uniforms_.declarations( ).find( name ) ); + if ( dPos == uniforms_.declarations( ).end( ) ) { + return nullptr; + } + auto const& decl( dPos->second ); + + const auto cat( GetUniformCategory( decl.type ) ); + const auto pos( starts_[ int( cat ) ] + uniforms_.position( name ) ); + return &values_[ pos ]; +} + + +/*= T_ProgramUniforms ========================================================*/ + +T_ProgramUniforms::T_ProgramUniforms( + __rw__ T_UniformSet uniforms ) + : T_UniformStorage( std::move( uniforms ) ) +{ } + +void T_ProgramUniforms::apply( + __rd__ const GLuint id ) +{ + GLuint uLoc( 0 ); + for ( auto i = 0 ; i < int( E_UniformCategory::__COUNT__ ) ; i ++ ) { + const auto cat{ E_UniformCategory( i ) }; + const auto count{ uniforms_.inCategory( cat ) }; + if ( count != 0 ) { + switch ( cat ) { + case E_UniformCategory::FLOAT: + glProgramUniform4fv( id , uLoc , count / 4 , + reinterpret_cast< float* >( &values_[ starts_[ i ] ] ) ); + uLoc += count / 4; + break; + case E_UniformCategory::INT: + glProgramUniform4iv( id , uLoc , count / 4 , + &values_[ starts_[ i ] ] ); + uLoc += count / 4; + break; + case E_UniformCategory::SAMPLER2D: + glProgramUniform1iv( id , uLoc , count , + &values_[ starts_[ i ] ] ); + uLoc += count; + break; + + case E_UniformCategory::__COUNT__: + std::abort( ); + } + } + } +} + + +/*= T_UniformBuffer ==========================================================*/ + +T_UniformBuffer::T_UniformBuffer( + __rw__ T_UniformSet set ) + : T_UniformStorage( std::move( set ) ) , buffer_( 0 ) +{ + assert( uniforms_.opaqueElements( ) == 0 ); + + glGenBuffers( 1 , &buffer_ ); + glBindBuffer( GL_UNIFORM_BUFFER , buffer_ ); + glBufferData( GL_UNIFORM_BUFFER , values_.size( ) * 4 , &values_[ 0 ] , GL_STREAM_DRAW ); + GL_ASSERT( ); +} + +T_UniformBuffer::T_UniformBuffer( + __rw__ T_UniformBuffer&& ori ) noexcept + : T_UniformStorage( std::move( ori ) ) , buffer_( 0 ) +{ + std::swap( buffer_ , ori.buffer_ ); +} + +T_UniformBuffer& T_UniformBuffer::operator=( + __rw__ T_UniformBuffer&& other ) noexcept +{ + if ( buffer_ ) { + glBindBuffer( GL_UNIFORM_BUFFER , 0 ); + glDeleteBuffers( 1 , &buffer_ ); + buffer_ = 0; + } + std::swap( buffer_ , other.buffer_ ); + T_UniformStorage::operator=( std::move( other ) ); + return *this; +} + +void T_UniformBuffer::update( ) +{ + glBindBuffer( GL_UNIFORM_BUFFER , buffer_ ); + glInvalidateBufferData( GL_UNIFORM_BUFFER ); + glBufferData( GL_UNIFORM_BUFFER , values_.size( ) * 4 , &values_[ 0 ] , GL_STREAM_DRAW ); +} + +void T_UniformBuffer::bindTo( + __rd__ const GLuint binding ) +{ + glBindBufferBase( GL_UNIFORM_BUFFER , binding , buffer_ ); +} + +T_UniformBuffer::~T_UniformBuffer( ) +{ + if ( buffer_ ) { + glBindBuffer( GL_UNIFORM_BUFFER , 0 ); + glDeleteBuffers( 1 , &buffer_ ); + } +} diff --git a/uniforms.hh b/uniforms.hh index d73025f..2678bf6 100644 --- a/uniforms.hh +++ b/uniforms.hh @@ -43,6 +43,8 @@ struct T_UniformDeclaration using T_UniformDeclarations = std::unordered_map< std::string , T_UniformDeclaration >; +/*============================================================================*/ + // Packed uniforms struct T_PackedUniforms { @@ -94,3 +96,57 @@ struct T_UniformSet uint32_t vectorElements_ , opaqueElements_; T_PackedUniforms packed_[ int( E_UniformCategory::__COUNT__ ) ]; }; + + +/*============================================================================*/ + +struct T_UniformStorage +{ + T_UniformStorage( ) = delete; + NO_COPY( T_UniformStorage ); + DEF_MOVE( T_UniformStorage ); + + explicit T_UniformStorage( + __rw__ T_UniformSet&& uniforms ); + + float* getf( + __rd__ std::string const& name ); + int* geti( + __rd__ std::string const& name ); + + protected: + T_UniformSet uniforms_; + uint32_t starts_[ int( E_UniformCategory::__COUNT__ ) ]; + std::vector< int > values_; +}; + +struct T_ProgramUniforms : public T_UniformStorage +{ + T_ProgramUniforms( ) = delete; + NO_COPY( T_ProgramUniforms ); + DEF_MOVE( T_ProgramUniforms ); + + explicit T_ProgramUniforms( + __rw__ T_UniformSet uniforms ); + + void apply( + __rd__ const GLuint id ); +}; + +struct T_UniformBuffer : public T_UniformStorage +{ + T_UniformBuffer( ) = delete; + NO_COPY( T_UniformBuffer ); + + explicit T_UniformBuffer( + __rw__ T_UniformSet uniforms ); + MOVE( T_UniformBuffer ); + ~T_UniformBuffer( ); + + void update( ); + void bindTo( + __rd__ const GLuint binding ); + + private: + GLuint buffer_; +};