Получение `VkMemoryRequirements` - PullRequest
       3

Получение `VkMemoryRequirements`

2 голосов
/ 01 апреля 2019
  1. Есть ли способ получить правильные значения для структуры VkMemoryRequirements без необходимости сначала выделять буфер и без использования vkGetBufferMemoryRequirements?
  2. Поддерживается ли это?

Мотивация - короткая версия

У меня есть приложение, которое выполняет следующие действия, и все работает, как и ожидалось.

    VkMemoryRequirements memReq;
    vkGetBufferMemoryRequirements(application.shell->device, uniformBuffer, &memReq);
    int memType = application.shell->findMemoryType(memReq.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);

Внутренне findMemoryType перебирает типы памяти и проверяет наличие у них необходимых флагов свойств.

Если я заменю вызов vkGetMemoryRequirements на жестко закодированные значения (которые не переносимы, специфичны для моей системыи получен в результате отладки), все по-прежнему работает, и я не получаю никаких ошибок проверки.

    VkMemoryRequirements memReq = { 768, 256, 1665 };
    int memType = application.shell->findMemoryType(memReq.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);

Приведенный выше код является ИМХО аккуратным, поскольку позволяет предварительно выделить память до того, как она вам действительно понадобится.

Мотивация - Длинная версия

В Vulkan вы создаете буферы, которые изначально не поддерживаются памятью устройства, а на более позднем этапе вы выделяете память и связываете ее с буфером, используя vkBindBufferMemory:

VkResult vkBindBufferMemory(
    VkDevice                                    device,
    VkBuffer                                    buffer,
    VkDeviceMemory                              memory,
    VkDeviceSize                                memoryOffset);

Его спецификация Vulkan гласит, что:

память должна быть выделена с использованием одного из типов памяти, разрешенных в элементе memoryTypeBits структуры VkMemoryRequirements, возвращаемой из вызова vkGetBufferMemoryRequirementsс буфером

Это означает, что перед выделением памяти для буфера вы должны были уже создать буфер.

У меня есть ощущение, что в некоторых обстоятельствах это будетполезно предварительно выделить часть памяти, прежде чем она вам действительно понадобится;в большинстве разновидностей OpenGL, с которыми я сталкивался, это было невозможно, но Vulkan не должен страдать от этого ограничения, верно?

  1. Существует ли (более или менее автоматический) способ получитьтребования к памяти до создания первого буфера?
  2. Поддерживается ли он / соответствует?

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

1 Ответ

2 голосов
/ 01 апреля 2019

Этот вопрос уже признает, что ответ «нет»;Кажется, вы просто хотите покончить с тем, что уже знаете.Что вы не можете.

Код, который вы показали с жестко закодированными значениями, работает, потому что вы уже знаете ответ .Дело не в том, что Вулкан требует от вас задать вопрос;Vulkan требует, чтобы вы предоставили буферы, которые используют ответ.

Однако, поскольку «ответ» зависит от реализации, он изменяется в зависимости от аппаратного обеспечения.Это может измениться при установке нового драйвера.На самом деле, он может измениться даже в зависимости от того, какие расширения или функции Vulkan вы активируете при создании VkDevice.

. Сказанное:

Что подразумеваетчто перед выделением памяти для буфера вы должны были уже создать буфер.

Неверно.Требуется, чтобы у вас был ответ и вы выбрали смещение памяти и байтов, соответствующее этому ответу.Но Vulkan определенно свободно о том, что на самом деле означает «ответ».

Vulkan имеет определенные гарантии вместо , которые позволяют вам узнать ответ для определенного буфера /изображение не обязательно спросив об этом конкретном VkBuffer/Image объекте.Детали довольно сложны, но для буферов они довольно слабые.

Основная идея заключается в том, что вы можете создать тест VkBuffer/Image и спросить о его свойствах памяти.Затем вы можете использовать этот ответ, чтобы узнать, какие свойства буферов, которые вы намереваетесь использовать, «похожи» на них.По крайней мере, Vulkan гарантирует, что два одинаковых буфера / изображения (форматы, флаги использования, размеры и т. Д.) Всегда будут давать идентичные свойства памяти.

Но Vulkan также предлагает несколько других гарантий.Как правило, свойства памяти говорят о трех вещах:

  • Типы памяти, к которым может быть привязан этот объект.
  • Требование выравнивания для смещения для объекта памяти.
  • Размер байта, который объект будет занимать в памяти.

Для размера вы получаете только самую базовую гарантию: эквивалентный буфер / изображения будут давать эквивалентные размеры.

Для выравнивания изображения такие же строгие, как и размеры: только эквивалентные изображения гарантируют одинаковое выравнивание.Но для буферов все более слабо.Если тестовый буфер отличается только флагами использования, а конечный буфер использует подмножество флагов использования, то выравнивание для конечного буфера не будет на более ограничительным , чем тестовый буфер.Таким образом, вы можете использовать выравнивание из тестового буфера.

Для типов памяти все еще более свободно.Для изображений важны только следующие значения:

  • Черепица
  • Некоторые флаги памяти (привязка разреженных / разделенных экземпляров)
  • Цветовой формат изображения илиглубина / трафарет
    • Если формат изображения - глубина / трафарет, то форматы должны соответствовать
  • Внешняя память
  • Использование временного выделения

Если все они одинаковы для двух VkImage объектов, то стандарт гарантирует, что все такие образы будут поддерживать один и тот же набор типов памяти.

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

Oh, и линейные изображения и буферы всегда должны использоваться по крайней мере в одном отображаемом, связном типе памяти.Конечно, это требует, чтобы вы создали действительный VkDevice/Image с этими полями использования и флажками, поэтому, если устройство не позволяет (например) линейным изображениям использоваться в качестве текстур, то это останавливается задолго до того, как спрашивать о памятисвойства.

...