Индексирование во 2-й элемент массива всегда возвращает ноль - PullRequest
2 голосов
/ 20 января 2020

У меня есть UBO, которое выглядит так:

#version 450
#extension GL_ARB_separate_shader_objects : enable

const uint InstanceCount = 64;

layout(std140, align = 16, binding = 0) uniform UBO
{
    vec4 array_indices[InstanceCount];
    mat4 proj;
    mat4 model;
    mat4 models[InstanceCount];
    uint selection[128];
} ubo;

и каждый экземпляр вершинного шейдера обращается к одному биту из uint selection[128] следующим образом:

layout(location = 1) out uint is_selected;

void main() {
    uint id = gl_InstanceIndex;
    uint num_index = id / 32;
    uint bit_index = id % uint(32);
    uint n = ubo.selection[num_index];
    is_selected = n & (1u << bit_index);
...
}

Проблема в том, что всякий раз, когда id больше 31 (то есть когда num_index равно 1 или больше) n всегда равно нулю. Но RenderDo c показывает, что первые 2 uint с ubo.selection[128] являются F0000380 и 0000000F (что означает, что 2nd uint не ноль), поэтому я предполагаю, что у шейдера есть проблемы с индексацией в массиве, поэтому есть идеи, почему n равен нулю, если я не индексирую первый элемент массива?

Видеокарта AMD Polaris10.

Структура C ++, которая питает этот UBO:

static const u32 InstanceCount = 64;

struct UBO
{
    vkm::vec4 array_indices[InstanceCount];
    vkm::mat4 proj;
    vkm::mat4 model;
    vkm::mat4 models[InstanceCount];
    u32 selection[128];
};

vkm::mat4 - класс с плавающей точкой с одним членом arr [16].

Ответы [ 2 ]

3 голосов
/ 21 января 2020

В макете std140 все массивы имеют шаг массива от элемента к элементу, округленный до ближайшего sizeof(vec4), что составляет 16 байтов. Поэтому, если u32 на самом деле не является 16-байтовой структурой, u32 selection[128]; не соответствует вашему определению.

Что нужно сделать вашему GLSL - это взять массив uvec4 в 4 раза меньше его фактического размер и индексировать массив следующим образом:

const int num_selection_elements = 128;
const int num_selection_words = num_selection_elements / 4
layout(std140, align = 16, binding = 0) uniform UBO
{
    ...
    uvec4 selection[num_selection_words];
} ubo;

void main() {
    uint id = gl_InstanceIndex;
    uint bit_index = id % 32;
    uint word_index = (id / 32) % 4;
    uint vec_index = id / (num_selection_words * 32 * 4);
    uint n = ubo.selection[vec_index][word_index];
    is_selected = n & (1u << bit_index);
...
}
0 голосов
/ 27 января 2020

После дополнительного тестирования это окончательное правильное индексирование в массив uvec4:

uint index = gl_InstanceIndex;
const uint vec_index = index / 128; // 128 = 32 * 4 = vec size
index %= 128;
uint num_index = index / 32;
const uint bit_index = index % 32;
const uint n = ubo.selection[vec_index][num_index];
is_selected = n & (1u << bit_index);

То есть, когда индексирование после первого uvec4 num_index становится неправильным без index %= 128;.

...