Вопрос относительно кратности смещения выравнивания памяти для данных буфера вершин при вызове vkCmdBindVertexBuffers () - PullRequest
0 голосов
/ 06 февраля 2019

Я создаю основанный на Vulkan рендерер для моей игровой среды.На данный момент я загружаю в меш около 10 000 уникальных треугольников (не проиндексированных - все отдельные), где каждая вершина имеет значение позиции, значение RGB, никаких нормалей и текстурных координат.Это получается как 72 байта на треугольник, т.е.1 * xyz float + 1 * RGB float = 6 операций с плавающей точкой на вершину.6 * 3 вершины = 18 поплавков на треугольник.18 * 4 = 72 байта на треугольник.Данные Vertex хранятся в локальном буфере графического процессора с установленным флагом VK_BUFFER_USAGE_VERTEX_BUFFER_BIT.

В настоящее время я также использую одни и те же шейдеры vert и frag для всех сеток с константами push для вычисляемой ЦП матрицы MVP.

Если я использую значения, кратные 72, как для параметра смещения в vkCmdBindVertexBuffers (), то моя сетка распадается, так как первые треугольники в буфере никогда не рисуются.Я увеличил смещение на 72 кадра за кадром, что привело к исчезновению сетки без ошибок или ошибок.Стандартная проверка LunarG включена без сообщений об ошибках проверки (у меня много ошибок при проверке и регистрации в моем коде).

Кстати, если я не использую кратные 72, я получаю очень интересные рендеры, но не вылетает!Я также получаю частоту кадров 650 кадров в секунду на шестилетнем компьютере, работающем в renderdoc.

Этот код связывает буфер вершин ...

vkCmdBindVertexBuffers, (cmd[swapindex], 0, 1, vertexBuffers, offsets)

Теперь простопотому что это нормально работает на моем ПК, это не значит, что это правильно.Одна вещь, в которой я запутался, это область спецификации Vulkan, касающаяся требований выравнивания памяти, в частности, в VkPhysicalDeviceLimits.

В VkPhysicalDeviceLimits есть несколько: minTexelBufferOffsetAlignment, minUniformBuffer * OffsetAlignmentговорит: Элемент выравнивания удовлетворяет требованиям выравнивания смещения дескриптора буфера, связанным с использованием VkBuffer:

Если включено использование VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT или VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BEGF_LIFE_LIBRING_BLT_HD_HD_WR_T_L_T_C_T_L_S_FL_S_S_F_L_F_S_FL_C_F_C_L_Sиспользование включает VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, выравнивание должно быть целочисленным кратным VkPhysicalDeviceLimits :: minUniformBufferOffsetAlignment.

Если используется использование VK_BUFFER_USOR_STORAGE_STORAGE_STAGE_STAGE_STAGE_STAL_STAL_STAL_STRING_BING_BHE_BIFF_Beffer_BefferЯ создаю буфер вершин в локальной памяти устройства с vkCreateBuffer () с помощью bufferCreateInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT (А VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT).

1025 * Вопрос ... Как я не создание буфера с VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT,VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT или VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, означает ли это, что нет требований к выравниванию памяти для параметра смещения, когда я вызываю vkCmdB * 0, я думаю, что это не так?Я хочу сохранить более одного меша в одном выделенном буфере vkCreateBuffer () с установленным флагом VK_BUFFER_USAGE_VERTEX_BUFFER_BIT.Затем я могу смещаться в этот «супер вершинный буфер» для каждой уникальной сетки, которую мне нужно нарисовать, не имея нескольких распределений буфера вершин.Я знаю, что предел для выделения буферов Vertex обычно составляет 4096 (VkPhysicalDeviceLimits :: maxMemoryAllocationCount), но вместо того, чтобы выделять несколько буферов Vertex, я бы предпочел использовать один «супер буфер» для производительности.

Имеет ли это смысл?

ОБНОВЛЕНИЕ: я изменил свой код, чтобы не использовать смещение в vkCmdBindVertexBuffers (), и вместо этого использую параметр firstVertex в vkCmdDraw () в качестве смещения модели сетки, что приводит к немного более высокому и стабильному FPS.

1 Ответ

0 голосов
/ 06 февраля 2019

Я не вижу каких-либо требований по выравниванию в спецификации, хотя я думаю, что это, вероятно, недосмотр.Вы можете попробовать округлить до кратного 16;любое фактическое требование выравнивания вряд ли будет больше этого.Таким образом, если ваша первая сетка состоит из 5 треугольников, вам нужно 5 * 72 байта для нее, а вторая сетка будет начинаться со смещения round_up (5 * 72, 16) = 368.Если это не сработает, возможно, у вас есть ошибка в другом месте.

Вместо того, чтобы использовать смещения для vkCmdBindVertexBuffers, вы можете просто связать полный буфер вершин один раз и использовать параметр firstVertex для каждогонарисовать, чтобы указать индекс в буфер, где начинается сетка.

...