воскресенье, 28 февраля 2016 г.

Vulkan API. Devices

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


Devices


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


Логическое устройство создается как подключение к физическому устройству. Чтоб создать логическое устройство используется функция:
VkResult vkCreateDevice(
VkPhysicalDevice physicalDevice,
const VkDeviceCreateInfo * pCreateInfo,
const VkAllocationCallbacks * pAllocator,
VkDevice * pDevice);
• physicalDevice - валидный хэндл физического устройства, полученный через vkEnumeratePhysicalDevices.
• pCreateInfo - указатель на структуру VkDeviceCreateInfo, содержащую информацию о том, как создавать устройство.
• pAllocator - контролирует выделение памяти хостом, может быть NULL.
• pDevice -  указатель на хендл VkDevice, куда будет возвращено созданное устройство.


Возможные коды ошибок:
Success
• VK_SUCCESS
Failure
• VK_ERROR_OUT_OF_HOST_MEMORY
• VK_ERROR_OUT_OF_DEVICE_MEMORY
• VK_ERROR_INITIALIZATION_FAILED
• VK_ERROR_LAYER_NOT_PRESENT
• VK_ERROR_EXTENSION_NOT_PRESENT
• VK_ERROR_FEATURE_NOT_PRESENT
• VK_ERROR_TOO_MANY_OBJECTS
• VK_ERROR_DEVICE_LOST


Структура VkDeviceCreateInfo определена как:
typedef struct VkDeviceCreateInfo {
VkStructureType sType;
const void * pNext;
VkDeviceCreateFlags flags;
uint32_t queueCreateInfoCount;
const VkDeviceQueueCreateInfo * pQueueCreateInfos;
uint32_t enabledLayerCount;
const char * const * ppEnabledLayerNames;
uint32_t enabledExtensionCount;
const char * const * ppEnabledExtensionNames;
const VkPhysicalDeviceFeatures * pEnabledFeatures;
} VkDeviceCreateInfo;


• sType - тип структуры, должен быть VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO.
• pNext - должен быть NULL.
• flags - зарезервировано, должен быть 0.
• queueCreateInfoCount - количество элементов в массиве pQueueCreateInfos, должно быть больше нуля.
• pQueueCreateInfos - указатель на массив структур VkDeviceQueueCreateInfo, описывающих очереди, запрашиваемые для создания совместно с логическим устройством.
• enabledLayerCount - количество лееров в массиве ppEnabledLayerNames.
• ppEnabledLayerNames - указатель на массив UTF-8 строк с именами лееров, которые должны быть созданы для данного устройства.
• enabledExtensionCount - количество элементов в массиве ppEnabledExtensionNames.
• ppEnabledExtensionNames - указатель на массив UTF-8 строк с именами расширений для данного устройства.
• pEnabledFeatures - указатель на структуру VkPhysicalDeviceFeatures, содержащую список активных состояний.
В спецификации явно не указано, но поле pEnabledFeatures может быть NULL, если не предполагается использование особых вызможностей.

Заметка: поле queueFamilyIndex для любого элемента pQueueCreateInfos должно быть уникальным внутри pQueueCreateInfos.


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


Device Use


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


Device Idle


Устройство активно пока хотя бы одна из его очередей имеет рабочий процесс. Как только все очереди устройства переходят в состояние простоя, устройство так же переходят в состояние простоя. Чтоб дождаться этого состояния вызовите:
VkResult vkDeviceWaitIdle(VkDevice device);


Возвращаемые ошибки:
Success
• VK_SUCCESS
Failure
• VK_ERROR_OUT_OF_HOST_MEMORY
• VK_ERROR_OUT_OF_DEVICE_MEMORY
• VK_ERROR_DEVICE_LOST


Lost Device


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


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


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


Команды, которые бесконечно ожидают завершение выполнения устройством команд ( vkDeviceWaitIdle, vkQueueWaitIdle, vkWaitForFences или vkAcquireNextImageKHR с максимальным таймаутом, vkGetQueryPoolResults с установленным  VK_QUERY_RESULT_WAIT_BIT) должны завершиться в конечное время даже в случае если устройство потеряно и вернуть либо VK_SUCCESS либо VK_ERROR_DEVICE_LOST. Для любой команды, которая может вернуть  VK_ERROR_DEVICE_LOST, с целью определения того, отложено ли выполнение буфером команды или задействованы ли ресурсы устройством, код ошибки  VK_ERROR_DEVICE_LOST эквивалентен  VK_SUCCESS.


Device Destruction


Чтоб уничтожить устройство необходимо вызвать команду:
void vkDestroyDevice(VkDevice device, const VkAllocationCallbacks * pAllocator);
При этом все дочерние объекты (те, что были созданный через vkCreate* или vkAllocate*, где первым параметром было это устройство) должны быть удалены до удаления устройства.


Можно использовать vkDeviceWaitIdle чтоб убедиться что у устройства не осталось активных задач.  

Время жизни каждого из дочерних объектов ограничено временем жизни объекта VkDevice. Таким образом, чтоб избежать утечек ресурсов, критично важно явно освободить все эти ресурсы до вызова vkDestroyDevice.

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

Отправить комментарий