Изображение определенных размеров имеет странный объем памяти

У меня странное поведение: изображение размером 500x500 формата R8G8B8A8_UNORM занимает дополнительный объем памяти 8000 байт, в то время как другие размеры занимают ровно ширину * высоту * 4 байта. Я делаю следующее:

  1. Нарисовать цвет-вложение
  2. Скопируйте вложение цвета в изображение, видимое хостом, и сопоставьте его (после всех переходов макета).

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

  • w=1000,h=1000: 4 000 000 байт
  • w=600,h=600: 1 440 000 байт
  • w=500,h=500: 1 008 000 байт (должно быть 1 000 000)

Результирующее изображение в последнем случае искажено. Есть ли что-то очевидное, что я упускаю, что может привести к другим формулам для размера памяти, кроме w * h * 4? Изображение, видимое хосту, имеет линейную мозаику и было переведено в макет VK_IMAGE_LAYOUT_GENERAL перед командой vkMapMemory.

Это информация о создании цветного вложения:

VkImageCreateInfo color_image_info = {
  VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // sType,
  nullptr, // pNext (see documentation, must be null)
  0, // image flags
  VK_IMAGE_TYPE_2D, // image type
  this->color_format_, // image format
  {this->render_width_, this->render_height_, 1}, // image extent
  1, // level of detail = 1
  1, // layers = 1
  VK_SAMPLE_COUNT_1_BIT, // sampling
  VK_IMAGE_TILING_OPTIMAL, // optimal tiling
  VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // used for color
  VK_SHARING_MODE_EXCLUSIVE, // sharing between queue families
  1, // number queue families
  &this->queue_family_index_, // queue family index
  VK_IMAGE_LAYOUT_PREINITIALIZED // initial layout
};

И это изображение, видимое хостом:

VkImageCreateInfo host_visible_image_info = {
  VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // sType,
  nullptr, // pNext (see documentation, must be null)
  0, // image flags
  VK_IMAGE_TYPE_2D, // image type
  this->color_format_, // image format
  {this->render_width_, this->render_height_, 1}, // image extent
  1, // level of detail = 1
  1, // layers = 1
  VK_SAMPLE_COUNT_1_BIT, // sampling
  VK_IMAGE_TILING_LINEAR, // linear tiling
  VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, // used for color
  VK_SHARING_MODE_EXCLUSIVE, // sharing between queue families
  1, // number queue families
  &this->queue_family_index_, // queue family index
  VK_IMAGE_LAYOUT_PREINITIALIZED // initial layout // TODO: !!!Find out whether this has to be transisition first
};

person Michael Franzen    schedule 11.09.2016    source источник
comment
Иногда из соображений выравнивания длина строки увеличивается до степени, кратной 2, путем заполнения. Вы должны попробовать ширину 500, 501, 502... и найти закономерность. В данных случаях ширина кратна 8 пикселям (32 байта), кроме 500; следующее кратное 504.   -  person Yves Daoust    schedule 11.09.2016
comment
@YvesDaoust Да, ты прав. для w=504 изображение выглядит нормально. Так что, думаю, я просто вычислю padding = (required_size - computed_size)/width/4. Если вы проверите свой ответ, я с благодарностью приму его. редактировать: хорошо, ваш распорядок имеет больше смысла. Спасибо!   -  person Michael Franzen    schedule 11.09.2016
comment
Изображение, полученное в последнем случае, искажено. Как узнать, что оно искажено?   -  person Nicol Bolas    schedule 11.09.2016
comment
@MichaelFranzen: было бы неплохо исследовать другие размеры, мое объяснение может быть правильным просто случайно.   -  person Yves Daoust    schedule 11.09.2016


Ответы (1)


Так что, я думаю, я просто вычислю padding = (required_size - вычисленный_размер)/width/4.

No.

Vulkan позволяет запрашивать макет изображения (с линейной мозаикой) через vkGetImageSubresourceLayout. Это то, что вы должны были использовать, когда пытались сопоставить текстуру и получить доступ к ее битам.

VkSubresourceLayout сообщит вам шаг строки изображения (то есть: количество байтов, которое вы должны сместить, чтобы добраться до пикселя непосредственно под ним/над ним). Это значение не обязательно должно быть равно ширине * размеру в пикселях. Вам необходимо запрашивать каждое изображение, к которому вы хотите получить доступ.

person Nicol Bolas    schedule 11.09.2016
comment
Метод называется vkGetImageSubresourceLayout, в остальном работает хорошо. Большое спасибо. - person Michael Franzen; 11.09.2016