воскресенье, 6 марта 2016 г.

Vulkan API, Synchronization primitives, Events.

Продолжение перевода 6 главы - Synchronization and Cache Control, в этот раз рассмотрим третий тип синхронизации - события(Events).
Предыдущие части можно посмотреть здесь:

Vulkan API, Synchronization primitives, Semaphores


Events

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

Чтоб создать событие необходимо вызвать функцию:
VkResult vkCreateEvent(
VkDevice device,
const VkEventCreateInfo * pCreateInfo,
const VkAllocationCallbacks * pAllocator,
VkEvent * pEvent);

• device - логическое устройство, создающее событие.
• pCreateInfo - указатель на структуру VkEventCreateInfo, содержащую информацию о том, как будет создано событие.
• pEvent - указатель на хэндл, в который будет возвращено созданное событие.

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

Структура VkEventCreateInfo определена как:
typedef struct VkEventCreateInfo {
VkStructureType sType;
const void * pNext;
VkEventCreateFlags flags;
} VkEventCreateInfo;

• sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO
• pNext = NULL
• flags - зарезервировано, должен быть равен 0

Чтоб уничтожить событие необходимо вызвать:
void vkDestroyEvent(
VkDevice device,
VkEvent event,
const VkAllocationCallbacks * pAllocator);
•  Все отправленные команды, относящиеся к событию, должны быть завершены.

Чтоб получить состояние события с хоста необходимо вызвать функцию:
VkResult vkGetEventStatus(
VkDevice device,
VkEvent event);

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

В случае успешного выполнения команды, функция vkGetEventStatus вернет следующие значения:
VK_EVENT_SET - событие сигнализировало.
VK_EVENT_RESET - событие не сигнализировало или сброшено.

Состояние события может быт установлено хостом, это состояние сразу же отражается на событии и сразу же может быть получено обратно через vkGetEventStatus.

Чтоб со стороны хоста установить состояние события в состояние signaled, необходимо вызвать функцию:
VkResult vkSetEvent(
VkDevice device,
VkEvent event);

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

Чтоб со стороны хоста сбросить состояние события в состояние unsignaled, необходимо вызвать функцию:
VkResult vkResetEvent(
VkDevice device,
VkEvent event);

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

Состояние события так же может быть обновлено со стороны устройства, командами помещенными в буферы команд. Что бы установить состояние события в signaled, необходимо вызывать команду:
void vkCmdSetEvent(
VkCommandBuffer commandBuffer,
VkEvent event,
VkPipelineStageFlags stageMask);

• stageMask - не должны равняться 0, указывает этап пайплайна, на котором событие обновит свое состояние.

• Если геометрический шейдер не активен, то stageMask не должен содержать VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT
• Если шейдер тесселяции не активен, то stageMask н должно содержать флагов VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT или VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT

Команда может использоваться как в первичном так и вторичном буфере команд, вне скопа прохода рендера. Поддерживается семействами очередей GRAPHICS и COMPUTE.

Чтоб сбросить состояние события на стороне устройства, необходимо вызвать команду vkCmdResetEvent. Ее параметры идентичны команде vkCmdSetEvent:
void vkCmdResetEvent(
VkCommandBuffer commandBuffer,
VkEvent event,
VkPipelineStageFlags stageMask);


В обоих случаях, для vkCmdSetEvent и vkCmdResetEvent, статус события изменяется сразу же после завершения выполнения команды, предшествующей указанному в stageMask этапу пайплайна. Команда модифицирующая событие передается через пайплайн, привязанный к буферу команд во время выполнения.
Чтоб на стороне устройства ожидать пока одно или несколько событий перейдут в сигнализируемое состояние, необходимо вызвать команду:
void vkCmdWaitEvents(
VkCommandBuffer commandBuffer,
uint32_t eventCount,
const VkEvent * pEvents,
VkPipelineStageFlags srcStageMask,
VkPipelineStageFlags dstStageMask,
uint32_t memoryBarrierCount,
const VkMemoryBarrier * pMemoryBarriers,
uint32_t bufferMemoryBarrierCount,
const VkBufferMemoryBarrier * pBufferMemoryBarriers,
uint32_t imageMemoryBarrierCount,
const VkImageMemoryBarrier * pImageMemoryBarriers);

• commandBuffer - буфер команд, в который будет записана команда.
• eventCount - количество событий в массиве pEvents, должно быть больше 0.
• pEvents - массив событий для ожидания.
• srcStageMask - флаги этапов пайплайна, используемые для отправки сигнала событиям из pEvents, не должно быть равно 0. Параметры такие же как и в предыдущей команде vkCmdSetEvent и флагом VK_PIPELINE_STAGE_HOST_BIT, если событие устанавливается хостом.
• dstStageMask - флаги этапов пайплайна в которых будет ожидание получения сигнала события, не должно быть равно 0. Аналогично srcStageMask.
• pMemoryBarriers - указатель на массив структур VkMemoryBarrier из memoryBarrierCount элементов.
• pBufferMemoryBarriers - указатель на массив структур VkBufferMemoryBarrier из bufferMemoryBarrierCount элементов.
• pImageMemoryBarriers - указатель на массив структур VkImageMemoryBarrier из imageMemoryBarrierCount элементов.

vkCmdWaitEvents ожидает что все события, установленные через vkSetEvent или vkCmdSetEvent, будут в состоянии signaled.
Это имеет три логических фазы:
1. Ожидание этапа пайплайна ,указанного в dstStageMask, пока eventCount событий из pEvents не просигнализируют. Реализация Вулкана может ожидать пока последовательно, каждый из объектов события не перейдет в сигнальное состояние (начиная с первого события указанного в pEvents и заканчивая последним), или ожидать пока все события не перейдут в сигнальное состояние одновременно.
2. Выполнение барьеров памяти, указанных в pMemoryBarriers, pBufferMemoryBarriers и pImageMemoryBarriers.
3. Возобновить выполнение этапов пайплайна, указанных в dstStageMask. Реализация Вулкана может не выполнять команды в порядке пайплайна, таким образом, vkCmdWaitEvents может не увидеть результаты последующих команд vkCmdSetEvent или vkCmdResetEvent, даже если указанный в dstStageMask этап произошел после этапа, указанного в srcStageMask.
Команды, обновляющие статус событий в разных этапах пайплайна могут выполняться в произвольном порядке, если этот порядок не определен через зависимости.

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

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

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

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