@@ -73,6 +73,8 @@ struct suballocator_private
7373 std::vector<lookup> image_lookup;
7474 std::vector<lookup> buffer_lookup;
7575 std::vector<lookup> tensor_lookup;
76+ // / Does this device have the an annoying optimal-to-linear padding requirement? If so, put optimal and linear objects in different memory heaps
77+ bool allow_mixed_tiling = true ;
7678
7779 void print_memory_usage ();
7880 uint32_t get_device_memory_type (uint32_t type_filter, VkMemoryPropertyFlags& properties);
@@ -90,6 +92,15 @@ struct suballocator_private
9092
9193// helpers
9294
95+ static VkMemoryPropertyFlags prune_memory_flags (VkMemoryPropertyFlags flags)
96+ {
97+ if ((flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) || (flags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT))
98+ {
99+ flags &= ~VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; // do not require this bit in these cases
100+ }
101+ return flags;
102+ }
103+
93104void suballocator_private::print_memory_usage ()
94105{
95106 printf (" Suballocator memory usage:\n " );
@@ -166,6 +177,9 @@ void suballocator::setup(VkPhysicalDevice physicaldevice)
166177 if (priv->run )
167178 {
168179 wrap_vkGetPhysicalDeviceMemoryProperties (physicaldevice, &priv->memory_properties );
180+ VkPhysicalDeviceProperties pdprops = {};
181+ wrap_vkGetPhysicalDeviceProperties (physicaldevice, &pdprops);
182+ priv->allow_mixed_tiling = (pdprops.limits .bufferImageGranularity == 1 );
169183 }
170184 else
171185 {
@@ -175,6 +189,7 @@ void suballocator::setup(VkPhysicalDevice physicaldevice)
175189 priv->memory_properties .memoryHeapCount = 1 ;
176190 priv->memory_properties .memoryHeaps [0 ].size = UINT64_MAX;
177191 priv->memory_properties .memoryHeaps [0 ].flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT;
192+ priv->allow_mixed_tiling = true ;
178193 }
179194 assert (priv->memory_properties .memoryTypeCount > 0 );
180195}
@@ -262,12 +277,11 @@ suballoc_location suballocator_private::add_object(VkDevice device, uint16_t tid
262277 h.deletes .clear ();
263278 }
264279 // find suballocation
265- if (h.tid == tid && (flags & f) == flags && h.free >= s.size && h.memoryTypeIndex == memoryTypeIndex && h.tiling == tiling)
280+ if (h.tid == tid && (flags & f) == flags && h.free >= s.size && h.memoryTypeIndex == memoryTypeIndex && ( h.tiling == tiling || allow_mixed_tiling) )
266281 {
267282 // First case: nothing allocated in heap. In this case, we do not care about alignment, because according to the spec:
268283 // "Allocations returned by vkAllocateMemory are guaranteed to meet any alignment requirement of the implementation."
269- // Also second case: some memory is available before the first allocation. Like above, we are guaranteed not to have
270- // to care about alignment in this case.
284+ // Also second case: We place our allocation first. Like above, we are guaranteed not to have to care about alignment.
271285 if (h.subs .empty () || (h.subs .front ().offset >= s.size ))
272286 {
273287 s.offset = 0 ;
@@ -354,30 +368,28 @@ void suballocator_private::bind(heap& h, const suballocation& s)
354368 assert (s.offset + s.size <= h.total );
355369}
356370
357- suballoc_location suballocator::add_image (uint16_t tid, VkDevice device, VkImage image, uint32_t image_index, VkMemoryPropertyFlags flags, VkImageTiling tiling, VkDeviceSize min_size )
371+ suballoc_location suballocator::add_image (uint16_t tid, VkDevice device, VkImage image, const trackedimage& image_data )
358372{
359- if ((flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) || (flags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT))
360- {
361- flags &= ~VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; // do not require this bit in these cases
362- }
363373 VkMemoryRequirements2 req = {};
364- const bool dedicated = priv->fill_image_memreq (device, image, req, min_size);
365- const uint32_t memoryTypeIndex = priv->get_device_memory_type (req.memoryRequirements .memoryTypeBits , flags);
374+ VkMemoryPropertyFlags memory_flags = prune_memory_flags (image_data.memory_flags );
375+ const bool dedicated = priv->fill_image_memreq (device, image, req, image_data.size );
376+ const uint32_t memoryTypeIndex = priv->get_device_memory_type (req.memoryRequirements .memoryTypeBits , memory_flags);
366377 suballocation s;
367378 s.type = VK_OBJECT_TYPE_IMAGE;
368379 s.handle .image = image;
369- s.size = std::max (req.memoryRequirements .size , min_size );
380+ s.size = std::max (req.memoryRequirements .size , image_data. size );
370381 s.offset = 0 ;
371- s.index = image_index ;
382+ s.index = image_data. index ;
372383 s.alignment = req.memoryRequirements .alignment ;
373- auto r = priv->add_object (device, tid, memoryTypeIndex, s, flags, tiling, dedicated, 0 );
384+ auto r = priv->add_object (device, tid, memoryTypeIndex, s, memory_flags, image_data. tiling , dedicated, 0 );
374385 assert (r.offset == s.offset );
375386 return r;
376387}
377388
378- void suballocator::virtualswap_images (VkDevice device, const std::vector<VkImage>& images, VkMemoryPropertyFlags flags )
389+ void suballocator::virtualswap_images (VkDevice device, const std::vector<VkImage>& images, VkMemoryPropertyFlags memory_flags )
379390{
380391 assert (priv->run );
392+ VkMemoryPropertyFlags flags = prune_memory_flags (memory_flags);
381393 VkMemoryRequirements2 req = {};
382394 const bool dedicated = priv->fill_image_memreq (device, images.at (0 ), req, 0 );
383395 const uint32_t memoryTypeIndex = priv->get_device_memory_type (req.memoryRequirements .memoryTypeBits , flags);
@@ -407,13 +419,10 @@ void suballocator::virtualswap_images(VkDevice device, const std::vector<VkImage
407419 }
408420}
409421
410- suballoc_location suballocator::add_buffer (uint16_t tid, VkDevice device, VkBuffer buffer, VkMemoryPropertyFlags mempropflags, const trackedbuffer& buffer_data)
422+ suballoc_location suballocator::add_buffer (uint16_t tid, VkDevice device, VkBuffer buffer, const trackedbuffer& buffer_data)
411423{
424+ VkMemoryPropertyFlags memory_flags = prune_memory_flags (buffer_data.memory_flags );
412425 const VkBufferUsageFlags buffer_flags = buffer_data.usage ;
413- if ((mempropflags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) || (mempropflags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT))
414- {
415- mempropflags &= ~VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; // do not require this bit in these cases
416- }
417426 VkMemoryRequirements2 req = { VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2, nullptr };
418427 VkMemoryDedicatedRequirements dedicated = { VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS, nullptr };
419428 if (use_dedicated_allocation () && priv->run )
@@ -433,7 +442,7 @@ suballoc_location suballocator::add_buffer(uint16_t tid, VkDevice device, VkBuff
433442 req.memoryRequirements .alignment = 1 ;
434443 req.memoryRequirements .memoryTypeBits = 1 ;
435444 }
436- uint32_t memoryTypeIndex = priv->get_device_memory_type (req.memoryRequirements .memoryTypeBits , mempropflags );
445+ uint32_t memoryTypeIndex = priv->get_device_memory_type (req.memoryRequirements .memoryTypeBits , memory_flags );
437446 suballocation s;
438447 s.type = VK_OBJECT_TYPE_BUFFER;
439448 s.handle .buffer = buffer;
@@ -443,7 +452,7 @@ suballoc_location suballocator::add_buffer(uint16_t tid, VkDevice device, VkBuff
443452 s.alignment = req.memoryRequirements .alignment ;
444453 VkMemoryAllocateFlags allocflags = 0 ;
445454 if (buffer_flags & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT) { dedicated.prefersDedicatedAllocation = VK_TRUE; allocflags |= VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR; }
446- auto r = priv->add_object (device, tid, memoryTypeIndex, s, mempropflags , VK_IMAGE_TILING_LINEAR, dedicated.prefersDedicatedAllocation , allocflags);
455+ auto r = priv->add_object (device, tid, memoryTypeIndex, s, memory_flags , VK_IMAGE_TILING_LINEAR, dedicated.prefersDedicatedAllocation , allocflags);
447456 assert (r.offset == s.offset );
448457 return r;
449458}
0 commit comments