Пример #1
0
int makeUniformBlockSlots(GLuint glprogram, const Shader::BindingSet& slotBindings, Shader::SlotSet& buffers) {
    GLint buffersCount = 0;

    glGetProgramiv(glprogram, GL_ACTIVE_UNIFORM_BLOCKS, &buffersCount);

    // fast exit
    if (buffersCount == 0) {
        return 0;
    }

    GLint maxNumUniformBufferSlots = 0;
    glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &maxNumUniformBufferSlots);
    std::vector<GLint> uniformBufferSlotMap(maxNumUniformBufferSlots, -1);

    for (int i = 0; i < buffersCount; i++) {
        const GLint NAME_LENGTH = 256;
        GLchar name[NAME_LENGTH];
        GLint length = 0;
        GLint size = 0;
        GLint binding = -1;

        glGetActiveUniformBlockiv(glprogram, i, GL_UNIFORM_BLOCK_NAME_LENGTH, &length);
        glGetActiveUniformBlockName(glprogram, i, NAME_LENGTH, &length, name);
        glGetActiveUniformBlockiv(glprogram, i, GL_UNIFORM_BLOCK_BINDING, &binding);
        glGetActiveUniformBlockiv(glprogram, i, GL_UNIFORM_BLOCK_DATA_SIZE, &size);

        GLuint blockIndex = glGetUniformBlockIndex(glprogram, name);

        // CHeck if there is a requested binding for this block
        auto requestedBinding = slotBindings.find(std::string(name));
        if (requestedBinding != slotBindings.end()) {
        // If yes force it
            if (binding != (*requestedBinding)._location) {
                binding = (*requestedBinding)._location;
                glUniformBlockBinding(glprogram, blockIndex, binding);
            }
        } else if (binding == 0) {
        // If no binding was assigned then just do it finding a free slot
            auto slotIt = std::find_if(uniformBufferSlotMap.begin(), uniformBufferSlotMap.end(), isUnusedSlot); 
            if (slotIt != uniformBufferSlotMap.end()) {
                binding = slotIt - uniformBufferSlotMap.begin();
                glUniformBlockBinding(glprogram, blockIndex, binding);
            } else {
                // This should neve happen, an active ubo cannot find an available slot among the max available?!
                binding = -1;
            }
        }
        // If binding is valid record it
        if (binding >= 0) {
            uniformBufferSlotMap[binding] = blockIndex;
        }

        Element element(SCALAR, gpu::UINT32, gpu::UNIFORM_BUFFER);
        buffers.insert(Shader::Slot(name, binding, element, Resource::BUFFER));
    }
    return buffersCount;
}
Пример #2
0
int GL45Backend::makeResourceBufferSlots(GLuint glprogram, const Shader::BindingSet& slotBindings,Shader::SlotSet& resourceBuffers) {
    GLint buffersCount = 0;
    glGetProgramInterfaceiv(glprogram, GL_SHADER_STORAGE_BLOCK, GL_ACTIVE_RESOURCES, &buffersCount);

    // fast exit
    if (buffersCount == 0) {
        return 0;
    }

    GLint maxNumResourceBufferSlots = 0;
    glGetIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &maxNumResourceBufferSlots);
    std::vector<GLint> resourceBufferSlotMap(maxNumResourceBufferSlots, -1);

    struct ResourceBlockInfo {
        using Vector = std::vector<ResourceBlockInfo>;
        const GLuint index{ 0 };
        const std::string name;
        GLint binding{ -1 };
        GLint size{ 0 };

        static std::string getName(GLuint glprogram, GLuint i) {
            static const GLint NAME_LENGTH = 256;
            GLint length = 0;
            GLchar nameBuffer[NAME_LENGTH];
            glGetProgramResourceName(glprogram, GL_SHADER_STORAGE_BLOCK, i, NAME_LENGTH, &length, nameBuffer);
            return std::string(nameBuffer);
        }

        ResourceBlockInfo(GLuint glprogram, GLuint i) : index(i), name(getName(glprogram, i)) {
            GLenum props[2] = { GL_BUFFER_BINDING, GL_BUFFER_DATA_SIZE};
            glGetProgramResourceiv(glprogram, GL_SHADER_STORAGE_BLOCK, i, 2, props, 2, nullptr, &binding); 
        }
    };

    ResourceBlockInfo::Vector resourceBlocks;
    resourceBlocks.reserve(buffersCount);
    for (int i = 0; i < buffersCount; i++) {
        resourceBlocks.push_back(ResourceBlockInfo(glprogram, i));
    }

    for (auto& info : resourceBlocks) {
        auto requestedBinding = slotBindings.find(info.name);
        if (requestedBinding != slotBindings.end()) {
            info.binding = (*requestedBinding)._location;
            glUniformBlockBinding(glprogram, info.index, info.binding);
            resourceBufferSlotMap[info.binding] = info.index;
        }
    }

    for (auto& info : resourceBlocks) {
        if (slotBindings.count(info.name)) {
            continue;
        }

        // If the binding is -1, or the binding maps to an already used binding
        if (info.binding == -1 || !isUnusedSlot(resourceBufferSlotMap[info.binding])) {
            // If no binding was assigned then just do it finding a free slot
            auto slotIt = std::find_if(resourceBufferSlotMap.begin(), resourceBufferSlotMap.end(), GLBackend::isUnusedSlot);
            if (slotIt != resourceBufferSlotMap.end()) {
                info.binding = slotIt - resourceBufferSlotMap.begin();
                glUniformBlockBinding(glprogram, info.index, info.binding);
            } else {
                // This should never happen, an active ssbo cannot find an available slot among the max available?!
                info.binding = -1;
            }
        }

        resourceBufferSlotMap[info.binding] = info.index;
    }

    for (auto& info : resourceBlocks) {
        static const Element element(SCALAR, gpu::UINT32, gpu::RESOURCE_BUFFER);
        resourceBuffers.insert(Shader::Slot(info.name, info.binding, element, Resource::BUFFER, info.size));
    }
    return buffersCount;
