Skip to content

File StorageBuffer.h

File List > buffers > StorageBuffer.h

Go to the documentation of this file

#pragma once

#include "Buffers.h"
#include <vector>
#include <cstring>

enum SSBType
{
    NONE_LIST,   
    FLOAT_LIST,  
    INT_LIST,    
    VEC2_LIST,   
    VEC3_LIST,   
    CUSTOM_LIST  
};

template<typename T>
struct is_not_vector : std::true_type {};

template<typename T, typename C>
struct is_not_vector<std::vector<T, C>> : std::false_type {};

class StorageBuffer : public Buffers
{
private:
    GLuint  ssbo_base = 3;          
    SSBType ssbo_type = NONE_LIST;  

public:

    StorageBuffer() = default;

    StorageBuffer(SSBType type);

    StorageBuffer(SSBType type, GLuint base);

    ~StorageBuffer() = default;

    StorageBuffer(const StorageBuffer& ssbo);

    StorageBuffer(StorageBuffer&& ssbo) noexcept;

    StorageBuffer& operator=(const StorageBuffer& ssbo);

    StorageBuffer& operator=(StorageBuffer&& ssbo) noexcept;

public:

    void BindBuffer() const;

    void BindBufferBase(GLuint _base = static_cast<GLuint>(-1)) const;

    void UnbindBuffer() const;

    void SetBufferBase(GLuint base);

public:

    GLuint  GetBase() const { return ssbo_base; }

    SSBType GetType() const { return ssbo_type; }

public:

    template <typename T>
    void GenStorageBuffer(const std::vector<T>& src);

    template <typename T>
    void ReadStorageBuffer(std::vector<T>& tar, GLuint _offset = 0);

    template <typename _Info, typename _Ele> requires is_not_vector<_Info>::value
    void GenStorageBuffers(const _Info& _info, const std::vector<_Ele>& _data);

};

template <typename _Info, typename _Ele> requires is_not_vector<_Info>::value
void StorageBuffer::GenStorageBuffers(const _Info& _info, const std::vector<_Ele>& _data)
{
    buf_size = static_cast<GLuint>(sizeof(_Info) + _data.size() * sizeof(_Ele));
    BindBuffer();
    glBufferData(GL_SHADER_STORAGE_BUFFER, buf_size, nullptr, GL_STATIC_DRAW);

    void* bufferData = glMapBuffer(GL_SHADER_STORAGE_BUFFER, GL_WRITE_ONLY);
    std::memcpy(static_cast<char*>(bufferData), &_info, sizeof(_Info));
    std::memcpy(static_cast<char*>(bufferData) + sizeof(_Info), _data.data(), _data.size() * sizeof(_Ele));
    glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);

    UnbindBuffer();
}

template <typename T>
void StorageBuffer::GenStorageBuffer(const std::vector<T>& src)
{
    if (src.size() == 0) return;

    buf_size = static_cast<GLuint>(src.size() * sizeof(T));
    BindBuffer();
    glBufferData(GL_SHADER_STORAGE_BUFFER, buf_size, src.data(), GL_STATIC_DRAW);
    UnbindBuffer();
}

template <typename T>
void StorageBuffer::ReadStorageBuffer(std::vector<T>& tar, GLuint _offset)
{
    BindBuffer();
    void* dataPtr = glMapBuffer(GL_SHADER_STORAGE_BUFFER, GL_READ_ONLY);

    if (dataPtr == nullptr)
        return;

    /* | -- Offset -- | -----------  Target  -----------|
     * |-------------   Whole Data Range   -------------| */

    if (tar.size() == 0) {
        GLint bufferSize;
        glGetBufferParameteriv(GL_SHADER_STORAGE_BUFFER, GL_BUFFER_SIZE, &bufferSize);
        tar.resize(bufferSize - _offset);
    }

    std::memcpy(tar.data(), static_cast<char*>(dataPtr) + _offset, tar.size() * sizeof(T));

    glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
    UnbindBuffer();
}