Vulkan API — урок 26. Графический конвейер (+листинг)

Теперь мы можем объеденить все созданные ранее структуры и объекты и создать графический конвейер. Перечислим имеющиеся типы объектов:

  • Шейдеры: шейдерные модули, которые определяют функциональность программируемых этапов конвейера.
  • Фиксированные функции: все структуры, которые определяют фиксированные функции конвейера.
  • Layout конвейера: постоянные и устанавливаемые значения, на которые ссылаются шейдеры и которые могут быть изменены во время отрисовки.
  • Render pass: вложения, на которые ссылаются различные этапы конвейера и их использование.

Комбинация всего этого в полной мере определяет функциональность графического конвейера. Теперь приступим к заполнению структуры VkGraphicsPipelineCreateInfo в конце функции createGraphicsPipeline. Начнем со структуры VkPipelineShaderStageCreateInfo.

VkGraphicsPipelineCreateInfo pipelineInfo = {};
pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
pipelineInfo.stageCount = 2;
pipelineInfo.pStages = shaderStages;

Далее укажем все структуры, описывающие фиксированные функции:

pipelineInfo.pVertexInputState = &vertexInputInfo;
pipelineInfo.pInputAssemblyState = &inputAssembly;
pipelineInfo.pViewportState = &viewportState;
pipelineInfo.pRasterizationState = &rasterizer;
pipelineInfo.pMultisampleState = &multisampling;
pipelineInfo.pDepthStencilState = nullptr; // Optional
pipelineInfo.pColorBlendState = &colorBlending;
pipelineInfo.pDynamicState = nullptr; // Optional

Затем указываем наш объект layout, не структуру:

pipelineInfo.layout = pipelineLayout;

И ссылаемcя на render pass и индекс подпрохода, где данный графический конвейер будет использоваться.

pipelineInfo.renderPass = renderPass;
pipelineInfo.subpass = 0;

Имеются еще два параметра: basePipelineHandle и basePipelineIndex. Vulkan позвоялет создовать новый графический конвейер на оуснове существующего. Идея производных конвейеров основана на том, что создание производного (дочернего) конвейера обойдется гораздо дешевле, и переключение между несколькими конвейерами одного родителя будет происходить быстрее. Но на данный момент у нас задуман только один конвейер, потому передадим пустой дескриптор:

pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
pipelineInfo.basePipelineIndex = -1; // Optional

Не забываем использовать наш любимый VDeleter:

VDeleter<VkPipeline> graphicsPipeline{device, vkDestroyPipeline};

И наконец создание самого конвейера:

if (vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, graphicsPipeline.replace()) != VK_SUCCESS) {
    throw std::runtime_error("failed to create graphics pipeline!");
}

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

Вторым параметром, в котором ныне указан VK_NULL_HANDLE, указывается ссылка на VkPipelineCache. Кэш конвейера может быть использован для хранения и повторного использования данных, имеющих отношение к созданию конвейера после нескольких вызовов vkCreateGraphicsPipelines, и даже после перезапуска программы, если кэш был сохранен в файл. Это позволяет создавать конвейеры более быстро через большие промежутки времени.

Ну вот и создан конвейер. Еще примерно 4 урока и на экран будет выведен треугольник.

И вот листинг.

Main Admin

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *