Vulkan run time что это за программа и нужна

Я работаю техническим переводчиком ижевской IT-компании CG Tribe, которая предложила мне внести свой вклад в сообщество и начать публиковать переводы интересных статей и руководств.

Здесь я буду публиковать перевод руководства к Vulkan API. Ссылка на источник — vulkan-tutorial.com. Поскольку переводом этого же руководства занимается еще один пользователь Хабра — kiwhy, мы договорились разделить уроки между собой. В своих публикациях я буду давать ссылки на главы, переведенные kiwhy.

Содержание

  1. Подготовка к работе
    • Базовый код
    • Экземпляр (instance)
    • Слои валидации
    • Физические устройства и семейства очередей
    • Логическое устройство и очереди
    • Отображение на экране
      • Window surface
      • Swap chain
      • Image views
      • Графический конвейер (pipeline)
        • Вступление
        • Шейдерные модули
        • Непрограммируемые стадии конвейера
        • Проходы рендера (Render passes)
        • Заключение
        • Отрисовка
          • Фреймбуферы
          • Буферы команд
          • Рендеринг и отображение на экране
          • Пересоздание swap chain

          AIDA64, все что нужно знать

          1. Описание входных данных вершин
          2. Создание вершинного буфера
          3. Промежуточный буфер
          4. Индексный буфер
          1. Layout дескрипторов и буфер
          2. Пул дескрипторов и сеты дескрипторов
          1. Изображения
          2. Image view и image sampler
          3. Комбинированный image sampler

          9. Загрузка моделей

          10. Создание мип-карт

          FAQ

          Политика конфиденциальности

          1. Вступление

          2. Краткий обзор

          1. Шаг 1 — Экземпляр (instance) и физические устройства
          2. Шаг 2 — Логическое устройство и семейства очередей
          3. Шаг 3 — Window surface и цепочки показа (swap chain)
          4. Шаг 4 — Image views и фреймбуферы
          5. Шаг 5 — Проходы рендера
          6. Шаг 6 — Графический конвейер (pipeline)
          7. Шаг 7 — Пул команд и буферы команд
          8. Шаг 8 — Основной цикл
          9. Выводы
          1. Стандарт оформления кода
          2. Слои валидации

          Предпосылки возникновения Vulkan

          Как и предыдущие графические API, Vulkan задуман как кроссплатформенная абстракция над GPU. Основная проблема большинства таких API заключается в том, что в период их разработки использовалось графическое оборудование, ограниченное фиксированным функционалом. Разработчики должны были предоставить данные о вершинах в стандартном формате и в плане освещения и теней полностью зависели от производителей графических процессоров.

          По мере развития архитектуры видеокарт в ней стало появляться все больше программируемых функций. Все новые функции необходимо было каким-то образом объединить с существующими API. Это привело к неидеальным абстракциям и множеству гипотез со стороны графического драйвера о том, как воплотить замысел программиста в современных графических архитектурах.

          API — Vulkan и DirectX | Что это такое ? | 2020

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

          Архитектуры этих мобильных GPU могут сильно отличаться в зависимости от требований по размерам и энергопотреблению. Одним из таких примеров является тайловый рендеринг, который может дать большую производительность за счет лучшего контроля над функционалом. Еще одним ограничением, связанным с возрастом API, является ограниченная поддержка многопоточности, что может привести к появлению узкого места со стороны ЦП.

          Vulkan помогает решить эти проблемы, поскольку изначально создан для современных графических архитектур. Это снижает потери на стороне драйвера за счет того, что разработчики могут четко описать свои цели с помощью подробного API. Vulkan позволяет параллельно создавать и отсылать команды в нескольких потоках. Также снижаются расхождения компиляции шейдеров за счет перехода на стандартизованный формат байтового кода и использования одного компилятора. И наконец, Vulkan реализует главную возможность современных видеокарт, объединяя графические и вычислительные возможности в едином API.

          Как нарисовать треугольник?

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

          Шаг 1 — Экземпляр (instance) и физические устройства

          Работа с Vulkan начинается с настройки Vulkan API через VkInstance (экземпляр). Экземпляр создается с помощью описания вашей программы и всех расширений, которые вы хотите использовать. После создания экземпляра вы можете запросить, какое оборудование поддерживает Vulkan, и выбрать один или несколько VkPhysicalDevices для выполнения операций. Вы можете сделать запрос по таким параметрам, как размер VRAM и возможности устройств, чтобы выбрать желаемые устройства, если вы предпочитаете использовать специализированные видеокарты.

          Шаг 2 — Логическое устройство и семейства очередей

          После того, как вы выберете подходящее hardware устройство для использования, вам необходимо создать VkDevice (логическое устройство), где вы более подробно опишете, какие возможности (VkPhysicalDeviceFeatures) будете использовать, например, рендеринг в несколько viewport-ов (multi viewport rendering) и 64-битные числа с плавающей точкой. Вам также необходимо установить, какие семейства очередей вы бы хотели использовать.

          Многие операции, совершаемые с помощью Vulkan, например, команды рисования и операции в памяти, выполняются асинхронно после отправки в VkQueue. Очереди выделяются из семейства очередей, где каждое семейство поддерживает определенный набор операций. Например, для операций с графикой, вычислительных операций и передачи данных памяти могут существовать отдельные семейства очередей. Кроме того их доступность может использоваться в качестве ключевого параметра при выборе физического устройства. Некоторые устройства с поддержкой Vulkan не предлагают никаких графических возможностей, однако, все современные видеокарты с поддержкой Vulkan, как правило, поддерживают все необходимые нам операции с очередями.

          Шаг 3 — Window surface и цепочки показа (swap chain)

          Если вас интересует не только внеэкранный рендеринг, вам необходимо создать окно для отображения отрендеренных изображений. Окна можно создать с помощью API исходной платформы или библиотек, таких как GLFW и SDL. В руководстве мы будем использовать GLFW, подробнее о которой мы расскажем в следующей главе.

          Нам необходимо еще два компонента, чтобы рендерить в окно приложения: window surface ( VkSurfaceKHR ) и цепочка показа ( VkSwapchainKHR ). Обратите внимание на постфикс KHR , который обозначает, что эти объекты являются частью расширения Vulkan. Vulkan API полностью независим от платформы, поэтому нам необходимо использовать стандартизованное расширение WSI (Window System Integration) для взаимодействия с менеджером окон. Surface – это кроссплатформенная абстракция окон для визуализации, которая, как правило, создается с помощью ссылки на собственный дескриптор окна, например HWND в Windows. К счастью, библиотека GLFW имеет встроенную функцию для работы со специфичными деталями платформы.

          Цепочка показа — это набор целей рендеринга. Ее задача — обеспечивать, чтобы изображение, которое рендерится в текущий момент, отличалось от отображаемого на экране. Это позволяет отслеживать, чтобы отображались только готовые изображения. Каждый раз, когда нам нужно создать кадр, мы должны сделать запрос, чтобы цепочка показа предоставила нам изображение для рендеринга.

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

          Некоторые платформы позволяют рендерить непосредственно на экран через расширения VK_KHR_display и VK_KHR_display_swapchain без взаимодействия с каким-либо менеджером окон. Это позволяет создать surface, которая представляет собой весь экран и может использоваться, например, для реализации вашего собственного менеджера окон.

          Шаг 4 — Image views и фреймбуферы

          Читайте также:
          Что за программа glary utilities 5

          Чтобы рисовать в изображение (image), полученное из цепочки показа, мы должны обернуть его в VkImageView и VkFramebuffer. Image view ссылается на определенную часть используемого изображения, а фреймбуфер ссылается на image views, которые используются как буферы цвета, глубины и шаблонов (stencil). Поскольку в цепочке показа может быть множество разных изображений, мы заранее создадим image view и фреймбуфер для каждого из них и выберем необходимое изображение во время рисования.

          Шаг 5 — Проходы рендера

          Проходы рендера в Vulkan описывают тип изображений, используемых во время операций рендеринга, то, как они используются, и то, как необходимо обрабатывать их содержимое. Перед отрисовкой треугольника мы сообщим Vulkan, что мы хотим использовать одиночное изображение в качестве буфера цвета и что нам нужно очистить его перед рисованием. Если проход рендера описывает только тип изображений, используемых в качестве буферов, то VkFramebuffer фактически связывает определенные изображения с этими слотами.

          Шаг 6 — Графический конвейер (pipeline)

          Графический конвейер в Vulkan настраивается с помощью создания объекта VkPipeline. Он описывает конфигурируемое состояние видеокарты, например, размер viewport или операцию буфера глубины, а также программируемое состояние, используя объекты VkShaderModule. Объекты VkShaderModule создаются из байтового кода шейдера. Драйверу также необходимо указать, какие цели рендеринга будут использоваться в конвейере. Мы задаем их, ссылаясь на проход рендера.

          Одна из наиболее отличительных особенностей Vulkan по сравнению с существующими API-интерфейсами заключается в том, что почти все системные настройки графического конвейера должны задаваться заранее. Это значит, что если вы хотите переключиться на другой шейдер или немного изменить vertex layout, вам необходимо полностью пересоздать графический конвейер.

          Поэтому вам придется заранее создать множество объектов VkPipeline для всех комбинаций, необходимых для операций рендеринга. Только некоторые базовые настройки, такие как размер viewport и цвет очистки, могут быть изменены динамически. Все состояния должны быть описаны явно. Так, например, не существует смешивания цветов (color blend state) по умолчанию.

          К счастью, поскольку процесс больше напоминает опережающую компиляцию, вместо компиляции «на лету», у драйвера появляется больше возможностей для оптимизации, а производительность оказывается более предсказуемой, так как значительные изменения состояния, например, переключение на другой графический конвейер, указываются явно.

          Шаг 7 — Пул команд и буферы команд

          Как уже было сказано, многие операции в Vulkan, например операции рисования, должны быть отправлены в очередь. Прежде чем отправить операции, их необходимо записать в VkCommandBuffer. Буферы команд берутся из VkCommandPool, который связан с определенным семейством очередей. Чтобы нарисовать простой треугольник, нам нужно записать буфер команд со следующими операциями:

          • Начать проход рендера
          • Привязать графический конвейер
          • Нарисовать 3 вершины
          • Закончить проход рендера

          Шаг 8 — Основной цикл

          После того, как мы отправили команды рисования в буфер команд, основной цикл кажется достаточно простым. Сначала мы получаем изображение из цепочки показа с помощью vkAcquireNextImageKHR . Затем мы можем выбрать соответствующий буфер команд для этого изображения и запустить его с помощью vkQueueSubmit. В конце, мы возвращаем изображение в цепочку показа для вывода на экран с помощью vkQueuePresentKHR .

          Операции, отправляемые в очереди, выполняются асинхронно. Поэтому мы должны использовать объекты синхронизации — семафоры —, чтобы обеспечить правильный порядок запуска. Необходимо настроить запуск буфера команд рисования таким образом, чтобы он осуществлялся только после того, как изображение будет извлечено из цепочки показа, в противном случае может возникнуть ситуация, когда мы начнем рендерить изображение, которое все еще считывается для отображения на экране. Вызов vkQueuePresentKHR , в свою очередь, должен дождаться завершения рендеринга, для которого мы будем использовать второй семафор. Он будет уведомлять об окончании отрисовки.

          Этот краткий обзор позволяет получить общее представление о предстоящей работе по рисованию вашего первого треугольника. В реальности же шагов гораздо больше. Среди них выделение буферов вершин, создание uniform-буферов и загрузка изображений текстур — все это мы рассмотрим в следующих главах, а пока начнем с простого. Чем дальше мы будем двигаться, тем сложнее будет материал.

          Обратите внимание, что мы решили пойти хитрым путем, изначально встраивая координаты вершины в вершинный шейдер вместо использования буфера вершин. Такое решение связано с тем, что для управления буферами вершин сначала требуется знакомство с буферами команд.

          Подведем краткий итог. Для отрисовки первого треугольника нам необходимо:

          • Создать VkInstance
          • Выбрать поддерживаемую видеокарту (VkPhysicalDevice)
          • Создать VkDevice и VkQueue для рисования и отображения
          • Создать окно, window surface и цепочку показа
          • Обернуть изображения цепочки показа в VkImageView
          • Создать проход рендера, который определяет цели рендеринга и их использование
          • Создать фреймбуфер для прохода рендера
          • Настроить графический конвейер
          • Распределить и записать команды рисования в буфер для каждого изображения цепочки показа
          • Отрисовать кадры в полученные изображения, отправляя правильный буфер команд и возвращая изображения обратно в цепочку показа

          Концепты API

          В заключение к текущей главе будет приведен краткий обзор того, как структурируются Vulkan API на более низком уровне.

          Стандарт оформления кода

          Все функции, перечисления и структуры Vulkan обозначены под заголовком vulkan.h , который включен в Vulkan SDK, разработанный LunarG. Установка SDK будет рассмотрена в следующей главе.

          Функции имеют префикс vk в нижнем регистре, перечисляемые типы (enum) и структуры имеют префикс Vk , а перечисляемые значения имеют префикс VK_ . API активно использует структуры, чтобы предоставить параметры функциям. Например, создание объектов обычно происходит по следующей схеме:

          image

          Многие структуры в Vulkan требуют прямого указания типа структуры в члене sType . Член pNext может указывать на структуру расширения и в нашем руководстве всегда будет иметь тип nullptr . Функции, создающие или уничтожающие объект, будут иметь параметр VkAllocationCallbacks, который позволяет вам использовать собственный аллокатор памяти и который в руководстве также будет иметь тип nullptr .

          Почти все функции возвращают VkResult, который является либо VK_SUCCESS , либо кодом ошибки. В спецификации указано, какие коды ошибок может возвратить каждая функция и что они обозначают.

          Слои валидации

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

          Поэтому Vulkan позволяет запускать расширенные проверки с помощью функции, известной как слои валидации. Слои валидации — это фрагменты кода, которые могут быть вставлены между API и графическим драйвером для выполнения дополнительных проверок параметров функций и отслеживания проблем по управлению памятью. Это удобно тем, что вы можете запустить их во время разработки, а затем полностью отключить при запуске программы без дополнительных затрат. Любой пользователь может написать свои собственные слои валидации, но Vulkan SDK от LunarG предоставляет стандартный набор, который мы будем использовать в руководстве. Вам также необходимо зарегистрировать функцию обратного вызова для получения сообщений отладки от слоев.

          Поскольку операции в Vulkan расписываются очень подробно, и слои валидации достаточно обширные, вам будет намного проще установить причину черного экрана по сравнению с OpenGL и Direct3D.

          Остался всего один шаг, прежде чем мы начнем писать код, и это — настройка рабочей среды.

          • перевод с английского
          • tutorial
          • Программирование
          • C++
          • Работа с 3D-графикой
          • Разработка игр
          • CGI (графика)

          Источник: habr.com

          Рендеринг треугольника в Vulkan (почему так сложно)

          Рендеринг треугольника в Vulkan (почему так сложно)

          На прошлой неделе отец спросил, почему я горжусь этим треугольником в ноутбуке. Я рассказал ему, что рендеринг треугольника в Vulkan очень сложен: мне потребовалось 3 дня и более 1000 строк кода, чтобы создать изображение выше. Папа был сбит с толку.

          Читайте также:
          Устройства root что это за программа

          Вот так я написал эту статью. Она объясняет что такое графический интерфейс Vulkan, как он работает, и что нужно для рендеринга треугольника с помощью вашего графического процессора.

          Что такое Vulkan

          Этот графический API создали для предоставления точной абстракции работы современных графических процессоров (GPU). В отличие от OpenGL, Vulkan очень требует множества подробностей. Любая мелочь, связанная с этим графическим API, должна быть настроена с нуля. Плюс в том, что вы используете только то, что выбираете сами. Так можно лучше понять, что происходит в вашем приложении, и при этом добиться значительно более высокой производительности.

          Эта статья предназначена для краткого обзора основ Vulkan. Она была написана для кого-то, кто знал Vulkan, но забыл многие детали (то есть для будущего меня). Большая часть информации здесь взята из Vulkan 1.2 Spec.

          Примечание: В данной статье используются C++ привязки для Vulkan.

          Кратко о работе Vulkan

          Если смотреть с высоты птичьего полета, приложение Vulkan работает так:

          Vulkan может получать доступ к устройствам, что дает вам возможность управлять одной или несколькими очередями. Очереди — это способ отправки списка команд в графический процессор, и они могут быть членами одного или нескольких семейств очередей, каждое из которых может выполнять разные действия (например, рисовать вершины трехмерной модели).

          Буферы команд — это способ отправки команд в очередь. Команды устройства «записываются» в буфер команд посредством вызовов API Vulkan и затем могут быть переданы один или несколько раз (например, один раз в каждом кадре) в очередь, которая должна быть выполнена.

          Это было предисловие. Теперь самое время погрузиться в детали!

          Начало

          Экземпляры и устройства

          В начале был Vulkan API. И API был воплощен через vk :: Instance, и из него возникли все состояния для каждого приложения.

          Вы инициализируете Vulkan, создавая экземпляр, который содержит состояние приложения. Т.е. такую информацию, как используемую вами версию Vulkan API, название вашего приложения, а также какие расширения и слои вы хотите включить. Расширения и слои обеспечивают поведение, которое по умолчанию не включено в Vulkan, например, расширенная проверка ошибок и ведение журнала вызовов.

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

          Обычная схема выбора физического устройства:

          • Перечислить все физические устройства
          • Оценить каждое физическое устройство по наличию необходимых свойств
          • Дать физическим устройствам без требуемых свойств оценку 0
          • Выбрать физическое устройство с самой высокой оценкой

          Пример кода для выбора физического устройства

          (Совет: читайте комментарии, чтобы не запутаться)

          void pickPhysicalDevice() < // Получить список всех физических устройств, которые может найти Vulkan auto physicalDevices = instance.enumeratePhysicalDevices(); if (physicalDevices.size() == 0) < throw std::runtime_error(«No GPUs with Vulkan support found!»); >// Получить список физических устройств, сортированных по rateDeviceSuitability std::multimap candidates; for (const auto int score = rateDeviceSuitability(physicalDevice); candidates.insert(std::make_pair(score, physicalDevice)); >// Проверка, что лучший кандидат соответствует необходимым свойствам (score > 0) if (candidates.rbegin()->first > 0) < physicalDevice = candidates.rbegin()->second; > else < throw std::runtime_error(«failed to find a suitable GPU!»); >> int rateDeviceSuitability(vk::PhysicalDevice physicalDevice) < // Получить все функции / свойства данного физического устройства vk::PhysicalDeviceFeatures deviceFeatures = physicalDevice.getFeatures(); vk::PhysicalDeviceProperties deviceProperties = physicalDevice.getProperties(); int score = 0; if ( deviceProperties.deviceType == vk::PhysicalDeviceType::eDiscreteGpu) < score += 1000; // Предпочитать выделенные GPU >if (!deviceFeatures.geometryShader) < return 0; // Необходимы геометрические шейдеры >return score; >

          Имея физическое устройство, вы можете создать логическое устройство.

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

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

          Логическое устройство создается там же, где вы создаете очереди.

          Как все делается

          Очереди, командные буферы и проходы рендеринга

          Очередь — это список команд, которые выполняет графический процессор.

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

          Четыре типа операций с очередями:

          • Графика -> Рисование вершин модели
          • Вычисление -> Трассировка лучей, моделирование ткани
          • Перемещение -> Загрузка текстур и буферов
          • Разрежение -> Загрузка части “мега-текстуры”

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

          Команды передаются в очереди, сначала записывая серию команд в буфер команд, а затем отправляя весь буфер в очередь с помощью vk :: Queue :: submit ().

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

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

          Наконец, команды, записанные в буферах команд, могут выполнить:

          • Действия -> отрисовку, отправку, очистку, копирование, операции запроса и т.д.
          • Настройку состояния -> связать конвейеры / буферы, перенести константы и т.д.
          • Синхронизацию -> установку / ожидание событий, конвейерные барьеры и т.д.

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

          Проходы рендеринга

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

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

          Цветные прикрепления

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

          Пример кода для записи в буфер команд и прохода рендеринга

          // Создать буфер команд vk::CommandBuffer cmd; // Начать запись в буфер команд и проход рендеринга cmd.begin(vk::CommandBufferBeginInfo()); cmd.beginRenderPass(vk::RenderPassBeginInfo(); // Привязать графический конвейер (рассмотрено позже) cmd.bindPipeline(vk::PipelineBindPoint::eGraphics, graphicsPipeline); // Для отрисовки вершин привязать информацию, содержащую буферы вершин cmd.bindVertexBuffers(0, 1, vertexBuffers, offsets); // Отрисовать буфер, в текущий момент привязанный к данному буферу команд cmd.draw(vertices.size(), 1, 0, 0); // Прекратить запись в проход рендеринга и командный буфер cmd.beginRenderPass(vk::RenderPassBeginInfo(); cmd.end();

          Последняя вещь! Некоторые команды, которые выполняют действия (например, рисуют вершины), делают это на основе текущего состояния (например, текущего связанного массива вершин), установленного командами с начала буфера команд. Это означает, что в приведенном выше примере кода cmd.draw () будет работать с текущим состоянием, установленным cmd.bindVertex () в предыдущей строке. Такая «гарантия синхронизации», что одна команда завершит выполнение до начала следующей, обычно неверна.

          Читайте также:
          Booking com partner app что это за программа

          Синхронизация

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

          Иногда спецификации Vulkan вводят в заблуждение по этому вопросу, но если вкратце, то это верно, если не используется объект синхронизации (или команды установки состояния внутри одного буфера команд).

          Существует несколько типов объектов синхронизации:

          • Заборы (синхронизация между GPU и CPU) -> Пример: убедиться, что в цепочке переключений одновременно имеется только два визуализированных кадра (то есть двойная буферизация)
          • Семафоры (синхронизация GPU с GPU между очередями) -> Пример: дождаться конца рендеринга кадра до того, как представить его
          • Барьеры (синхронизация в буфере команд / конвейере) -> Пример: запуск вычислительного шейдера сразу после завершения вершинного шейдера
          • Зависимости подпрохода (синхронизация между подпроходами) -> Пример: дождаться завершения нормального и альбедо прикреплений, прежде чем запускать подпроход рендеринга освещения.

          Синхронизация тесно связана с графическим конвейером.

          Графический конвейер

          Он берет меши и текстуры 3D-моделей (вместе с другой информацией) и превращает это в пиксели на вашем 2D-экране. Каждый этап графического конвейера работает на выходе предыдущего этапа.

          В графическом конвейере есть два типа этапов: фиксированные функции и шейдеры.

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

          Шейдеры — это созданные пользователем программы, которые выполняются в графическом конвейере. Они могут читать из входных переменных (например, положения вершины / фрагмента / света) и работать на графических процессорах. GPU отлично справляются с параллельными вычислительными задачами, такими как применение одного и того же правила освещения для каждого из 2 миллионов пикселей на экране или вращение 3D-модели с тысячами вершин.

          Разные шейдеры на одной и той же сфере

          В упрощенном виде графический конвейер состоит из 7 этапов:

          1. Входная сборка: Собирает необработанные данные вершин из указанных буферов. При желании индексный буфер может использоваться для повтора определенных элементов без дублирования данных вершин.
          2. Вершинный шейдер: Выполняется на каждой вершине и передает данные каждой вершины дальше по графическому конвейеру. Обычно применяет преобразования к вершинам и преобразует из пространства модели в пространство экрана.
          3. Тесселяционный шейдер: Необязателен. Работает с массивами вершин («патчами») и подразделяет их на более мелкие примитивы.
          4. Геометрический шейдер: Необязателен. Работает на каждом примитиве (треугольник, линия, точка) и может отбрасывать примитивы или выводить их больше. Этот этап часто не используется, потому что его производительность невелика на большинстве видеокарт.
          5. Растеризация: Выполняет дискретизацию примитивов на фрагменты (данные, необходимые для генерации пикселя). Фрагменты, которые выпадают за пределы экрана, и фрагменты, которые находятся за другими примитивами, отбрасываются.
          6. Фрагментный шейдер: Выполняется для каждого фрагмента и определяет его цвет, значение глубины и в какой кадровый буфер тот записывается. Часто использует интерполированные данные из вершинного шейдера, такие как нормали поверхности, чтобы применить освещение.
          7. Смешивание цветов: Применяет операции для смешивания разных фрагментов, которые отображаются на один и тот же пиксель в кадровом буфере. Фрагменты могут перезаписывать друг друга или смешиваться на основе прозрачности.

          Шейдерные модули

          В отличие от OpenGL, код шейдера в Vulkan должен быть в формате байт-кода под названием SPIR-V, а не читабельного синтаксиса типа GLSL.

          Преимущество формата байт-кода заключается в том, что компиляторы для преобразования шейдерного кода в собственный код графического процессора значительно менее сложны. Это приводит к тому, что шейдерный код SPIR-V становится надежнее для видеокарт от разных проихводителей.

          Тем не менее, шейдеры все еще обычно пишутся на GLSL, а затем компилируются в SPIR-V с помощью инструмента под названием glslc (входит в Vulkan SDK). SPIR-V можно передать в графический конвейер путем чтения байт-кода, а затем обернув тот в объект vk :: ShaderModule. Объект определяет функцию точки входа в шейдере и назначает ее для определенного этапа графики.

          Время показа

          Цепочки переключений и поверхности окон

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

          Поверхность окна позволяет вам взаимодействовать с системами отображения для конкретных платформ.

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

          Разрыв изображения

          Использование буфера кадра и одного вторичного буфера называется двойной буфер. Эта техника предотвращает разрыв изображения.

          Рендеринг треугольника в Vulkan

          В итоге, в приложении Vulkan:

          • Мы начнем с создания экземпляра, физического устройства и логического устройства.
          • Команды записываются в буферы команд и проходы рендеринга, которые передаются в очереди. Графический процессор проходит через очереди и выполняет команды в них
          • Чтобы гарантировать выполнение определенных команд после завершения выполнения других команд, необходимо использовать объекты синхронизации.
          • Некоторые команды связаны со стадиями в графическом конвейере, которые могут быть либо шейдерами, либо фиксированными функциями, и превращают трехмерные данные в двухмерное изображение.
          • Наконец, поверхность окна показывает изображения из цепочки переключений на экран

          Вот почему рендеринг треугольника в Vulkan сложен.

          Не стесняйтесь связаться со мной в Twitter. Отзывы и комментарии приветствуются 🙂

          Понравилась статья? Поделиться с друзьями:

          Переводит для Вас самые интересные статьи про разработку игр. По образованию физик-программист. Техническими переводами начала подрабатывать еще на старших курсах и постепенно это переросло в основное занятие. Интересуется гуманитарными технологиями, пробует себя в журналистике.

          Источник: coremission.net

          Запуск Valheim с Vulkan позволяет повысить частоту кадров и избавляет от вылетов

          Запуск Valheim с Vulkan позволяет повысить частоту кадров и избавляет от вылетов

          Последний апдейт Valheim не только усилил боссов, но и ввел поддержку Vulkan на Windows, так что некоторые PC-геймеры смогут увидеть прирост производительности. В отличие от DirectX 12 запуск Vulkan меньше зависит от процессора, так что игра должна работать лучше.

          Согласно заметкам патча, использование Vulkan также может избавить от рандомных вылетов, связанных с драйверами видеокарты. Правда, ждать каких-то чудес все же не стоит, так как игра все еще в раннем доступе.

          Самое большое преимущество от Vulkan можно ощутить на достаточно старых процессорах, что же касается поддержки видеокартой, то многие GPU рассчитаны на работу с API. Впрочем, перед запуском все же стоит убедиться, что ваша модель соответствует.

          Чтобы играть с Vulkan необходимо кликнуть правой кнопкой мыши на игре в библиотеке Steam и в свойствах запуска прописать -force-vulkan. Если возникнут какие-то проблемы, просто удалите эту строку.

          Некоторые игроки сообщают, что после перехода на Vulkan частота кадров в Valheim подскачила более чем на 30 fps.

          Больше статей на Shazoo

          • В Grounded сыграли 13 миллионов человек
          • В следующем обновлении Valheim игроки смогут прогуляться по Иггдрасилю
          • Grounded от Obsidian ушла «на золото» — игра покинет ранний доступ 27 сентября

          Источник: shazoo.ru

          Рейтинг
          ( Пока оценок нет )
          Загрузка ...
          EFT-Soft.ru