<commit_before>#include <storm/platform/ogl/shader_ogl.h>

#include <numeric>
#include <set>

#include <storm/platform/ogl/buffer_ogl.h>
#include <storm/platform/ogl/check_result_ogl.h>
#include <storm/platform/ogl/rendering_system_ogl.h>
#include <storm/platform/ogl/sampler_ogl.h>
#include <storm/platform/ogl/texture_ogl.h>
#include <storm/throw_exception.h>

namespace storm {

namespace {

class ShaderBinaryLoadingError : public Exception {};

struct ValueHandleImplementation {
    enum class Type {
        UniformBlock,
        Sampler
    };

    const ShaderOgl *shader;
    Type type;
    GLint index;
};

void bindTexture( Texture::Pointer texture, GLuint textureUnit ) {
    const auto nativeTexture =
        std::static_pointer_cast< TextureOgl >( texture );

    ::glActiveTexture( GL_TEXTURE0 + textureUnit );
    checkResult( "::glActiveTexture" );

    if( nativeTexture )
        ::glBindTexture(
            nativeTexture->getTarget(), nativeTexture->getHandle() );
    else
        ::glBindTexture( GL_TEXTURE_2D, 0 );
    checkResult( "::glBindTexture" );
}

void bindSampler( Sampler::Pointer sampler, GLuint textureUnit ) {
    const auto nativeSampler =
        std::static_pointer_cast< SamplerOgl >( sampler );

    storm_assert( nativeSampler, "Shader texture sampler is not set" );

    ::glBindSampler( textureUnit, nativeSampler->getHandle() );
    checkResult( "::glBindSampler" );
}

void bindUniformBuffer( Buffer::Pointer buffer, GLuint bindingPoint ) {
    const auto nativeBuffer = std::static_pointer_cast<BufferOgl>( buffer );

    storm_assert( nativeBuffer, "Shader uniform buffer is not set" );

    ::glBindBufferBase( GL_UNIFORM_BUFFER, bindingPoint,
        nativeBuffer->getHandle() );
    checkResult( "::glBindBufferBase" );
}

bool isSupportedSamplerType( GLenum uniformType ) {
    static const std::set<GLenum> supportedTypes = {
        GL_SAMPLER_1D,
        GL_SAMPLER_2D,
        GL_SAMPLER_3D,
        GL_SAMPLER_CUBE,
        GL_SAMPLER_1D_SHADOW,
        GL_SAMPLER_2D_SHADOW,
        GL_SAMPLER_1D_ARRAY,
        GL_SAMPLER_2D_ARRAY,
        GL_SAMPLER_1D_ARRAY_SHADOW,
        GL_SAMPLER_2D_ARRAY_SHADOW,
        GL_SAMPLER_2D_MULTISAMPLE,
        GL_SAMPLER_2D_MULTISAMPLE_ARRAY,
        GL_SAMPLER_CUBE_SHADOW,
        GL_INT_SAMPLER_1D,
        GL_INT_SAMPLER_2D,
        GL_INT_SAMPLER_3D,
        GL_INT_SAMPLER_CUBE,
        GL_INT_SAMPLER_1D_ARRAY,
        GL_INT_SAMPLER_2D_ARRAY,
        GL_INT_SAMPLER_2D_MULTISAMPLE,
        GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY,
        GL_UNSIGNED_INT_SAMPLER_1D,
        GL_UNSIGNED_INT_SAMPLER_2D,
        GL_UNSIGNED_INT_SAMPLER_3D,
        GL_UNSIGNED_INT_SAMPLER_CUBE,
        GL_UNSIGNED_INT_SAMPLER_1D_ARRAY,
        GL_UNSIGNED_INT_SAMPLER_2D_ARRAY,
        GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE,
        GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY
    };
    return supportedTypes.count( uniformType ) != 0;
}

} // namespace

// ProgramHandleOgl

ProgramHandleOgl::ProgramHandleOgl() {
    _handle = ::glCreateProgram();
    checkResult( "::glCreateProgram" );
}

ProgramHandleOgl::ProgramHandleOgl(
    GLenum shaderType, const char *sourceCode )
{
    _handle = ::glCreateShaderProgramv( shaderType, 1, &sourceCode );
    checkResult( "::glCreateShaderProgramv" );
}

ProgramHandleOgl::~ProgramHandleOgl() {
    ::glDeleteProgram( _handle );
}

// ShaderOgl

ShaderOgl::ShaderOgl( const std::string &sourceCode, Type type ) :
    _type( type ),
    _handle( convertType(type), sourceCode.c_str() )
{
    if( getProgramParameter(GL_LINK_STATUS) == GL_FALSE ) {
        std::string log( getProgramParameter(GL_INFO_LOG_LENGTH), 0 );

        ::glGetProgramInfoLog( _handle, log.size(), nullptr, &log[0] );
        checkResult( "::glGetProgramInfoLog" );

        throw ShaderCompilationError() << "Shader compilation failed:\n" << log;
    }

    createSamplersMapping();
    createUniformBlocksMapping();
}

ShaderOgl::ShaderOgl( const std::vector<unsigned char> &binary, Type type ) :
    _type( type )
{
    const size_t headerSize = 2 * sizeof( GLenum );

    if( binary.size() > headerSize &&
            getOpenGlSupportStatus().ARB_get_program_binary )
    {
        const GLenum shaderType =
            *reinterpret_cast<const GLenum*>( binary.data() );
        const GLenum binaryFormat =
            *reinterpret_cast<const GLenum*>( binary.data() + sizeof(GLenum) );

        if( shaderType != convertType(_type) )
            throw ShaderBinaryLoadingError();

        const GLvoid *binaryData = binary.data() + headerSize;
        const GLsizei binaryRepresentationLength = binary.size() - headerSize;

        ::glProgramBinary(
            _handle,
            binaryFormat,
            binaryData,
            binaryRepresentationLength );
    }

    if( getProgramParameter(GL_LINK_STATUS) == GL_FALSE )
        throw ShaderBinaryLoadingError();

    createSamplersMapping();
    createUniformBlocksMapping();
}

Shader::Type ShaderOgl::getType() const {
    return _type;
}
<commit_msg>Fixed error handling in shader binary loading code<commit_after>#include <storm/platform/ogl/shader_ogl.h>

#include <numeric>
#include <set>

#include <storm/platform/ogl/buffer_ogl.h>
#include <storm/platform/ogl/check_result_ogl.h>
#include <storm/platform/ogl/rendering_system_ogl.h>
#include <storm/platform/ogl/sampler_ogl.h>
#include <storm/platform/ogl/texture_ogl.h>
#include <storm/throw_exception.h>

namespace storm {

namespace {

class ShaderBinaryLoadingError : public Exception {};

struct ValueHandleImplementation {
    enum class Type {
        UniformBlock,
        Sampler
    };

