Почему простой цикл OpenGL быстрее, чем Vulkan one?

#opengl #vulkan

#opengl #vulkan

Вопрос:

У меня есть 2 графических приложения для OpenGL и Vulkan.

Цикл OpenGL выглядит примерно так:

 glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);

static int test = 0;

// "if" statement here is to ensure that there is no any caching or optimizations
// made by OpenGL driver (if such things exist),
// and commands are re-recorded to the buffer every frame

if ((test = 1 - test) == 0) {

    glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer1);
    glUseProgram(program1);
    glDrawArrays(GL_TRIANGLES, 0, vertices_size);
    glUseProgram(0);
}
else {

    glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer2);
    glUseProgram(program2);
    glDrawArrays(GL_LINES, 0, vertices_size);
    glUseProgram(0);
}

glfwSwapBuffers(window);
  

И Vulkan:

 static uint32_t image_index = 0;

vkAcquireNextImageKHR(device, swapchain, 0xFFFFFFFF, image_available_semaphores[image_index], VK_NULL_HANDLE, amp;image_indices[image_index]);

vkWaitForFences(device, 1, amp;submission_completed_fences[image_index], VK_TRUE, 0xFFFFFFFF);

// VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT
vkBeginCommandBuffer(cmd_buffers[image_index], amp;command_buffer_bi);
vkCmdBeginRenderPass(cmd_buffers[image_index], amp;render_pass_bi[image_index], VK_SUBPASS_CONTENTS_INLINE);
vkCmdEndRenderPass(cmd_buffers[image_index]);
vkEndCommandBuffer(cmd_buffers[image_index]);

vkResetFences(device, 1, amp;submission_completed_fences[image_index]);

vkQueueSubmit(graphics_queue, 1, amp;submit_info[image_index], submission_completed_fences[image_index]);

present_info[image_index].pImageIndices = amp;image_indices[image_index];

vkQueuePresentKHR(present_queue, amp;present_info[image_index]);

const static int max_swapchain_image_index = swapchain_image_count - 1;

if (  image_index > max_swapchain_image_index) {

  image_index = 0;
}
  

В цикле Vulkan нет четных команд рендеринга, просто пустой проход рендеринга. Уровни проверки отключены.

Частота кадров в секунду в OpenGL составляет около 10500, а Vulkan FPS — около 7500 (при использовании 8 изображений swapchain с VK_PRESENT_MODE_IMMEDIATE_KHR, меньшее количество изображений снижает частоту кадров в секунду).

Код выполняется на ноутбуке с Ubuntu 18.04, дискретным графическим процессором Nvidia RTX 2060, драйвером Nvidia 450.66, версией Vulkan API 1.2.133.

Я знаю, что драйвер OpenGL сильно оптимизирован, но я не могу представить, что еще нужно оптимизировать в цикле Vulkan, чтобы сделать его быстрее, чем он есть.

Есть ли какие-то проблемы с низкоуровневыми драйверами Linux? Или, может быть, увеличение производительности Vulkan достигается только в гораздо более сложных приложениях (например, с использованием многопоточности)?

Комментарии:

1. Какой именно смысл измерять, сколько времени требуется, чтобы ничего не делать? Ваше фактическое приложение будет что-то делать, поэтому тестирование производительности в случае бездействия не дает … ничего.

2. Если он ничего не делает, почему он медленнее, чем цикл OpenGL, который выполняет какую-то работу? И если я вставляю команды vkCmdBindDescriptorSets и vkCmdBindVertexBuffers раньше vkCmdBeginRenderPass , и vkCmdBindPipeline и vkCmdDraw раньше vkCmdEndRenderPass , чтобы нарисовать ту же геометрию с теми же шейдерами, что и в приложении OpenGL, ничего не происходит, FPS остается ~ 7500.

3. Вы также должны учитывать, что частота кадров — это неправильная метрика. Фактическое время — вот что имеет значение. И разница во времени между ними составляет 0,038 микросекунд .

4. Это вопрос восприятия. Разница между 10500 и 7500 составляет 3000, что кажется действительно большим числом. Но в абсолютном выражении 0,038 доллара США — это крошечная сумма, и поэтому беспокоиться о ней не стоит.

5. Итак, какие возможные последствия вы могли бы извлечь из этого «бенчмарка». Итак, это какой-то микро-бенчмарк, основанный на основном обращении к библиотекам драйверов в двух разных случаях, и результат вообще ни к чему не применим.