/*
    GLint ssboCount = 0;
    glGetProgramInterfaceiv(glprogram, GL_SHADER_STORAGE_BLOCK, GL_ACTIVE_RESOURCES, &ssboCount);
    if (ssboCount > 0) {
        GLint maxNameLength = 0;
        glGetProgramInterfaceiv(glprogram, GL_SHADER_STORAGE_BLOCK, GL_MAX_NAME_LENGTH, &maxNameLength);
        std::vector<GLchar> nameBytes(maxNameLength);

        for (GLint b = 0; b < ssboCount; b++) {
            GLint  length;
            glGetProgramResourceName(glprogram, GL_SHADER_STORAGE_BLOCK, b, maxNameLength, &length, nameBytes.data());
            std::string bufferName(nameBytes.data());

            GLenum props = GL_BUFFER_BINDING;
            GLint binding = -1;
            glGetProgramResourceiv(glprogram, GL_SHADER_STORAGE_BLOCK, b, 1, &props, 1, nullptr, &binding); 

            auto requestedBinding = slotBindings.find(std::string(bufferName));
            if (requestedBinding != slotBindings.end()) {
                if (binding != (*requestedBinding)._location) {
                    binding = (*requestedBinding)._location;
                    glShaderStorageBlockBinding(glprogram, b, binding);
                }
            }

            static const Element element(SCALAR, gpu::UINT32, gpu::RESOURCE_BUFFER);
            resourceBuffers.insert(Shader::Slot(bufferName, binding, element, -1));
        }
    }
    return ssboCount;*/
}
Пример #3
0
int makeUniformSlots(GLuint glprogram, const Shader::BindingSet& slotBindings, Shader::SlotSet& uniforms, Shader::SlotSet& textures, Shader::SlotSet& samplers) {
    GLint uniformsCount = 0;

#if (GPU_FEATURE_PROFILE == GPU_LEGACY)
    GLint currentProgram = 0;
    glGetIntegerv(GL_CURRENT_PROGRAM, &currentProgram);
    glUseProgram(glprogram);
#endif

    glGetProgramiv(glprogram, GL_ACTIVE_UNIFORMS, &uniformsCount);

    for (int i = 0; i < uniformsCount; i++) {
        const GLint NAME_LENGTH = 256;
        GLchar name[NAME_LENGTH];
        GLint length = 0;
        GLint size = 0;
        GLenum type = 0;
        glGetActiveUniform(glprogram, i, NAME_LENGTH, &length, &size, &type, name);
        GLint location = glGetUniformLocation(glprogram, name);
        const GLint INVALID_UNIFORM_LOCATION = -1;

        // Try to make sense of the gltype
        auto elementResource = getFormatFromGLUniform(type);

        // The uniform as a standard var type
        if (location != INVALID_UNIFORM_LOCATION) {
            // Let's make sure the name doesn't contains an array element
            std::string sname(name);
            auto foundBracket = sname.find_first_of('[');
            if (foundBracket != std::string::npos) {
              //  std::string arrayname = sname.substr(0, foundBracket);

                if (sname[foundBracket + 1] == '0') {
                    sname = sname.substr(0, foundBracket);
                } else {
                    // skip this uniform since it's not the first element of an array
                    continue;
                }
            }

            if (elementResource._resource == Resource::BUFFER) {
                uniforms.insert(Shader::Slot(sname, location, elementResource._element, elementResource._resource));
            } else {
                // For texture/Sampler, the location is the actual binding value
                GLint binding = -1;
                glGetUniformiv(glprogram, location, &binding);

                auto requestedBinding = slotBindings.find(std::string(sname));
                if (requestedBinding != slotBindings.end()) {
                    if (binding != (*requestedBinding)._location) {
                        binding = (*requestedBinding)._location;
#if (GPU_FEATURE_PROFILE == GPU_LEGACY)
                        glUniform1i(location, binding);
#else
                        glProgramUniform1i(glprogram, location, binding);
#endif
                    }
                }

                textures.insert(Shader::Slot(name, binding, elementResource._element, elementResource._resource));
                samplers.insert(Shader::Slot(name, binding, elementResource._element, elementResource._resource));
            }
        }
    }

#if (GPU_FEATURE_PROFILE == GPU_LEGACY)
    glUseProgram(currentProgram);
#endif

    return uniformsCount;
}