Войти
ПрограммированиеФорумГрафика

DirectX12 Основной цикл

#0
14:26, 8 мая 2018

У меня вопрос про архитектуру игрового цикла движка специализированого для DirectX 12
У меня сложилось впечатление что сейчас игры которые используют многопоточность, если грубо обобщить, делают так:
1 | DirectX12 Основной цикл
если подробнее расмотреть рендер и обновление то можно выделить подзадачи, опять же грубое обобщение:
2 | DirectX12 Основной цикл
понятно что некоторые подзадачи могут паралелится сами по себе, некоторые не могут - это не суть важно
меня вбила в ступор статья где микрософт продвигают идею кольцевого буфера для данных Per Frame
https://msdn.microsoft.com/en-us/library/windows/desktop/dn899125.aspx
не понимаю зачем нужен кольцевой буфер, ведь после задачи Wait Fence, мы точно знаем что создание кадра завершено и никакие операции не выполняются, хватило бы обычного буфера-стека, который отбрасывался и заного заполнялся каждый новый кадр
Потому я подумал может они имеют в виду что нужно сделать вот так:
3 | DirectX12 Основной цикл
т.е. загружать данные в gpu именно на стороне задачи обновления движка, оперируя последними N данными, а не N-1
Тогда, если бы обновление выполнялось несколько раз за один период вертикальной развертки - в кольцевом буфере был бы смысл, и не нужна была бы синхронизация state и Δstate(N), т.к. роль двойной буферизации играла бы gpu память.
Но все же я всегда думал что Culling должен выполнятся в задаче рендера, темболее что есть render-specific техники кулинга, типа использования d-buffer из прошлого кадра. Да и отправка данных в gpu тоже смотрится как то не к месту в задаче обновления
в общем, разъясните, знающие люди, как правильно нужно делать многопоточность в directX12, и правильно ли я понял смысл кольцевого буфера который предлагается на msdn?


#1
22:23, 8 мая 2018

A ring buffer is one way to manage an upload heap. The ring buffer holds data required for the next few frames.

#2
22:51, 8 мая 2018

innuendo
> The ring buffer holds data required for the next few frames
но зачем это нужно.
вот еще презентация на тему
https://www.youtube.com/watch?v=mdPeXJ0eiGc начиная с 21:30
все говорят что это мастхэв, возможно я правильно понял и это нужно для буферизации сырых данных рендера для кадра по аналигии с двойной/тройной буферизацией для цепи обмена
т.е. отношения GameEngine->RingBuffer->RenderEngine
такое же как RenderEngine->SwapChain->PresentEngine
но из актуальных есть всего пара методик swapchain, это DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL и DXGI_SWAP_EFFECT_FLIP_DISCARD
первый метод отображает все буферы отправленные в present движок, что подходит например для видеопотока
второй больше походит для игр, где в случае тройной буферизации - первый будет заблокирован present движком, второй содержит буфер для следующего present, и всегда доступный третий буфер для записи, и 2 и 3 буфер меняются местами пока кадр не меняется
В случае RingBuffer тоже можно разделить на двойную буферизацию, когда поток обновления выполняется с той же частотой что и рендеринг, или тройной буферизации когда частота обновления может быть выше частоты рендеринга, но в этом случае используется модель SEQUENTIAL, что не эффективно, т.к. блокирует обновления пока память не освободится, а DISCARD не возможен, потому что у нас один буфер, чтобы он был возможен должны быть 3 stack-like буфера, а не один ring-buffer. тогда не понятно почему они продвигают именно ring-buffer как общий метод

#3
9:32, 10 мая 2018

ashujon
> но зачем это нужно.
может быть для того, чтобы не ждать по GPU отрендрит кадр и переходить к следующему?

ПрограммированиеФорумГрафика

Тема в архиве.