Как установить смещение glBindBufferRange () с помощью буфера хранилища шейдеров и std430? - PullRequest
1 голос
/ 03 июня 2019

Я хочу переключаться между данными ssbo, чтобы рисовать вещи с разными настройками. Чтобы это произошло, мне нужно использовать glBindBufferRange() с подходящим смещением. Я читал, что смещение должно быть кратным GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT для UBO, но с ssbo все может измениться, поскольку вместо std140 используется std430.

Я пытался сделать это самым простым способом

struct Color
{
    float r, g, b, a;
};
struct V2
{
   float x, y;
};
struct Uniform
{
    Color c1;
    Color c2;
    V2 v2;
    float r;
    float f;
    int t;
};

GLuint ssbo = 0;
std::vector<Uniform> uniform;

int main()
{
    //create window, context etc.

    glCreateBuffers(1, &ssbo);
    glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);

    Uniform u;
    u.c1 = {255, 0, 255, 255 };
    u.c2 = {255, 0, 255, 255 };
    u.v2 = { 0.0f, 0.0f };
    u.r = 0.0f;
    u.f = 100.0f;
    u.t = 0;
    uniform.push_back(u);

    u.c1 = {255, 255, 0, 255 };
    u.c2 = {255, 255, 0, 255 };
    u.v2 = { 0.0f, 0.0f };
    u.r = 100.0f;
    u.f = 100.0f;
    u.t = 1;
    uniform.push_back(u);

    u.c1 = {255, 0, 0, 255 };
    u.c2 = {255, 0, 0, 255 };
    u.v2 = { 0.0f, 0.0f };
    u.r = 100.0f;
    u.f = 0.0f;
    u.t = 0;
    uniform.push_back(u);

    glNamedBufferData(ssbo, sizeof(Uniform) * uniform.size(), uniform.data(), GL_STREAM_DRAW);

    for(int i = 0; i < uniform.size(); ++i) {
        glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 1, ssbo, sizeof(Uniform) * i, sizeof(Uniform));

        glDrawArrays(...);
    }

    //swap buffer etc.

    return 0;
}
#version 460 core

layout(location = 0) out vec4 f_color;

layout(std430, binding = 1) buffer Unif
{
    vec4 c1; 
    vec4 c2; 
    vec2 v2;   
    float r;  
    float f; 
    int t;      
};

void main()
{       
    f_color = vec4(t, 0, 0, 1);
}

Конечно, есть vao, vbo, структура вершин и так далее, но они не влияют на ssbo.

Я получил GL_INVALID_VALUE glBindBufferRange() ошибку, хотя. И это должно исходить из смещения, потому что моя следующая попытка передает данные, но с неправильным порядком.

Моя следующая попытка была использовать GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT и формула, которую я нашел в интернете

    int align = 4;
    glGetIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &align);
    int ssboSize = sizeof(Uniform) + align - sizeof(Uniform) % align;

так что просто меняя glNamedBufferData и glBindBufferRange это выглядит так

 glNamedBufferData(ssbo, ssboSize * uniform.size(), uniform.data(), GL_STREAM_DRAW);
glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 1, ssbo, ssboSize * i, sizeof(Uniform));

и таким образом, это почти сработало. Как видите, t s

0;
1;
0;

так что opengl должен нарисовать 3 фигуры с цветами -

vec4(0, 0, 0, 1); 
vec4(1, 0, 0, 1); 
vec4(0, 0, 0, 1); 

рисует их в неправильном порядке

vec4(1, 0, 0, 1); 
vec4(0, 0, 0, 1); 
vec4(0, 0, 0, 1);

Как я могу заставить его правильно передавать данные?

Ответы [ 2 ]

1 голос
/ 03 июня 2019

Спецификация OpenGL (Версия 4.6) гласит следующее в разделе «6.1.1 Привязка объектов буфера к индексированным целевым точкам» относительно условий ошибки для glBindBufferRange:

  • Ошибка INVALID_VALUE генерируется BindBufferRange, если buffer ненулевые и offset или size соответственно не удовлетворяют ограничениям, описанным для этих параметров для указанной цели, как описано в разделе 6.7.1.

Раздел 6.7.1 «Ограничения объекта индексированного буфера и запросы привязки» для SSBO:

  • начальное смещение: SHADER_STORAGE_BUFFER_START
  • ограничение смещения: кратно значению SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT
  • переплет SHADER_STORAGE_BUFFER_SIZE

В соответствии с таблицей 23.64 «Пределы зависимых от реализации совокупных шейдеров»:

256 [со следующей сноской]: значение SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT является максимально допустимым, а не минимальным.

Так что, если ваше смещение не кратно 256 (что не так), этот код просто не гарантируется вообще. Вы можете запросить фактическое ограничение по реализации, на которой вы работаете, и соответственно отрегулировать содержимое буфера, но вы должны быть подготовлены, чтобы он достиг 256 байтов.

0 голосов
/ 04 июня 2019

Я использовал struct alignas(128) Uniform.Думаю, моя следующая цель - не использовать жестко закодированное выравнивание.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...