restructure allocation strategy for small allocations
	
		
			
	
		
	
	
		
			
				
	
				continuous-integration/drone/push Build is passing
				
					Details
				
			
		
	
				
					
				
			
				
	
				continuous-integration/drone/push Build is passing
				
					Details
				
			
		
	
							parent
							
								
									0994ac152e
								
							
						
					
					
						commit
						2c77bf96d9
					
				|  | @ -74,11 +74,11 @@ typedef struct VulkanExtensions | ||||||
| 
 | 
 | ||||||
| /* Defines */ | /* Defines */ | ||||||
| 
 | 
 | ||||||
| #define STARTING_ALLOCATION_SIZE 67108864 	    /* 64MiB */ | #define SMALL_ALLOCATION_THRESHOLD 1048576      /* 1   MiB */ | ||||||
| #define MAX_ALLOCATION_SIZE 268435456 		    /* 256MiB */ | #define SMALL_ALLOCATION_SIZE 16777216          /* 16  MiB */ | ||||||
| #define ALLOCATION_INCREMENT 16777216           /* 16MiB */ | #define LARGE_ALLOCATION_INCREMENT 67108864     /* 64  MiB */ | ||||||
| #define UBO_BUFFER_SIZE 16777216 				/* 16MiB */ | #define UBO_BUFFER_SIZE 16777216                /* 16  MiB */ | ||||||
| #define MAX_UBO_SECTION_SIZE 4096 			        /* 4KiB */ | #define MAX_UBO_SECTION_SIZE 4096               /* 4   KiB */ | ||||||
| #define DESCRIPTOR_POOL_STARTING_SIZE 128 | #define DESCRIPTOR_POOL_STARTING_SIZE 128 | ||||||
| #define MAX_FRAMES_IN_FLIGHT 3 | #define MAX_FRAMES_IN_FLIGHT 3 | ||||||
| #define WINDOW_DATA "Refresh_VulkanWindowData" | #define WINDOW_DATA "Refresh_VulkanWindowData" | ||||||
|  | @ -424,7 +424,6 @@ typedef struct VulkanMemoryUsedRegion | ||||||
| typedef struct VulkanMemorySubAllocator | typedef struct VulkanMemorySubAllocator | ||||||
| { | { | ||||||
| 	uint32_t memoryTypeIndex; | 	uint32_t memoryTypeIndex; | ||||||
| 	VkDeviceSize nextAllocationSize; |  | ||||||
| 	VulkanMemoryAllocation **allocations; | 	VulkanMemoryAllocation **allocations; | ||||||
| 	uint32_t allocationCount; | 	uint32_t allocationCount; | ||||||
| 	VulkanMemoryFreeRegion **sortedFreeRegions; | 	VulkanMemoryFreeRegion **sortedFreeRegions; | ||||||
|  | @ -2626,13 +2625,15 @@ static uint8_t VULKAN_INTERNAL_BindResourceMemory( | ||||||
| 	VulkanMemoryAllocation *allocation; | 	VulkanMemoryAllocation *allocation; | ||||||
| 	VulkanMemorySubAllocator *allocator; | 	VulkanMemorySubAllocator *allocator; | ||||||
| 	VulkanMemoryFreeRegion *region; | 	VulkanMemoryFreeRegion *region; | ||||||
|  | 	VulkanMemoryFreeRegion *selectedRegion; | ||||||
| 	VulkanMemoryUsedRegion *usedRegion; | 	VulkanMemoryUsedRegion *usedRegion; | ||||||
| 
 | 
 | ||||||
| 	VkDeviceSize requiredSize, allocationSize; | 	VkDeviceSize requiredSize, allocationSize; | ||||||
| 	VkDeviceSize alignedOffset; | 	VkDeviceSize alignedOffset; | ||||||
| 	uint32_t newRegionSize, newRegionOffset; | 	uint32_t newRegionSize, newRegionOffset; | ||||||
| 	uint8_t shouldAllocDedicated = forceDedicated; | 	uint8_t shouldAllocDedicated = forceDedicated; | ||||||
| 	uint8_t isHostVisible, allocationResult; | 	uint8_t isHostVisible, smallAllocation, allocationResult; | ||||||
|  | 	int32_t i; | ||||||
| 
 | 
 | ||||||
| 	isHostVisible = | 	isHostVisible = | ||||||
| 		(renderer->memoryProperties.memoryTypes[memoryTypeIndex].propertyFlags & | 		(renderer->memoryProperties.memoryTypes[memoryTypeIndex].propertyFlags & | ||||||
|  | @ -2640,6 +2641,7 @@ static uint8_t VULKAN_INTERNAL_BindResourceMemory( | ||||||
| 
 | 
 | ||||||
| 	allocator = &renderer->memoryAllocator->subAllocators[memoryTypeIndex]; | 	allocator = &renderer->memoryAllocator->subAllocators[memoryTypeIndex]; | ||||||
| 	requiredSize = memoryRequirements->memoryRequirements.size; | 	requiredSize = memoryRequirements->memoryRequirements.size; | ||||||
|  | 	smallAllocation = requiredSize < SMALL_ALLOCATION_THRESHOLD; | ||||||
| 
 | 
 | ||||||
| 	if (	(buffer == VK_NULL_HANDLE && image == VK_NULL_HANDLE) || | 	if (	(buffer == VK_NULL_HANDLE && image == VK_NULL_HANDLE) || | ||||||
| 		(buffer != VK_NULL_HANDLE && image != VK_NULL_HANDLE)	) | 		(buffer != VK_NULL_HANDLE && image != VK_NULL_HANDLE)	) | ||||||
|  | @ -2650,90 +2652,113 @@ static uint8_t VULKAN_INTERNAL_BindResourceMemory( | ||||||
| 
 | 
 | ||||||
| 	SDL_LockMutex(renderer->allocatorLock); | 	SDL_LockMutex(renderer->allocatorLock); | ||||||
| 
 | 
 | ||||||
| 	/* find the largest free region and use it */ | 	selectedRegion = NULL; | ||||||
| 	if (!shouldAllocDedicated && allocator->sortedFreeRegionCount > 0) | 
 | ||||||
|  | 	if (!shouldAllocDedicated) | ||||||
| 	{ | 	{ | ||||||
| 		region = allocator->sortedFreeRegions[0]; | 		for (i = allocator->sortedFreeRegionCount - 1; i >= 0; i -= 1) | ||||||
| 		allocation = region->allocation; |  | ||||||
| 
 |  | ||||||
| 		alignedOffset = VULKAN_INTERNAL_NextHighestAlignment( |  | ||||||
| 			region->offset, |  | ||||||
| 			memoryRequirements->memoryRequirements.alignment |  | ||||||
| 		); |  | ||||||
| 
 |  | ||||||
| 		if (alignedOffset + requiredSize <= region->offset + region->size) |  | ||||||
| 		{ | 		{ | ||||||
| 			usedRegion = VULKAN_INTERNAL_NewMemoryUsedRegion( | 			region = allocator->sortedFreeRegions[i]; | ||||||
| 				renderer, | 
 | ||||||
| 				allocation, | 			if (smallAllocation && region->allocation->size != SMALL_ALLOCATION_SIZE) | ||||||
|  | 			{ | ||||||
|  | 				/* region is not in a small allocation */ | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			if (!smallAllocation && region->allocation->size == SMALL_ALLOCATION_SIZE) | ||||||
|  | 			{ | ||||||
|  | 				/* allocation is not small and current region is in a small allocation */ | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			alignedOffset = VULKAN_INTERNAL_NextHighestAlignment( | ||||||
| 				region->offset, | 				region->offset, | ||||||
| 				requiredSize + (alignedOffset - region->offset), |  | ||||||
| 				alignedOffset, |  | ||||||
| 				resourceSize, |  | ||||||
| 				memoryRequirements->memoryRequirements.alignment | 				memoryRequirements->memoryRequirements.alignment | ||||||
| 			); | 			); | ||||||
| 
 | 
 | ||||||
| 			usedRegion->isBuffer = buffer != VK_NULL_HANDLE; | 			if (alignedOffset + requiredSize <= region->offset + region->size) | ||||||
| 
 |  | ||||||
| 			newRegionSize = region->size - ((alignedOffset - region->offset) + requiredSize); |  | ||||||
| 			newRegionOffset = alignedOffset + requiredSize; |  | ||||||
| 
 |  | ||||||
| 			/* remove and add modified region to re-sort */ |  | ||||||
| 			VULKAN_INTERNAL_RemoveMemoryFreeRegion(renderer, region); |  | ||||||
| 
 |  | ||||||
| 			/* if size is 0, no need to re-insert */ |  | ||||||
| 			if (newRegionSize != 0) |  | ||||||
| 			{ | 			{ | ||||||
| 				VULKAN_INTERNAL_NewMemoryFreeRegion( | 				selectedRegion = region; | ||||||
| 					renderer, | 				break; | ||||||
| 					allocation, |  | ||||||
| 					newRegionOffset, |  | ||||||
| 					newRegionSize |  | ||||||
| 				); |  | ||||||
| 			} | 			} | ||||||
| 
 |  | ||||||
| 			SDL_UnlockMutex(renderer->allocatorLock); |  | ||||||
| 
 |  | ||||||
| 			if (buffer != VK_NULL_HANDLE) |  | ||||||
| 			{ |  | ||||||
| 				if (!VULKAN_INTERNAL_BindBufferMemory( |  | ||||||
| 					renderer, |  | ||||||
| 					usedRegion, |  | ||||||
| 					alignedOffset, |  | ||||||
| 					buffer |  | ||||||
| 				)) { |  | ||||||
| 					VULKAN_INTERNAL_RemoveMemoryUsedRegion( |  | ||||||
| 						renderer, |  | ||||||
| 						usedRegion |  | ||||||
| 					); |  | ||||||
| 
 |  | ||||||
| 					return 0; |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 			else if (image != VK_NULL_HANDLE) |  | ||||||
| 			{ |  | ||||||
| 				if (!VULKAN_INTERNAL_BindImageMemory( |  | ||||||
| 					renderer, |  | ||||||
| 					usedRegion, |  | ||||||
| 					alignedOffset, |  | ||||||
| 					image |  | ||||||
| 				)) { |  | ||||||
| 					VULKAN_INTERNAL_RemoveMemoryUsedRegion( |  | ||||||
| 						renderer, |  | ||||||
| 						usedRegion |  | ||||||
| 					); |  | ||||||
| 
 |  | ||||||
| 					return 0; |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			*pMemoryUsedRegion = usedRegion; |  | ||||||
| 			return 1; |  | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* No suitable free regions exist, allocate a new memory region */ | 	if (selectedRegion != NULL) | ||||||
|  | 	{ | ||||||
|  | 		region = selectedRegion; | ||||||
|  | 		allocation = region->allocation; | ||||||
| 
 | 
 | ||||||
|  | 		usedRegion = VULKAN_INTERNAL_NewMemoryUsedRegion( | ||||||
|  | 			renderer, | ||||||
|  | 			allocation, | ||||||
|  | 			region->offset, | ||||||
|  | 			requiredSize + (alignedOffset - region->offset), | ||||||
|  | 			alignedOffset, | ||||||
|  | 			resourceSize, | ||||||
|  | 			memoryRequirements->memoryRequirements.alignment | ||||||
|  | 		); | ||||||
|  | 
 | ||||||
|  | 		usedRegion->isBuffer = buffer != VK_NULL_HANDLE; | ||||||
|  | 
 | ||||||
|  | 		newRegionSize = region->size - ((alignedOffset - region->offset) + requiredSize); | ||||||
|  | 		newRegionOffset = alignedOffset + requiredSize; | ||||||
|  | 
 | ||||||
|  | 		/* remove and add modified region to re-sort */ | ||||||
|  | 		VULKAN_INTERNAL_RemoveMemoryFreeRegion(renderer, region); | ||||||
|  | 
 | ||||||
|  | 		/* if size is 0, no need to re-insert */ | ||||||
|  | 		if (newRegionSize != 0) | ||||||
|  | 		{ | ||||||
|  | 			VULKAN_INTERNAL_NewMemoryFreeRegion( | ||||||
|  | 				renderer, | ||||||
|  | 				allocation, | ||||||
|  | 				newRegionOffset, | ||||||
|  | 				newRegionSize | ||||||
|  | 			); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		SDL_UnlockMutex(renderer->allocatorLock); | ||||||
|  | 
 | ||||||
|  | 		if (buffer != VK_NULL_HANDLE) | ||||||
|  | 		{ | ||||||
|  | 			if (!VULKAN_INTERNAL_BindBufferMemory( | ||||||
|  | 				renderer, | ||||||
|  | 				usedRegion, | ||||||
|  | 				alignedOffset, | ||||||
|  | 				buffer | ||||||
|  | 			)) { | ||||||
|  | 				VULKAN_INTERNAL_RemoveMemoryUsedRegion( | ||||||
|  | 					renderer, | ||||||
|  | 					usedRegion | ||||||
|  | 				); | ||||||
|  | 
 | ||||||
|  | 				return 0; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		else if (image != VK_NULL_HANDLE) | ||||||
|  | 		{ | ||||||
|  | 			if (!VULKAN_INTERNAL_BindImageMemory( | ||||||
|  | 				renderer, | ||||||
|  | 				usedRegion, | ||||||
|  | 				alignedOffset, | ||||||
|  | 				image | ||||||
|  | 			)) { | ||||||
|  | 				VULKAN_INTERNAL_RemoveMemoryUsedRegion( | ||||||
|  | 					renderer, | ||||||
|  | 					usedRegion | ||||||
|  | 				); | ||||||
|  | 
 | ||||||
|  | 				return 0; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		*pMemoryUsedRegion = usedRegion; | ||||||
|  | 		return 1; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* No suitable free regions exist, allocate a new memory region */ | ||||||
| 	if ( | 	if ( | ||||||
| 		!shouldAllocDedicated && | 		!shouldAllocDedicated && | ||||||
| 		renderer->allocationsToDefragCount == 0 && | 		renderer->allocationsToDefragCount == 0 && | ||||||
|  | @ -2747,15 +2772,15 @@ static uint8_t VULKAN_INTERNAL_BindResourceMemory( | ||||||
| 	{ | 	{ | ||||||
| 		allocationSize = requiredSize; | 		allocationSize = requiredSize; | ||||||
| 	} | 	} | ||||||
| 	else if (requiredSize > allocator->nextAllocationSize) | 	else if (requiredSize > SMALL_ALLOCATION_THRESHOLD) | ||||||
| 	{ | 	{ | ||||||
| 		/* allocate a page of required size aligned to ALLOCATION_INCREMENT increments */ | 		/* allocate a page of required size aligned to LARGE_ALLOCATION_INCREMENT increments */ | ||||||
| 		allocationSize = | 		allocationSize = | ||||||
| 			VULKAN_INTERNAL_NextHighestAlignment(requiredSize, ALLOCATION_INCREMENT); | 			VULKAN_INTERNAL_NextHighestAlignment(requiredSize, LARGE_ALLOCATION_INCREMENT); | ||||||
| 	} | 	} | ||||||
| 	else | 	else | ||||||
| 	{ | 	{ | ||||||
| 		allocationSize = allocator->nextAllocationSize; | 		allocationSize = SMALL_ALLOCATION_SIZE; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	allocationResult = VULKAN_INTERNAL_AllocateMemory( | 	allocationResult = VULKAN_INTERNAL_AllocateMemory( | ||||||
|  | @ -11543,7 +11568,6 @@ static Refresh_Device* VULKAN_CreateDevice( | ||||||
| 	for (i = 0; i < VK_MAX_MEMORY_TYPES; i += 1) | 	for (i = 0; i < VK_MAX_MEMORY_TYPES; i += 1) | ||||||
| 	{ | 	{ | ||||||
| 		renderer->memoryAllocator->subAllocators[i].memoryTypeIndex = i; | 		renderer->memoryAllocator->subAllocators[i].memoryTypeIndex = i; | ||||||
| 		renderer->memoryAllocator->subAllocators[i].nextAllocationSize = STARTING_ALLOCATION_SIZE; |  | ||||||
| 		renderer->memoryAllocator->subAllocators[i].allocations = NULL; | 		renderer->memoryAllocator->subAllocators[i].allocations = NULL; | ||||||
| 		renderer->memoryAllocator->subAllocators[i].allocationCount = 0; | 		renderer->memoryAllocator->subAllocators[i].allocationCount = 0; | ||||||
| 		renderer->memoryAllocator->subAllocators[i].sortedFreeRegions = SDL_malloc( | 		renderer->memoryAllocator->subAllocators[i].sortedFreeRegions = SDL_malloc( | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue