Uniforms storage

This commit is contained in:
Emmanuel BENOîT 2017-10-09 12:49:08 +02:00
parent ab4416ed58
commit 84ebc69d54
2 changed files with 198 additions and 0 deletions

View file

@ -1,4 +1,5 @@
#include "externals.hh" #include "externals.hh"
#include "utilities.hh"
#include "uniforms.hh" #include "uniforms.hh"
@ -203,3 +204,144 @@ uint32_t T_UniformSet::position(
assert( ePos != packed_[ ci ].positions.end( ) ); assert( ePos != packed_[ ci ].positions.end( ) );
return ePos->second; 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_ );
}
}

View file

@ -43,6 +43,8 @@ struct T_UniformDeclaration
using T_UniformDeclarations = std::unordered_map< std::string , T_UniformDeclaration >; using T_UniformDeclarations = std::unordered_map< std::string , T_UniformDeclaration >;
/*============================================================================*/
// Packed uniforms // Packed uniforms
struct T_PackedUniforms struct T_PackedUniforms
{ {
@ -94,3 +96,57 @@ struct T_UniformSet
uint32_t vectorElements_ , opaqueElements_; uint32_t vectorElements_ , opaqueElements_;
T_PackedUniforms packed_[ int( E_UniformCategory::__COUNT__ ) ]; 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_;
};