короче, я нашёл, наконец-то ответ: https://community.khronos.org/t/framebuffer-attachments-clarification/7595/7
суть в следующем. так как каждый фрейм сабмитится как минимум в одном отдельном command buffer'е, то гарантируется,что каждый command buffer закончит выполнение перед началом выполнения следующего*:
https://renderdoc.org/vkspec_chunked/chap2.html#fundamentals-execmodel
это значит, что локальные для кадра ресурсы (которые создаются во время рендера кадра и не испольузются за его пределами) вроде gbuffer'а и depth buffer'а можно не создавать по несколько копий, а использовать в единственном экземпляре. это как бы и через sanity check проходит — никогда не создавали в предыдущих API по несколько копий screenspace рендертаргетов, всегда был один сет, даже в случае с double/triple buffering'ом. несколько копий создаётся только для самого swapchain image, который создаётся вместе со swapchain'ом.
ресурсы же, которые модифицируются на CPU и которые, следовательно, должны существовать дольше времени рендера самого кадра, (буферы констант, всякие замапленные буферы вершин, все command buffer'ы) нужно создавать отдельную копию для каждого frame in flight.
* объяснение неправильное, так как "respect submission order" обозначает, что они именно начинают выполняться в нужно порядке, а закончить могут как попало.
я не уверен, что объяснение в предыдущем объяснении корректное, но выводы — сто пудов должны быть именно такими. тонкий момент спеки заключается в этом предложении:
> Command buffers submitted to a single queue respect submission order
"respect submission order" может обозначать, что следующий command buffer не начнёт выполняться, пока предыдущий не закончит, а может означать, что command buffer'ы начинают выполнение в порядке того, как их засабмитили (и могут выполняться параллельно).
однако, должно быть какое-то конкретное объяснение, почему depth buffer можно использовать один. должна быть формальная гарантия, что его содержимое не побъётся следующим кадром, пока текущий не отобразится на экране.
короче, поговорил с людьми, которые шарят. теперь уже практически полностью уверен, как быть. суть в том, что если не предпринимать никаких действий, то действительно нет гарантии, что пока один фрейм рендерится, его depth buffer не перетрёт следующий фрейм. однако, достаточно первым барьером в каждом кадре поставить такой:
accessPattern.stage = vk::PipelineStageFlagBits::eBottomOfPipe; accessPattern.accessMask = vk::AccessFlags(); accessPattern.layout = vk::ImageLayout::eUndefined; accessPattern.stage = vk::PipelineStageFlagBits::eLateFragmentTests | vk::PipelineStageFlagBits::eEarlyFragmentTests; accessPattern.accessMask = vk::AccessFlagBits::eDepthStencilAttachmentRead | vk::AccessFlagBits::eDepthStencilAttachmentWrite; accessPattern.layout = vk::ImageLayout::eDepthStencilAttachmentOptimal;
accessPattern.stage = vk::PipelineStageFlagBits::eTopOfPipe;
Suslik
> короче, поговорил с людьми, которые шарят.
это кто такие?
> никогда не создавали в предыдущих API по несколько копий screenspace
> рендертаргетов, всегда был один сет
только в предыдущих API не было же всяких асинков и прочей ботвы
Suslik
> eBottomOfPipe же говорит, что ресурс можно инициализировать, как только предыдущие дроколлы дойдут до конца пайпа, то есть ресурсом перестанут пользоваться.
ты каждый кадр это ждешь, а значит на некоторых видюхах и некоторых задачах для рендера и некоторых способов организации задач для рендера - просядешь по производительности. а мог бы просто создать еще сет
Suslik
> . однако, достаточно первым барьером в каждом кадре поставить такой:
Разве действие барьера распространяется не на текущий комманд буффер? Т.е., по идее, он отработает в холостую.
*Lain*
> ты каждый кадр это ждешь
это означает буквально "дождаться окончания рендера предыдущего кадра". то есть то, что любой api уровня dx11 всё равно всегда делает по умолчанию.
*Lain*
> а мог бы просто создать еще сет
ага, лол, особенно если gbuffer размером метров на 150. 3 сета, так как у меня 3 кадра в полёте.
BingoBongo
> Разве действие барьера распространяется не на текущий комманд буффер?
https://github.com/KhronosGroup/Vulkan-Docs/issues/300
Suslik
Вот и верь после этого спецификациям.
Suslik
> это значит, что локальные для кадра ресурсы (которые создаются во время рендера
> кадра
ресурсы создаются во время рендера кадра ?
Suslik
> и это будет гарантировать, что создастся execution dependency, который дождётся
> окончания работы предыдущего пайплайна (eBottomOfPipe).
Между кадрами лучше уж вставить execution barrier на все команды
Suslik
> однако, достаточно первым барьером в каждом кадре поставить такой:
и такой вариант работает 100 %, я так понимаю ?
/A\
> Между кадрами лучше уж вставить execution barrier на все команды
тоже так думал. это имеет смысл.
Suslik
Ну и если у тебя асинк компьют или трансфер, то в любом случае будут синхронизации через семафоры, которые как раз заменят барьер в начале кадра.
Тема в архиве.