Рендеринг нескольких разных материалов, которые иногда требуют разных конфигураций шейдеров - PullRequest
0 голосов
/ 22 сентября 2018

Я пытаюсь создать игровой движок на основе 3D вокселей, чтобы научиться использовать вулкан.Я столкнулся со стеной, которую я не могу найти в документации о том, как лазить.Прямо сейчас я рисую 2D-треугольник и перемещаю его по экрану, мой 2D-треугольник определен как 1 вершина в буфере вершин, которая в будущем будет преобразована в пространство экрана в моем вершинном шейдере.Эта единственная вершина превращается в 3 вершины моим геометрическим шейдером и затем передается моему фрагментному шейдеру.

    triangle_center_position[0] = (cursor_x - (vulkan_window_width_get() / 2.0f)) / vulkan_window_width_get();
    triangle_center_position[1] = (cursor_y - (vulkan_window_height_get() / 2.0f)) / vulkan_window_height_get();
    // send to gpu via memory mapped region
    memcpy(triangle_position_buffer.mapped_memory, &triangle_center_position, sizeof(vec2) * 1);

Он связан в командном буфере следующим образом:

    VkBuffer vertexBuffers[] = {buffer->buffer};
    VkDeviceSize offsets[] = {0};
    vkCmdBindVertexBuffers(command_buffer[i], 0, 1, vertexBuffers, offsets);
    vkCmdDraw(command_buffer[i], (uint32_t) buffer->num_elements, 1, 0, 0);

Мой план состоит в том, чтобы в конечном итоге изменить этот код, чтобы он получал трехмерную точку и чтобы мой геометрический шейдер расширялсямоя трехмерная точка в вокселе.

К сожалению, я хочу, чтобы это преобразование происходило только с блоками в мире вокселей, а не с другими вещами (моделями игроков и т. д.).

В OpenGL я бы просто назвал glUseProgram() для двух шейдерных программ, созданных для разных «материалов», что в вулканах крайне нежелательно.Мой инстинкт выглядит примерно так:

currentMaterial = null
for (Renderable r : sort(everything, by material type)) 
    if (!r.isWithinViewOfScreen()) 
        continue
    if (r.material != currentMaterial)
        currentMaterial = r.material
        r.material.use()
    r.render()

Основная проблема заключается в том, что некоторые Renderable s будут использовать совершенно другие требования к шейдерам, но, похоже, в vulkan отсутствует условие для переключения между шейдерными программами.

1 Ответ

0 голосов
/ 23 сентября 2018

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

Ближайший аналог glUseProgram в Vulkan - vkCmdBindPipeline,

Основное отличие состоит в том, что большая часть того, что считается частью конечного автомата OpenGL, запекается в объект конвейера Vulkan.Так, например, в то время как в OpenGL вы можете вызвать glUseProgram, визуализировать некоторый контент, затем вызвать glDisable(GL_DEPTH_TEST) и сделать еще несколько, в Vulkan это будут два разных конвейера, и для каждого из них потребуется вызов vkCmdBindPipeline.

Если вы знакомы с vkCmdBindPipeline и ищете какой-либо способ изменить какие шейдеры, краткий ответ: вы не можете этого сделать.Вам необходимо создать полный объект VkPipeline для каждого набора шейдеров, который вам нужно использовать, даже если ни одно из других значений в конвейере не отличается.

Однако, если вы обеспокоены тем, что в конечном итоге создадите огромное количество конвейеров и это повлияет на вашу производительность, вам следует изучить использование кэшей конвейера и флаг VK_PIPELINE_CREATE_DERIVATIVE_BIT, который позволяетвам создать что-то вроде дочерних конвейеров из шаблона конвейера.Это должно привести к той же или лучшей производительности, что и у OpenGL.

РЕДАКТИРОВАТЬ:

Имейте в виду, что разработчики, пытающиеся улучшить производительность создания конвейера, должны использовать обоих функциональность VkPipelineCache и VK_PIPELINE_CREATE_DERIVATIVE_BIT.Степень полезности производных конвейеров полностью зависит от драйвера, а некоторые драйверы (например, драйвер ARM MALI ) явно задокументированы как игнорирующие этот флаг.Спецификация Vulkan не дает никаких указаний относительно того, когда использовать или не использовать производный флаг.Надлежащий подход, вероятно, заключается в том, чтобы либо напрямую работать с независимыми поставщиками программного обеспечения, чтобы выяснить, как лучше всего применять его, либо использовать его всегда в надежде, что это улучшит производительность там, где это может, и не повлияет на производительность, в противном случае, либо просто не использовать производные вообще.,

Функциональность конвейерного кэша, с другой стороны, почти наверняка сократит время создания конвейера на широком спектре оборудования.

...