Порядок действий команд, использующих зависимость subpass? - PullRequest
0 голосов
/ 06 февраля 2020

Из того, что я прочитал, команды в одном буфере команд могут быть не в порядке без явной синхронизации. Вот что говорит vulkan spe c (https://vulkan.lunarg.com/doc/view/1.0.26.0/linux/vkspec.chunked/ch02s02.html#fundamentals -queueoperation-commandorder )

"Работа, выполняемая при выполнении команд действия, часто может перекрываться или переупорядочиваться, но это не должно изменять состояние, которое будет использоваться каждой командой действия. В общем, команды действия - это те команды, которые изменяют вложения кадрового буфера, буфер чтения / записи или память изображений или выполняют запись в пулы запросов. "

Редактировать Сначала я подумал, что команды set state будут действовать как своего рода барьер для обеспечения порядка команд draw. Мне уже объяснили, что это неправильно. Итак, я смотрю на этот пример эффекта цветения в Vulkan https://github.com/SaschaWillems/Vulkan/blob/master/examples/bloom/bloom.cpp

/*First render pass: Render glow parts of the model (separate mesh) to an offscreen frame buffer*/

vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.scene, 0, 1, &descriptorSets.scene, 0, NULL);
vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.glowPass);
VkDeviceSize offsets[1] = { 0 };
vkCmdBindVertexBuffers(drawCmdBuffers[i], 0, 1, &models.ufoGlow.vertices.buffer, offsets);
vkCmdBindIndexBuffer(drawCmdBuffers[i], models.ufoGlow.indices.buffer, 0, VK_INDEX_TYPE_UINT32);
vkCmdDrawIndexed(drawCmdBuffers[i], models.ufoGlow.indexCount, 1, 0, 0, 0);
vkCmdEndRenderPass(drawCmdBuffers[i]);

/*Second render pass: Vertical blur
Render contents of the first pass into a second framebuffer and apply a vertical blur
This is the first blur pass, the horizontal blur is applied when rendering on top of the scene*/

renderPassBeginInfo.framebuffer = offscreenPass.framebuffers[1].framebuffer;
vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayouts.blur, 0, 1, &descriptorSets.blurVert, 0, NULL);
vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines.blurVert);
vkCmdDraw(drawCmdBuffers[i], 3, 1, 0, 0);
vkCmdEndRenderPass(drawCmdBuffers[i]);

Вот 2 зависимости подпрохода, используемые обоими проходами рендеринга

dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL;
dependencies[0].dstSubpass = 0;
dependencies[0].srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
dependencies[0].srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;

dependencies[1].srcSubpass = 0;
dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL;
dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
dependencies[1].dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
dependencies[1].dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;

My Тогда становится понятно, что эти 2 зависимости подпроцесса отвечают за порядок выполнения прохода рендеринга, но я пока не уверен, как, поскольку я все еще не совсем уверен относительно зависимостей подпрохода. Если я правильно понимаю, можете ли вы объяснить мне, почему зависимость subpass помогает упорядочить команду draw? Если я ошибаюсь, то что обеспечивает порядок команд рисования?

1 Ответ

3 голосов
/ 07 февраля 2020

Итак, происходит то, что что-то отображается в img1 (как цветовая привязка). Затем img1 выбирается, и материал записывается в img2 (в виде цветного вложения). Затем img2 выбирается и записывается в образ свопчейна.

dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL;
dependencies[0].srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
dependencies[0].srcAccessMask = VK_ACCESS_SHADER_READ_BIT;

dependencies[0].dstSubpass = 0;
dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;

Для первого и второго экземпляра прохода рендеринга это, возможно, блокирует некоторую предыдущую выборку ресурса. Вероятно, из предыдущего кадра. Предполагая, что между последующими кадрами нет другого syn c.

dependencies[1].srcSubpass = 0;
dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;

dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL;
dependencies[1].dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
dependencies[1].dstAccessMask = VK_ACCESS_SHADER_READ_BIT;

Теперь вложение цвета записано в VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, а также, что более важно (и удобно), операция сохранения происходит на этой же стадии. для цветных вложений. Это также всегда VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT независимо от того, STORE или DONT_CARE.

VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, и VK_ACCESS_SHADER_READ_BIT снова хорошо подходит для выборки изображений (в фрагментном шейдере).

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

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


Это расширенный пример, и ожидается, что вы уже поймете синхронизацию.

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

Зависимости и барьеры подпроцесса определяют зависимость таким образом : src Область синхронизации завершает выполнение до того, как dst Область синхронизации начинает выполнение.

Зависимости и барьеры подпроцесса практически одинаковы. Барьеры обычно используются за пределами прохода рендеринга, в то время как зависимости от него проходят. Подпроходы не расположены друг к другу, поэтому зависимости подпроцесса дополнительно имеют параметр *Subpass, а области синхронизации ограничены только указанным подпроходом. VK_SUBPASS_EXTERNAL означает, что материал до vkCmdBeginRenderPass \ after vkCmdEndRenderPass является частью области синхронизации.

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

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