Вопрос № 1: Это предположение верно?
Возможно, нет, но это зависит от вашей платформы, поддерживаете ли вы альтернативу.Для передачи GPU-> CPU действительно есть три варианта:
1.HOST_VISIBLE
Этот тип видим для хоста и гарантированно является связным, но не кэшируется на хосте.Чтение ЦП будет очень медленным, но это может быть нормально, если вы читаете только небольшой объем данных (и может быть дешевле, чем выдача vkInvalidateMappedMemoryRanges()
, и при этом мало места для потоковой передачи данных в кэш ЦПесли вы никогда не ожидаете снова прикоснуться к нему на процессоре).
2.HOST_VISIBLE |HOST_CACHED
Этот тип является видимым для хоста и кэшируется, но не гарантированно будет согласованным (CPU и GPU могут видеть разные вещи по одному и тому же адресу, если вы вручную не применяете согласованность).Для этого типа памяти вы должны использовать vkInvalidateMappedMemoryRanges()
после записи в GPU и до чтения ЦП (или vkFlushMappedRange()
для другого направления), чтобы один процессор мог видеть то, что написал другой, или вы могли читать устаревшие данные.
3.HOST_VISIBLE |HOST_CACHED |HOST_COHERENT
Наконец, у вас есть кешируемый И когерентный тип памяти хоста, который дает вам лучший выбор, если у вас есть считываемые данные с высокой пропускной способностью на CPU.НО это не гарантируется быть доступным на всех платформах.Для массовых считываний данных на ЦП я бы ожидал, что это будет наиболее эффективно в тех случаях, когда они доступны.
Стоит отметить, что нет «лучших» настроек памяти для всех выделений.Не используйте кэшированную или связную память хоста для вещей, которые вы никогда не собираетесь передавать обратно в ЦП (когерентность памяти не свободна с точки зрения мощности или производительности памяти).
Вопрос № 2: Чтопроисходит под капотом во время vkInvalidateMappedMemoryRanges?Это просто memcpy из некоторого внутреннего кэша или это может быть более длительная процедура?
В случае, когда у вас некогерентная память, она делает все необходимое, чтобы сделать их связными.Как правило, это означает аннулирование (удаление) строк кэша в кэше ЦП, которые могут содержать устаревшие копии данных, гарантируя, что последующие чтения ЦП увидят версию, которую фактически записал графический процессор.
Вопрос № 3:Если это может занять больше времени (т. Е. Это не просто memcpy), то у меня, вероятно, должна быть возможность синхронизироваться с завершением, верно?
Нет.Аннулирование - это операция на стороне ЦП, поэтому для ее завершения требуется время, а ЦП занята, когда операция завершается.В целом вы можете избежать необходимости делать это вообще, используя когерентную память.