alter vulkan defrag strategy
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
parent
2361cec274
commit
695abd4139
|
@ -77,12 +77,9 @@ typedef struct VulkanExtensions
|
||||||
#define STARTING_ALLOCATION_SIZE 64000000 /* 64MB */
|
#define STARTING_ALLOCATION_SIZE 64000000 /* 64MB */
|
||||||
#define MAX_ALLOCATION_SIZE 256000000 /* 256MB */
|
#define MAX_ALLOCATION_SIZE 256000000 /* 256MB */
|
||||||
#define ALLOCATION_INCREMENT 16000000 /* 16MB */
|
#define ALLOCATION_INCREMENT 16000000 /* 16MB */
|
||||||
#define TRANSFER_BUFFER_STARTING_SIZE 8000000 /* 8MB */
|
|
||||||
#define POOLED_TRANSFER_BUFFER_SIZE 16000000 /* 16MB */
|
|
||||||
#define UBO_BUFFER_SIZE 16777216 /* 16MB */
|
#define UBO_BUFFER_SIZE 16777216 /* 16MB */
|
||||||
#define MAX_UBO_SECTION_SIZE 4096 /* 4KB */
|
#define MAX_UBO_SECTION_SIZE 4096 /* 4KB */
|
||||||
#define DESCRIPTOR_POOL_STARTING_SIZE 128
|
#define DESCRIPTOR_POOL_STARTING_SIZE 128
|
||||||
#define DEFRAG_TIME 200
|
|
||||||
#define WINDOW_DATA "Refresh_VulkanWindowData"
|
#define WINDOW_DATA "Refresh_VulkanWindowData"
|
||||||
|
|
||||||
#define IDENTITY_SWIZZLE \
|
#define IDENTITY_SWIZZLE \
|
||||||
|
@ -1620,10 +1617,10 @@ typedef struct VulkanCommandBuffer
|
||||||
uint32_t usedFramebufferCount;
|
uint32_t usedFramebufferCount;
|
||||||
uint32_t usedFramebufferCapacity;
|
uint32_t usedFramebufferCapacity;
|
||||||
|
|
||||||
/* Shader modules have references tracked by pipelines */
|
|
||||||
|
|
||||||
VkFence inFlightFence;
|
VkFence inFlightFence;
|
||||||
uint8_t autoReleaseFence;
|
uint8_t autoReleaseFence;
|
||||||
|
|
||||||
|
uint8_t isDefrag; /* Whether this CB was created for defragging */
|
||||||
} VulkanCommandBuffer;
|
} VulkanCommandBuffer;
|
||||||
|
|
||||||
struct VulkanCommandPool
|
struct VulkanCommandPool
|
||||||
|
@ -1809,10 +1806,12 @@ typedef struct VulkanRenderer
|
||||||
SDL_mutex *framebufferFetchLock;
|
SDL_mutex *framebufferFetchLock;
|
||||||
SDL_mutex *renderTargetFetchLock;
|
SDL_mutex *renderTargetFetchLock;
|
||||||
|
|
||||||
uint8_t needDefrag;
|
|
||||||
uint64_t defragTimestamp;
|
|
||||||
uint8_t defragInProgress;
|
uint8_t defragInProgress;
|
||||||
|
|
||||||
|
VulkanMemoryAllocation **allocationsToDefrag;
|
||||||
|
uint32_t allocationsToDefragCount;
|
||||||
|
uint32_t allocationsToDefragCapacity;
|
||||||
|
|
||||||
#define VULKAN_INSTANCE_FUNCTION(ext, ret, func, params) \
|
#define VULKAN_INSTANCE_FUNCTION(ext, ret, func, params) \
|
||||||
vkfntype_##func func;
|
vkfntype_##func func;
|
||||||
#define VULKAN_DEVICE_FUNCTION(ext, ret, func, params) \
|
#define VULKAN_DEVICE_FUNCTION(ext, ret, func, params) \
|
||||||
|
@ -2127,6 +2126,45 @@ static void VULKAN_INTERNAL_MakeMemoryUnavailable(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void VULKAN_INTERNAL_MarkAllocationsForDefrag(
|
||||||
|
VulkanRenderer *renderer
|
||||||
|
) {
|
||||||
|
uint32_t memoryType, allocationIndex;
|
||||||
|
VulkanMemorySubAllocator *currentAllocator;
|
||||||
|
|
||||||
|
for (memoryType = 0; memoryType < VK_MAX_MEMORY_TYPES; memoryType += 1)
|
||||||
|
{
|
||||||
|
currentAllocator = &renderer->memoryAllocator->subAllocators[memoryType];
|
||||||
|
|
||||||
|
for (allocationIndex = 0; allocationIndex < currentAllocator->allocationCount; allocationIndex += 1)
|
||||||
|
{
|
||||||
|
if (currentAllocator->allocations[allocationIndex]->availableForAllocation == 1)
|
||||||
|
{
|
||||||
|
if (currentAllocator->allocations[allocationIndex]->freeRegionCount > 1)
|
||||||
|
{
|
||||||
|
EXPAND_ARRAY_IF_NEEDED(
|
||||||
|
renderer->allocationsToDefrag,
|
||||||
|
VulkanMemoryAllocation*,
|
||||||
|
renderer->allocationsToDefragCount + 1,
|
||||||
|
renderer->allocationsToDefragCapacity,
|
||||||
|
renderer->allocationsToDefragCapacity * 2
|
||||||
|
);
|
||||||
|
|
||||||
|
renderer->allocationsToDefrag[renderer->allocationsToDefragCount] =
|
||||||
|
currentAllocator->allocations[allocationIndex];
|
||||||
|
|
||||||
|
renderer->allocationsToDefragCount += 1;
|
||||||
|
|
||||||
|
VULKAN_INTERNAL_MakeMemoryUnavailable(
|
||||||
|
renderer,
|
||||||
|
currentAllocator->allocations[allocationIndex]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void VULKAN_INTERNAL_RemoveMemoryFreeRegion(
|
static void VULKAN_INTERNAL_RemoveMemoryFreeRegion(
|
||||||
VulkanRenderer *renderer,
|
VulkanRenderer *renderer,
|
||||||
VulkanMemoryFreeRegion *freeRegion
|
VulkanMemoryFreeRegion *freeRegion
|
||||||
|
@ -2348,12 +2386,6 @@ static void VULKAN_INTERNAL_RemoveMemoryUsedRegion(
|
||||||
usedRegion->size
|
usedRegion->size
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!usedRegion->allocation->dedicated)
|
|
||||||
{
|
|
||||||
renderer->needDefrag = 1;
|
|
||||||
renderer->defragTimestamp = SDL_GetTicks64() + DEFRAG_TIME; /* reset timer so we batch defrags */
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_free(usedRegion);
|
SDL_free(usedRegion);
|
||||||
|
|
||||||
SDL_UnlockMutex(renderer->allocatorLock);
|
SDL_UnlockMutex(renderer->allocatorLock);
|
||||||
|
@ -2762,6 +2794,15 @@ static uint8_t VULKAN_INTERNAL_BindResourceMemory(
|
||||||
|
|
||||||
/* No suitable free regions exist, allocate a new memory region */
|
/* No suitable free regions exist, allocate a new memory region */
|
||||||
|
|
||||||
|
if (
|
||||||
|
!shouldAllocDedicated &&
|
||||||
|
renderer->allocationsToDefragCount == 0 &&
|
||||||
|
!renderer->defragInProgress
|
||||||
|
) {
|
||||||
|
/* Mark currently fragmented allocations for defrag */
|
||||||
|
VULKAN_INTERNAL_MarkAllocationsForDefrag(renderer);
|
||||||
|
}
|
||||||
|
|
||||||
if (shouldAllocDedicated)
|
if (shouldAllocDedicated)
|
||||||
{
|
{
|
||||||
allocationSize = requiredSize;
|
allocationSize = requiredSize;
|
||||||
|
@ -3081,30 +3122,6 @@ static uint8_t VULKAN_INTERNAL_BindMemoryForBuffer(
|
||||||
return bindResult;
|
return bindResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t VULKAN_INTERNAL_FindAllocationToDefragment(
|
|
||||||
VulkanRenderer *renderer,
|
|
||||||
VulkanMemorySubAllocator *allocator,
|
|
||||||
uint32_t *allocationIndexToDefrag
|
|
||||||
) {
|
|
||||||
uint32_t i, j;
|
|
||||||
|
|
||||||
for (i = 0; i < VK_MAX_MEMORY_TYPES; i += 1)
|
|
||||||
{
|
|
||||||
*allocator = renderer->memoryAllocator->subAllocators[i];
|
|
||||||
|
|
||||||
for (j = 0; j < allocator->allocationCount; j += 1)
|
|
||||||
{
|
|
||||||
if (allocator->allocations[j]->availableForAllocation == 1 && allocator->allocations[j]->freeRegionCount > 1)
|
|
||||||
{
|
|
||||||
*allocationIndexToDefrag = j;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Memory Barriers */
|
/* Memory Barriers */
|
||||||
|
|
||||||
static void VULKAN_INTERNAL_BufferMemoryBarrier(
|
static void VULKAN_INTERNAL_BufferMemoryBarrier(
|
||||||
|
@ -9406,6 +9423,8 @@ static Refresh_CommandBuffer* VULKAN_AcquireCommandBuffer(
|
||||||
commandBuffer->renderPassColorTargetCount = 0;
|
commandBuffer->renderPassColorTargetCount = 0;
|
||||||
commandBuffer->autoReleaseFence = 1;
|
commandBuffer->autoReleaseFence = 1;
|
||||||
|
|
||||||
|
commandBuffer->isDefrag = 0;
|
||||||
|
|
||||||
/* Reset the command buffer here to avoid resets being called
|
/* Reset the command buffer here to avoid resets being called
|
||||||
* from a separate thread than where the command buffer was acquired
|
* from a separate thread than where the command buffer was acquired
|
||||||
*/
|
*/
|
||||||
|
@ -9976,6 +9995,13 @@ static void VULKAN_INTERNAL_CleanCommandBuffer(
|
||||||
commandBuffer->waitSemaphoreCount = 0;
|
commandBuffer->waitSemaphoreCount = 0;
|
||||||
commandBuffer->signalSemaphoreCount = 0;
|
commandBuffer->signalSemaphoreCount = 0;
|
||||||
|
|
||||||
|
/* Reset defrag state */
|
||||||
|
|
||||||
|
if (commandBuffer->isDefrag)
|
||||||
|
{
|
||||||
|
renderer->defragInProgress = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Return command buffer to pool */
|
/* Return command buffer to pool */
|
||||||
|
|
||||||
SDL_LockMutex(renderer->acquireCommandBufferLock);
|
SDL_LockMutex(renderer->acquireCommandBufferLock);
|
||||||
|
@ -10211,17 +10237,13 @@ static void VULKAN_Submit(
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check pending destroys */
|
/* Check pending destroys */
|
||||||
|
|
||||||
VULKAN_INTERNAL_PerformPendingDestroys(renderer);
|
VULKAN_INTERNAL_PerformPendingDestroys(renderer);
|
||||||
|
|
||||||
/* Defrag! */
|
/* Defrag! */
|
||||||
if (renderer->needDefrag && !renderer->defragInProgress)
|
if (renderer->allocationsToDefragCount > 0 && !renderer->defragInProgress)
|
||||||
{
|
|
||||||
if (SDL_GetTicks64() >= renderer->defragTimestamp)
|
|
||||||
{
|
{
|
||||||
VULKAN_INTERNAL_DefragmentMemory(renderer);
|
VULKAN_INTERNAL_DefragmentMemory(renderer);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
SDL_UnlockMutex(renderer->submitLock);
|
SDL_UnlockMutex(renderer->submitLock);
|
||||||
}
|
}
|
||||||
|
@ -10229,9 +10251,7 @@ static void VULKAN_Submit(
|
||||||
static uint8_t VULKAN_INTERNAL_DefragmentMemory(
|
static uint8_t VULKAN_INTERNAL_DefragmentMemory(
|
||||||
VulkanRenderer *renderer
|
VulkanRenderer *renderer
|
||||||
) {
|
) {
|
||||||
VulkanMemorySubAllocator allocator;
|
|
||||||
VulkanMemoryAllocation *allocation;
|
VulkanMemoryAllocation *allocation;
|
||||||
uint32_t allocationIndexToDefrag;
|
|
||||||
VulkanMemoryUsedRegion *currentRegion;
|
VulkanMemoryUsedRegion *currentRegion;
|
||||||
VulkanBuffer* newBuffer;
|
VulkanBuffer* newBuffer;
|
||||||
VulkanTexture* newTexture;
|
VulkanTexture* newTexture;
|
||||||
|
@ -10244,22 +10264,13 @@ static uint8_t VULKAN_INTERNAL_DefragmentMemory(
|
||||||
|
|
||||||
SDL_LockMutex(renderer->allocatorLock);
|
SDL_LockMutex(renderer->allocatorLock);
|
||||||
|
|
||||||
renderer->needDefrag = 0;
|
|
||||||
renderer->defragInProgress = 1;
|
renderer->defragInProgress = 1;
|
||||||
|
|
||||||
commandBuffer = (VulkanCommandBuffer*) VULKAN_AcquireCommandBuffer((Refresh_Renderer *) renderer);
|
commandBuffer = (VulkanCommandBuffer*) VULKAN_AcquireCommandBuffer((Refresh_Renderer *) renderer);
|
||||||
|
commandBuffer->isDefrag = 1;
|
||||||
|
|
||||||
if (VULKAN_INTERNAL_FindAllocationToDefragment(
|
allocation = renderer->allocationsToDefrag[renderer->allocationsToDefragCount - 1];
|
||||||
renderer,
|
renderer->allocationsToDefragCount -= 1;
|
||||||
&allocator,
|
|
||||||
&allocationIndexToDefrag
|
|
||||||
)) {
|
|
||||||
allocation = allocator.allocations[allocationIndexToDefrag];
|
|
||||||
|
|
||||||
VULKAN_INTERNAL_MakeMemoryUnavailable(
|
|
||||||
renderer,
|
|
||||||
allocation
|
|
||||||
);
|
|
||||||
|
|
||||||
/* For each used region in the allocation
|
/* For each used region in the allocation
|
||||||
* create a new resource, copy the data
|
* create a new resource, copy the data
|
||||||
|
@ -10292,11 +10303,13 @@ static uint8_t VULKAN_INTERNAL_DefragmentMemory(
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy buffer contents if necessary */
|
|
||||||
if (currentRegion->vulkanBuffer->preserveContentsOnDefrag)
|
|
||||||
{
|
|
||||||
originalResourceAccessType = currentRegion->vulkanBuffer->resourceAccessType;
|
originalResourceAccessType = currentRegion->vulkanBuffer->resourceAccessType;
|
||||||
|
|
||||||
|
/* Copy buffer contents if necessary */
|
||||||
|
if (
|
||||||
|
originalResourceAccessType != RESOURCE_ACCESS_NONE &&
|
||||||
|
currentRegion->vulkanBuffer->preserveContentsOnDefrag
|
||||||
|
) {
|
||||||
VULKAN_INTERNAL_BufferMemoryBarrier(
|
VULKAN_INTERNAL_BufferMemoryBarrier(
|
||||||
renderer,
|
renderer,
|
||||||
commandBuffer->commandBuffer,
|
commandBuffer->commandBuffer,
|
||||||
|
@ -10343,11 +10356,11 @@ static uint8_t VULKAN_INTERNAL_DefragmentMemory(
|
||||||
}
|
}
|
||||||
|
|
||||||
VULKAN_INTERNAL_QueueDestroyBuffer(renderer, currentRegion->vulkanBuffer);
|
VULKAN_INTERNAL_QueueDestroyBuffer(renderer, currentRegion->vulkanBuffer);
|
||||||
|
|
||||||
renderer->needDefrag = 1;
|
|
||||||
}
|
}
|
||||||
else if (!currentRegion->vulkanTexture->markedForDestroy)
|
else if (!currentRegion->vulkanTexture->markedForDestroy)
|
||||||
{
|
{
|
||||||
|
originalResourceAccessType = currentRegion->vulkanTexture->resourceAccessType;
|
||||||
|
|
||||||
newTexture = VULKAN_INTERNAL_CreateTexture(
|
newTexture = VULKAN_INTERNAL_CreateTexture(
|
||||||
renderer,
|
renderer,
|
||||||
currentRegion->vulkanTexture->dimensions.width,
|
currentRegion->vulkanTexture->dimensions.width,
|
||||||
|
@ -10367,8 +10380,8 @@ static uint8_t VULKAN_INTERNAL_DefragmentMemory(
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
originalResourceAccessType = currentRegion->vulkanTexture->resourceAccessType;
|
if (originalResourceAccessType != RESOURCE_ACCESS_NONE)
|
||||||
|
{
|
||||||
VULKAN_INTERNAL_ImageMemoryBarrier(
|
VULKAN_INTERNAL_ImageMemoryBarrier(
|
||||||
renderer,
|
renderer,
|
||||||
commandBuffer->commandBuffer,
|
commandBuffer->commandBuffer,
|
||||||
|
@ -10448,6 +10461,7 @@ static uint8_t VULKAN_INTERNAL_DefragmentMemory(
|
||||||
|
|
||||||
VULKAN_INTERNAL_TrackTexture(renderer, commandBuffer, currentRegion->vulkanTexture);
|
VULKAN_INTERNAL_TrackTexture(renderer, commandBuffer, currentRegion->vulkanTexture);
|
||||||
VULKAN_INTERNAL_TrackTexture(renderer, commandBuffer, newTexture);
|
VULKAN_INTERNAL_TrackTexture(renderer, commandBuffer, newTexture);
|
||||||
|
}
|
||||||
|
|
||||||
/* re-point original container to new texture */
|
/* re-point original container to new texture */
|
||||||
newTexture->container = currentRegion->vulkanTexture->container;
|
newTexture->container = currentRegion->vulkanTexture->container;
|
||||||
|
@ -10455,23 +10469,16 @@ static uint8_t VULKAN_INTERNAL_DefragmentMemory(
|
||||||
currentRegion->vulkanTexture->container = NULL;
|
currentRegion->vulkanTexture->container = NULL;
|
||||||
|
|
||||||
VULKAN_INTERNAL_QueueDestroyTexture(renderer, currentRegion->vulkanTexture);
|
VULKAN_INTERNAL_QueueDestroyTexture(renderer, currentRegion->vulkanTexture);
|
||||||
|
|
||||||
renderer->needDefrag = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_UnlockMutex(renderer->allocatorLock);
|
SDL_UnlockMutex(renderer->allocatorLock);
|
||||||
|
|
||||||
renderer->defragTimestamp = SDL_GetTicks64() + DEFRAG_TIME;
|
|
||||||
|
|
||||||
VULKAN_Submit(
|
VULKAN_Submit(
|
||||||
(Refresh_Renderer*) renderer,
|
(Refresh_Renderer*) renderer,
|
||||||
(Refresh_CommandBuffer*) commandBuffer
|
(Refresh_CommandBuffer*) commandBuffer
|
||||||
);
|
);
|
||||||
|
|
||||||
renderer->defragInProgress = 0;
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11849,10 +11856,16 @@ static Refresh_Device* VULKAN_CreateDevice(
|
||||||
renderer->framebuffersToDestroyCapacity
|
renderer->framebuffersToDestroyCapacity
|
||||||
);
|
);
|
||||||
|
|
||||||
renderer->needDefrag = 0;
|
/* Defrag state */
|
||||||
renderer->defragTimestamp = 0;
|
|
||||||
renderer->defragInProgress = 0;
|
renderer->defragInProgress = 0;
|
||||||
|
|
||||||
|
renderer->allocationsToDefragCount = 0;
|
||||||
|
renderer->allocationsToDefragCapacity = 4;
|
||||||
|
renderer->allocationsToDefrag = SDL_malloc(
|
||||||
|
renderer->allocationsToDefragCapacity * sizeof(VulkanMemoryAllocation*)
|
||||||
|
);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue