Retrieving Image Memory Alignment Limits

I have a few suballocators that manage memory for small resources, but I’ve hit an alignment problem when allocating a texture (on an AMD card under Linux). The memory requirements for the VkImage report a 64K alignment which is not consistent with the limits in the device properties (the largest there is 4K for bufferImageGranularity). The code in question has worked for several months; I suspect the addition of some BC7 formats is triggering the new requirement.

I’m likely missing an alignment limit from somewhere but I can’t find it in the spec or any of the device properties. I need that limit to configure the alignment settings for the suballocator–I know the memory pool ahead of time, but not the image format(s) it’ll need to support, so I don’t think vkGetImageMemoryRequirements is really feasible here. There should be something like D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT available from somewhere.

I’ve looked at VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT but that doesn’t report the required alignment either.

Everything works fine under Windows with an nVidia card, and the Linux/AMD drivers have given me problems before. It’s possible the driver is simply returning the wrong values.

Any suggestions for where to look or how to tackle this?

It doesn’t have to be consistent. In fact, bufferImageGranularity has nothing to do with this. It’s about what constitutes memory aliasing between linear and tiled images.

As far as the Vulkan specification is concerned, every combination of flags and formats for images can give you a completely different alignments. In fact, until KHR_maintenance4, an implementation was technically allowed give you different alignments for two VkImage objects that were created using the exact same parameters.

Not that implementations did such things, but the specification didn’t require it, so technically, user code shouldn’t have made that assumption. Even though everyone totally did/does.

But that’s the only answer Vulkan gives you.

Vulkan doesn’t have a setting that gives you a generic number that represents an alignment that will work for all images. If you need such a thing, then you must first restrict yourself to some set of image formats, usage flags, etc. Then you must query the requirements for each of them and aggregate them together to produce the single alignment number you’re looking for.

If you’re not willing to do that, if you want to be able to handle whatever the user throws at you, then you need to treat your allocator more like a memory heap than a pool allocator or something. You need to expect that alignments could be anything and build an allocator that can handle arbitrary alignments.

Thanks for the quick response. It’s baffling Vulkan can’t give a worst-case alignment for images, even if it’s hardware/driver-dependent (surely the video driver knows?).

The inconsistency I was referring to is due to this bit in the docs:

bufferImageGranularityis the granularity, in bytes, at which buffer or linear image resources, and optimal image resources **can** be bound to adjacent offsets in the sameVkDeviceMemory` object without aliasing.

It sounds like that isn’t actually true if, aliasing concerns aside, images can require courser granularity via their memory alignment requirements. I mean, knowing that images must be placed at (for example) 4K intervals to avoid aliasing isn’t helpful if images can’t be placed at 4k intervals at all.

Anyway, I can either probe various image formats or tweak my allocation scheme to work around this.

You can’t cast aside aliasing concerns, because that’s literally all bufferImageGranularity is for:

This restriction is only needed when a linear resource and a non-linear resource are adjacent in memory and will be used simultaneously. The memory ranges of adjacent resources can be closer than bufferImageGranularity, provided they meet the alignment requirement for the objects in question.

Also:

Despite its name, bufferImageGranularity is really a granularity between “linear” and “non-linear” resources.

It’s specifically and only about preventing aliasing between buffer/linear and tiled images that occupy adjacent memory. It is an additional issue that crops up in certain cases, not a hard requirement for every image.

That’s not inconsistency; you simply misinterpreted the purpose of the value.