Michael Franzen Michael Franzen - 2 months ago 13
C++ Question

Image of specific dimensions has strange memory size

I'm having the strange behaviour that an image of size 500x500 of format R8G8B8A8_UNORM takes an additional memory amount of 8000 byte while other dimensions take exactly width*height*4 bytes. I'm doing the following:


  1. Draw color-attachment

  2. Copy the color-attachment to a host-visible image and map it (after all the layout transitions).



Ths works fine, however, when checking for the host-visible image's memory requirements before mapping, I get the following results:


  • w=1000,h=1000: 4,000,000 byte

  • w=600,h=600: 1,440,000 byte

  • w=500,h=500: 1,008,000 byte (this should be 1,000,000)



The resulting image in the last case is malformed. Is there anything obvious that I'm missing that could result in different formulas for the memory size other than w*h*4? The host-visible image has linear-tiling and has been transitioned to the layout
VK_IMAGE_LAYOUT_GENERAL
before the vkMapMemory command.

This is the creation info of the color attachment:

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
};


And this is the host-visible image:

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
};

Answer

So I guess I will just just compute padding = (required_size - computed_size)/width/4.

No.

Vulkan permits you to query the layout of an image (with linear tiling) via vkGetSubresourceLayout. That's what you should have been using when you tried to map the texture and access its bits.

VkSubresourceLayout will tell you the row-pitch of the image (ie: the number of bytes you must offset to get to the pixel directly below/above it). This value is not required to be width * pixel size. You have to query it for each image you want to access.