Если вы собираетесь вести параллельную запись, вам лучше иметь отдельный пул для каждого потока, не так ли?
Я не понимаю, как наличие отдельного пула для каждого потока «убивает всю цель пулов команд, когда дело доходит до параллельной записи». На самом деле, это немного помогает, поскольку каждый поток может управлять своим собственным пулом команд по своему усмотрению.
Рассмотрим структурную разницу между, скажем, пулом дескрипторов и пулом команд. С пулом дескрипторов вы в основном говорите ему, что именно вы из него выделите. VkDescriptorPoolCreateInfo
предоставляет подробную информацию, которая позволяет реализациям распределять заранее точно, сколько памяти вы будете использовать для каждого пула. И вы не можете выделить больше этого из пула дескрипторов.
Напротив, VkCommandPoolCreateInfo
не содержит ... ничего. О, вы скажете, могут ли буферы команд быть первичными или вторичными. Вы говорите, будут ли буферы команд часто сбрасываться или постоянными. И еще пара вещей. Но кроме этого вы ничего не говорите о содержимом буферов команд. Вы даже не даете ему информацию о том, сколько буферов вы выделите.
Пулы дескрипторов должны быть фиксированными: выделяться по мере необходимости, но в пределах количества, установленного во время создания. Командные буферы должны быть очень динамичными: выделяться по мере необходимости для ваших конкретных случаев использования.
Думайте об этом как о каждом пуле, имеющем свой malloc / free. Поскольку пользователь вынужден синхронизировать доступ к пулам и их буферам, это означает, что каждая vkCmd*
функция не обязана делать это при выделении памяти. Это ускоряет создание команды. Это помогает многопоточности. Когда поток решает сбросить свой пул команд, ему не нужно блокировать какие-либо мьютексы или другие подобные вещи, чтобы сделать это.
Концептуально нет ничего плохого в том, чтобы иметь один пул команд для каждого потока. В самом деле, наличие двух на поток (двойная буферизация) имеет еще больший смысл.
Я лично не знаю, почему бы вам просто не записать все заранее.
Потому что вы не делаете статическую техническую демонстрацию.
Я предполагаю, что это происходит из-за недостатка опыта, но я представил, что параллельная запись будет выглядеть как «потоки 2-N записывают вторичные буферы команд, поток 1 вызывает их все в одном первичном буфере команд», и в этом случае есть только одна команда буфер на поток. Вот почему я сказал, что это убивает цель пулов команд, потому что вы делаете только одно распределение для каждого пула.
Это, безусловно, жизнеспособная форма параллельной записи буферов команд. Но вы упустили две вещи.
Хотя это, безусловно, одна из форм параллельной записи, но не единственная. Если вы выполняете отложенный рендеринг, поток, который строит CB для проходов освещения, завершит свою работу намного раньше, чем один из потоков, ответственных за (часть) прохода геометрии. Таким образом, хорошо спроектированная многопоточная система должна будет распределять работу по потокам в зависимости от необходимости, а не на основе какого-то фиксированного расположения вещей. Таким образом, отдельный поток часто приводит к созданию нескольких буферов команд.
И даже если бы это было не так, вы забываете о буферизации. Когда приходит время создавать CB для следующего кадра, вы не можете просто перезаписать существующие. В конце концов, они, вероятно, все еще в очереди на работу. Таким образом, каждому потоку потребуется как минимум два CB; тот, который в настоящее время выполняется, и тот, который в настоящее время строится.
И даже если это не так, пулы команд выделяют всю память, связанную с CB. Есть причина, по которой я сравнил их с malloc/free
. Даже если вы используете только один CB с определенным пулом, тот факт, что выделения этого CB (что может произойти из-за любой vkCmd*
функции) никогда не должны синхронизироваться с другим потоком, - это хорошо.
Так что нет, это никоим образом не препятствует возможности использования нескольких потоков для построения CB.
person
Nicol Bolas
schedule
12.07.2016