Зависимости подпрохода для одного подпрохода. как?

Итак, у меня есть проход рендеринга с одним подпроходом, который рисует прямо во фреймбуфер. Спецификация не заставляет меня использовать зависимости - если я их опускаю, реализация вставляет их неявно (хотя я не понимаю, почему она использует srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT для первого подпрохода - этот этап означает самое начало, т.е. что-нибудь).

Но, как обычно, с Vulkan - лучше быть откровенным. И вот в чем путаница - несколько источников по-разному используют подпроходы.

  1. В примере с кубом SDK они вообще не используются.

  2. В Vulkan-tutorial используется только один:

    dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
    dependency.dstSubpass = 0;
    dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
    dependency.srcAccessMask = 0;
    dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
    dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
    

    Почему здесь ноль srcAccessMask?

  3. API без секретов использует два:

    dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
    dependency.dstSubpass = 0;
    dependency.srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
    dependency.srcAccessMask = VK_ACCESS_MEMORY_READ_BIT;
    dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
    dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
    

    а также

    dependency.srcSubpass = 0;
    dependency.dstSubpass = VK_SUBPASS_EXTERNAL;
    dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
    dependency.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
    dependency.dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
    dependency.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
    

    Не очень понятно, почему именно srcStageMaskVK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT в первом подпроходе - нет этот этап следует использовать для зависимостей выполнения, но здесь мы нужна зависимость от памяти? Тот же вопрос, почему dstStageMask есть VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT во втором подпроходе?

  4. Примеры синхронизации Khronos используют один:

    dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
    dependency.dstSubpass = 0;
    dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
    dependency.srcAccessMask = 0;
    dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
    dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
    

    Почему srcAccessMask равен 0?

  5. А вот моя попытка с двумя зависимостями:

        dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
        dependency.dstSubpass = 0;
        dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; // need to wait until
    presentation is finished reading the image
        dependency.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT;
        dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; // we are writing to
    the image in this stage
        dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
    
    and
    
        dependency.srcSubpass = 0;
        dependency.dstSubpass = VK_SUBPASS_EXTERNAL;
        dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; // we are writing to
    the image in this stage
        dependency.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
        dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; // presentation reads
    image in this stage (is it?)
        dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT;
    

Все это очень сбивает с толку. Как видите, у нескольких компетентных источников разное видение. Какой использовать? Как понять эти зависимости?

4
0
1 833
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

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

  1. это старый пример, возникший до того, как многие особенности синхронизации были должным образом закреплены.

  2. Цель состоит в том, чтобы синхронизировать использование семафора для ожидания результата vkAcquireNextImage с рендерингом. Это опасность записи после чтения, и семафор будет включать синхронизацию видимости памяти. Так что в srcAccessMask нет необходимости.

  3. Опять же, барьер предназначен для синхронизации с семафором. При отправке командного буфера в очередь вы можете указать, какие этапы ожидают каких семафоров. В этом случае они используют нижнюю часть ступени трубы вместо VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT.

  4. тот же ответ, что и 2, единственная разница с dstAccessMask

  5. На вики-странице, на которую я ссылался выше, используется следующее:

    /* Only need a dependency coming in to ensure that the first
       layout transition happens at the right time.
       Second external dependency is implied by having a different
       finalLayout and subpass layout. */
    VkSubpassDependency dependency = {
        .srcSubpass = VK_SUBPASS_EXTERNAL,
        .dstSubpass = 0,
        // .srcStageMask needs to be a part of pWaitDstStageMask in the WSI semaphore.
        .srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
        .dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
        .srcAccessMask = 0,
        .dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
        .dependencyFlags = 0};
    
    /* Normally, we would need an external dependency at the end as well since we are changing layout in finalLayout,
       but since we are signalling a semaphore, we can rely on Vulkan's default behavior,
       which injects an external dependency here with
       dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
       dstAccessMask = 0. */
    

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

храповой урод, спасибо за объяснение. Пример 4 действительно взят из репозитория Khronos на github. С примером 3 (Intel) я все еще в замешательстве - второй этап назначения субпрохода - это VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, но этап назначения ожидания информации отправки - это VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT - не так ли? Да, я смешал признаки второго барьера - исправлена ​​ошибка копирования и вставки. Сейчас я не понимаю, как в игру вступает семафор? Как он взаимодействует с зависимостями подпроходов? Где я могу прочитать об этом подробнее?

nikitablack 26.10.2018 12:15

вторая зависимость в 3 синхронизирует конец рендеринга с материалом после завершения командного буфера. Механизмы межкомандной синхронизации буфера всегда ждут полного завершения командного буфера.

ratchet freak 26.10.2018 12:55

@nikitablack желательно в главах спецификации Семафорная сигнализация и Ожидание семафоров и отключение сигналов. Узнайте, что такое область синхронизации, область доступа и порядок отправки, в главе Зависимости выполнения и памяти, и тогда вы практически поймете всю синхронизацию Vulkan.

krOoze 26.10.2018 15:06

Другие вопросы по теме