    const ShaderOgl *shader;
    Type type;
    GLint index;
};

void bindTexture( Texture::Pointer texture, GLuint textureUnit ) {
    const auto nativeTexture =
        std::static_pointer_cast< TextureOgl >( texture );

    ::glActiveTexture( GL_TEXTURE0 + textureUnit );
    checkResult( "::glActiveTexture" );

    if( nativeTexture )
        ::glBindTexture(
            nativeTexture->getTarget(), nativeTexture->getHandle() );
    else
        ::glBindTexture( GL_TEXTURE_2D, 0 );
    checkResult( "::glBindTexture" );
}

void bindSampler( Sampler::Pointer sampler, GLuint textureUnit ) {
    const auto nativeSampler =
        std::static_pointer_cast< SamplerOgl >( sampler );

    storm_assert( nativeSampler, "Shader texture sampler is not set" );

    ::glBindSampler( textureUnit, nativeSampler->getHandle() );
    checkResult( "::glBindSampler" );
}

void bindUniformBuffer( Buffer::Pointer buffer, GLuint bindingPoint ) {
    const auto nativeBuffer = std::static_pointer_cast<BufferOgl>( buffer );

    storm_assert( nativeBuffer, "Shader uniform buffer is not set" );

    ::glBindBufferBase( GL_UNIFORM_BUFFER, bindingPoint,
        nativeBuffer->getHandle() );
    checkResult( "::glBindBufferBase" );
}

bool isSupportedSamplerType( GLenum uniformType ) {
    static const std::set<GLenum> supportedTypes = {
        GL_SAMPLER_1D,
        GL_SAMPLER_2D,
        GL_SAMPLER_3D,
        GL_SAMPLER_CUBE,
        GL_SAMPLER_1D_SHADOW,
        GL_SAMPLER_2D_SHADOW,
        GL_SAMPLER_1D_ARRAY,
        GL_SAMPLER_2D_ARRAY,
        GL_SAMPLER_1D_ARRAY_SHADOW,
        GL_SAMPLER_2D_ARRAY_SHADOW,
        GL_SAMPLER_2D_MULTISAMPLE,
        GL_SAMPLER_2D_MULTISAMPLE_ARRAY,
        GL_SAMPLER_CUBE_SHADOW,
        GL_INT_SAMPLER_1D,
        GL_INT_SAMPLER_2D,
        GL_INT_SAMPLER_3D,
        GL_INT_SAMPLER_CUBE,
        GL_INT_SAMPLER_1D_ARRAY,
        GL_INT_SAMPLER_2D_ARRAY,
        GL_INT_SAMPLER_2D_MULTISAMPLE,
        GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY,
        GL_UNSIGNED_INT_SAMPLER_1D,
        GL_UNSIGNED_INT_SAMPLER_2D,
        GL_UNSIGNED_INT_SAMPLER_3D,
        GL_UNSIGNED_INT_SAMPLER_CUBE,
        GL_UNSIGNED_INT_SAMPLER_1D_ARRAY,
        GL_UNSIGNED_INT_SAMPLER_2D_ARRAY,
        GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE,
        GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY
    };
    return supportedTypes.count( uniformType ) != 0;
}

} // namespace

// ProgramHandleOgl

ProgramHandleOgl::ProgramHandleOgl() {
    _handle = ::glCreateProgram();
    checkResult( "::glCreateProgram" );
}

ProgramHandleOgl::ProgramHandleOgl(
    GLenum shaderType, const char *sourceCode )
{
    _handle = ::glCreateShaderProgramv( shaderType, 1, &sourceCode );
    checkResult( "::glCreateShaderProgramv" );
}

ProgramHandleOgl::~ProgramHandleOgl() {
    ::glDeleteProgram( _handle );
}

// ShaderOgl

ShaderOgl::ShaderOgl( const std::string &sourceCode, Type type ) :
    _type( type ),
    _handle( convertType(type), sourceCode.c_str() )
{
    if( getProgramParameter(GL_LINK_STATUS) == GL_FALSE ) {
        std::string log( getProgramParameter(GL_INFO_LOG_LENGTH), 0 );

        ::glGetProgramInfoLog( _handle, log.size(), nullptr, &log[0] );
        checkResult( "::glGetProgramInfoLog" );

        throw ShaderCompilationError() << "Shader compilation failed:\n" << log;
    }

    createSamplersMapping();
    createUniformBlocksMapping();
}

ShaderOgl::ShaderOgl( const std::vector<unsigned char> &binary, Type type ) :
    _type( type )
{
    const size_t headerSize = 2 * sizeof( GLenum );

    if( binary.size() > headerSize &&
            getOpenGlSupportStatus().ARB_get_program_binary )
    {
        const GLenum shaderType =
            *reinterpret_cast<const GLenum*>( binary.data() );
        const GLenum binaryFormat =
            *reinterpret_cast<const GLenum*>( binary.data() + sizeof(GLenum) );

        if( shaderType != convertType(_type) )
            throw ShaderBinaryLoadingError();

        const GLvoid *binaryData = binary.data() + headerSize;
        const GLsizei binaryRepresentationLength = binary.size() - headerSize;

        ::glProgramBinary(
            _handle,
            binaryFormat,
            binaryData,
            binaryRepresentationLength );

#ifndef NDEBUG
        // We intentionally ignore shader binary loading errors and set error
        // flag to the 'GL_NO_ERROR' value. We will detect loading result using
        // the 'GL_LINK_STATUS' value.
        ::glGetError();
#endif
    }

    if( getProgramParameter(GL_LINK_STATUS) == GL_FALSE )
        throw ShaderBinaryLoadingError();

    createSamplersMapping();
    createUniformBlocksMapping();
}

Shader::Type ShaderOgl::getType() const {
    return _type;
}

{'fraction_non_alphanumeric': 0.09923516313292671, 'fraction_numerical': 0.006389776357827476, 'mean_word_length': 3.4372852233676974, 'pattern_counts': {'":': 14, '<': 43, '<?xml version=': 0, '>': 45, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6423309', 'n_tokens_mistral': 3482, 'n_tokens_neox': 3366, 'n_words': 593}