proper texture staging + fix buffer dispose api

submit_rewrite
cosmonaut 2021-01-02 20:56:40 -08:00 committed by thatcosmonaut
parent 10d326b201
commit 540c0985b7
4 changed files with 182 additions and 118 deletions

View File

@ -1184,26 +1184,14 @@ REFRESHAPI void REFRESH_AddDisposeSampler(
REFRESH_Sampler *sampler
);
/* Sends a vertex buffer to be destroyed by the renderer. Note that we call it
/* Sends a buffer to be destroyed by the renderer. Note that we call it
* "AddDispose" because it may not be immediately destroyed by the renderer if
* this is not called from the main thread (for example, if a garbage collector
* deletes the resource instead of the programmer).
*
* buffer: The REFRESH_Buffer to be destroyed.
*/
REFRESHAPI void REFRESH_AddDisposeVertexBuffer(
REFRESH_Device *device,
REFRESH_Buffer *buffer
);
/* Sends an index buffer to be destroyed by the renderer. Note that we call it
* "AddDispose" because it may not be immediately destroyed by the renderer if
* this is not called from the main thread (for example, if a garbage collector
* deletes the resource instead of the programmer).
*
* buffer: The REFRESH_Buffer to be destroyed.
*/
REFRESHAPI void REFRESH_AddDisposeIndexBuffer(
REFRESHAPI void REFRESH_AddDisposeBuffer(
REFRESH_Device *device,
REFRESH_Buffer *buffer
);

View File

@ -721,23 +721,12 @@ void REFRESH_AddDisposeSampler(
);
}
void REFRESH_AddDisposeVertexBuffer(
void REFRESH_AddDisposeBuffer(
REFRESH_Device *device,
REFRESH_Buffer *buffer
) {
NULL_RETURN(device);
device->AddDisposeVertexBuffer(
device->driverData,
buffer
);
}
void REFRESH_AddDisposeIndexBuffer(
REFRESH_Device *device,
REFRESH_Buffer *buffer
) {
NULL_RETURN(device);
device->AddDisposeIndexBuffer(
device->AddDisposeBuffer(
device->driverData,
buffer
);

View File

@ -446,12 +446,7 @@ struct REFRESH_Device
REFRESH_Sampler *sampler
);
void(*AddDisposeVertexBuffer)(
REFRESH_Renderer *driverData,
REFRESH_Buffer *buffer
);
void(*AddDisposeIndexBuffer)(
void(*AddDisposeBuffer)(
REFRESH_Renderer *driverData,
REFRESH_Buffer *buffer
);
@ -609,8 +604,7 @@ struct REFRESH_Device
ASSIGN_DRIVER_FUNC(CopyTextureDataCube, name) \
ASSIGN_DRIVER_FUNC(AddDisposeTexture, name) \
ASSIGN_DRIVER_FUNC(AddDisposeSampler, name) \
ASSIGN_DRIVER_FUNC(AddDisposeVertexBuffer, name) \
ASSIGN_DRIVER_FUNC(AddDisposeIndexBuffer, name) \
ASSIGN_DRIVER_FUNC(AddDisposeBuffer, name) \
ASSIGN_DRIVER_FUNC(AddDisposeColorTarget, name) \
ASSIGN_DRIVER_FUNC(AddDisposeDepthStencilTarget, name) \
ASSIGN_DRIVER_FUNC(AddDisposeFramebuffer, name) \

View File

@ -72,6 +72,7 @@ static uint32_t deviceExtensionCount = SDL_arraysize(deviceExtensionNames);
#define STARTING_ALLOCATION_SIZE 64000000 /* 64MB */
#define MAX_ALLOCATION_SIZE 256000000 /* 256MB */
#define TEXTURE_STAGING_SIZE 8000000 /* 8MB */
#define MAX_TEXTURE_STAGING_SIZE 128000000 /* 128MB */
#define UBO_BUFFER_SIZE 8000000 /* 8MB */
#define UBO_ACTUAL_SIZE (UBO_BUFFER_SIZE * 2)
#define DESCRIPTOR_POOL_STARTING_SIZE 128
@ -1324,6 +1325,7 @@ typedef struct VulkanRenderer
VulkanBuffer *dummyComputeUniformBuffer;
VulkanBuffer *textureStagingBuffer;
uint32_t textureStagingBufferOffset;
VulkanBuffer** buffersInUse;
uint32_t buffersInUseCount;
@ -1448,6 +1450,7 @@ typedef struct VulkanRenderer
static void VULKAN_INTERNAL_BeginCommandBuffer(VulkanRenderer *renderer, VulkanCommandBuffer *commandBuffer);
static void VULKAN_Submit(REFRESH_Renderer *driverData, REFRESH_CommandBuffer **pCommandBuffers, uint32_t commandBufferCount);
static void VULKAN_INTERNAL_FlushTransfers(VulkanRenderer *renderer);
/* Error Handling */
@ -2141,31 +2144,6 @@ static void VULKAN_INTERNAL_ImageMemoryBarrier(
/* Resource Disposal */
static void VULKAN_INTERNAL_RemoveBuffer(
REFRESH_Renderer *driverData,
REFRESH_Buffer *buffer
) {
VulkanRenderer *renderer = (VulkanRenderer*) driverData;
VulkanBuffer *vulkanBuffer = (VulkanBuffer*) buffer;
SDL_LockMutex(renderer->disposeLock);
EXPAND_ARRAY_IF_NEEDED(
renderer->buffersToDestroy,
VulkanBuffer*,
renderer->buffersToDestroyCount + 1,
renderer->buffersToDestroyCapacity,
renderer->buffersToDestroyCapacity * 2
)
renderer->buffersToDestroy[
renderer->buffersToDestroyCount
] = vulkanBuffer;
renderer->buffersToDestroyCount += 1;
SDL_UnlockMutex(renderer->disposeLock);
}
static void VULKAN_INTERNAL_DestroyTexture(
VulkanRenderer* renderer,
VulkanTexture* texture
@ -2299,10 +2277,10 @@ static void VULKAN_INTERNAL_DestroyCommandPool(
VulkanRenderer *renderer,
VulkanCommandPool *commandPool
) {
renderer->vkResetCommandPool(
renderer->vkDestroyCommandPool(
renderer->logicalDevice,
commandPool->commandPool,
VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT
NULL
);
SDL_free(commandPool->inactiveCommandBuffers);
@ -3488,6 +3466,12 @@ static void VULKAN_DestroyDevice(
}
}
renderer->vkDestroyCommandPool(
renderer->logicalDevice,
renderer->transferCommandPool,
NULL
);
for (i = 0; i < NUM_PIPELINE_LAYOUT_BUCKETS; i += 1)
{
graphicsPipelineLayoutHashArray = renderer->graphicsPipelineLayoutHashTable.buckets[i];
@ -5847,27 +5831,36 @@ static REFRESH_Buffer* VULKAN_CreateBuffer(
static void VULKAN_INTERNAL_MaybeExpandStagingBuffer(
VulkanRenderer *renderer,
VkDeviceSize size
uint32_t textureSize
) {
if (size <= renderer->textureStagingBuffer->size)
VkDeviceSize currentStagingSize = renderer->textureStagingBuffer->size;
if (renderer->textureStagingBufferOffset + textureSize <= renderer->textureStagingBuffer->size)
{
return;
}
VULKAN_INTERNAL_DestroyTextureStagingBuffer(renderer);
/* not enough room in the staging buffer, time to flush */
VULKAN_INTERNAL_FlushTransfers(renderer);
renderer->textureStagingBuffer = (VulkanBuffer*) SDL_malloc(sizeof(VulkanBuffer));
/* double staging buffer size up to max */
if (currentStagingSize * 2 <= MAX_TEXTURE_STAGING_SIZE)
{
VULKAN_INTERNAL_DestroyTextureStagingBuffer(renderer);
if (!VULKAN_INTERNAL_CreateBuffer(
renderer,
size,
RESOURCE_ACCESS_MEMORY_TRANSFER_READ_WRITE,
VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
1,
renderer->textureStagingBuffer
)) {
REFRESH_LogError("Failed to expand texture staging buffer!");
return;
renderer->textureStagingBuffer = (VulkanBuffer*) SDL_malloc(sizeof(VulkanBuffer));
if (!VULKAN_INTERNAL_CreateBuffer(
renderer,
currentStagingSize * 2,
RESOURCE_ACCESS_MEMORY_TRANSFER_READ_WRITE,
VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
1,
renderer->textureStagingBuffer
)) {
REFRESH_LogError("Failed to expand texture staging buffer!");
return;
}
}
}
@ -5903,6 +5896,88 @@ static void VULKAN_INTERNAL_EndTransferCommandBuffer(
}
}
/* Hard sync point! */
static void VULKAN_INTERNAL_FlushTransfers(
VulkanRenderer *renderer
) {
VkSubmitInfo transferSubmitInfo;
VkResult vulkanResult;
if (renderer->pendingTransfer)
{
VULKAN_INTERNAL_EndTransferCommandBuffer(renderer);
transferSubmitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
transferSubmitInfo.pNext = NULL;
transferSubmitInfo.commandBufferCount = 1;
transferSubmitInfo.pCommandBuffers = &renderer->transferCommandBuffers[renderer->frameIndex];
transferSubmitInfo.pWaitDstStageMask = NULL;
transferSubmitInfo.pWaitSemaphores = NULL;
transferSubmitInfo.waitSemaphoreCount = 0;
transferSubmitInfo.pSignalSemaphores = NULL;
transferSubmitInfo.signalSemaphoreCount = 0;
/* Wait for the previous submission to complete */
vulkanResult = renderer->vkWaitForFences(
renderer->logicalDevice,
1,
&renderer->inFlightFence,
VK_TRUE,
UINT64_MAX
);
if (vulkanResult != VK_SUCCESS)
{
LogVulkanResult("vkWaitForFences", vulkanResult);
return;
}
renderer->vkResetFences(
renderer->logicalDevice,
1,
&renderer->inFlightFence
);
/* Submit transfers */
vulkanResult = renderer->vkQueueSubmit(
renderer->transferQueue,
1,
&transferSubmitInfo,
NULL
);
if (vulkanResult != VK_SUCCESS)
{
LogVulkanResult("vkQueueSubmit", vulkanResult);
return;
}
/* Wait again */
vulkanResult = renderer->vkWaitForFences(
renderer->logicalDevice,
1,
&renderer->inFlightFence,
VK_TRUE,
UINT64_MAX
);
if (vulkanResult != VK_SUCCESS)
{
LogVulkanResult("vkWaitForFences", vulkanResult);
return;
}
renderer->vkResetFences(
renderer->logicalDevice,
1,
&renderer->inFlightFence
);
renderer->pendingTransfer = 0;
renderer->textureStagingBufferOffset = 0;
}
}
static void VULKAN_SetTextureData2D(
REFRESH_Renderer *driverData,
REFRESH_Texture *texture,
@ -5922,13 +5997,13 @@ static void VULKAN_SetTextureData2D(
VkBufferImageCopy imageCopy;
uint8_t *mapPointer;
VULKAN_INTERNAL_MaybeBeginTransferCommandBuffer(renderer);
VULKAN_INTERNAL_MaybeExpandStagingBuffer(renderer, dataLengthInBytes);
VULKAN_INTERNAL_MaybeBeginTransferCommandBuffer(renderer);
vulkanResult = renderer->vkMapMemory(
renderer->logicalDevice,
renderer->textureStagingBuffer->subBuffers[0]->allocation->memory,
renderer->textureStagingBuffer->subBuffers[0]->offset,
renderer->textureStagingBuffer->subBuffers[0]->offset + renderer->textureStagingBufferOffset,
renderer->textureStagingBuffer->subBuffers[0]->size,
0,
(void**) &mapPointer
@ -5971,7 +6046,7 @@ static void VULKAN_SetTextureData2D(
imageCopy.imageSubresource.baseArrayLayer = 0;
imageCopy.imageSubresource.layerCount = 1;
imageCopy.imageSubresource.mipLevel = level;
imageCopy.bufferOffset = 0;
imageCopy.bufferOffset = renderer->textureStagingBufferOffset;
imageCopy.bufferRowLength = 0;
imageCopy.bufferImageHeight = 0;
@ -5984,6 +6059,8 @@ static void VULKAN_SetTextureData2D(
&imageCopy
);
renderer->textureStagingBufferOffset += dataLengthInBytes;
if (vulkanTexture->usageFlags & REFRESH_TEXTUREUSAGE_SAMPLER_BIT)
{
VULKAN_INTERNAL_ImageMemoryBarrier(
@ -6023,13 +6100,13 @@ static void VULKAN_SetTextureData3D(
VkBufferImageCopy imageCopy;
uint8_t *mapPointer;
VULKAN_INTERNAL_MaybeBeginTransferCommandBuffer(renderer);
VULKAN_INTERNAL_MaybeExpandStagingBuffer(renderer, dataLength);
VULKAN_INTERNAL_MaybeBeginTransferCommandBuffer(renderer);
vulkanResult = renderer->vkMapMemory(
renderer->logicalDevice,
renderer->textureStagingBuffer->subBuffers[0]->allocation->memory,
renderer->textureStagingBuffer->subBuffers[0]->offset,
renderer->textureStagingBuffer->subBuffers[0]->offset + renderer->textureStagingBufferOffset,
renderer->textureStagingBuffer->subBuffers[0]->size,
0,
(void**) &mapPointer
@ -6072,7 +6149,7 @@ static void VULKAN_SetTextureData3D(
imageCopy.imageSubresource.baseArrayLayer = 0;
imageCopy.imageSubresource.layerCount = 1;
imageCopy.imageSubresource.mipLevel = level;
imageCopy.bufferOffset = 0;
imageCopy.bufferOffset = renderer->textureStagingBufferOffset;
imageCopy.bufferRowLength = 0;
imageCopy.bufferImageHeight = 0;
@ -6085,6 +6162,8 @@ static void VULKAN_SetTextureData3D(
&imageCopy
);
renderer->textureStagingBufferOffset += dataLength;
if (vulkanTexture->usageFlags & REFRESH_TEXTUREUSAGE_SAMPLER_BIT)
{
VULKAN_INTERNAL_ImageMemoryBarrier(
@ -6123,13 +6202,13 @@ static void VULKAN_SetTextureDataCube(
VkBufferImageCopy imageCopy;
uint8_t *mapPointer;
VULKAN_INTERNAL_MaybeBeginTransferCommandBuffer(renderer);
VULKAN_INTERNAL_MaybeExpandStagingBuffer(renderer, dataLength);
VULKAN_INTERNAL_MaybeBeginTransferCommandBuffer(renderer);
vulkanResult = renderer->vkMapMemory(
renderer->logicalDevice,
renderer->textureStagingBuffer->subBuffers[0]->allocation->memory,
renderer->textureStagingBuffer->subBuffers[0]->offset,
renderer->textureStagingBuffer->subBuffers[0]->offset + renderer->textureStagingBufferOffset,
renderer->textureStagingBuffer->subBuffers[0]->size,
0,
(void**) &mapPointer
@ -6172,7 +6251,7 @@ static void VULKAN_SetTextureDataCube(
imageCopy.imageSubresource.baseArrayLayer = cubeMapFace;
imageCopy.imageSubresource.layerCount = 1;
imageCopy.imageSubresource.mipLevel = level;
imageCopy.bufferOffset = 0;
imageCopy.bufferOffset = renderer->textureStagingBufferOffset;
imageCopy.bufferRowLength = 0; /* assumes tightly packed data */
imageCopy.bufferImageHeight = 0; /* assumes tightly packed data */
@ -6185,6 +6264,8 @@ static void VULKAN_SetTextureDataCube(
&imageCopy
);
renderer->textureStagingBufferOffset += dataLength;
if (vulkanTexture->usageFlags & REFRESH_TEXTUREUSAGE_SAMPLER_BIT)
{
VULKAN_INTERNAL_ImageMemoryBarrier(
@ -6226,8 +6307,8 @@ static void VULKAN_SetTextureDataYUV(
uint8_t *mapPointer;
VkResult vulkanResult;
VULKAN_INTERNAL_MaybeBeginTransferCommandBuffer(renderer);
VULKAN_INTERNAL_MaybeExpandStagingBuffer(renderer, dataLength);
VULKAN_INTERNAL_MaybeBeginTransferCommandBuffer(renderer);
/* Initialize values that are the same for Y, U, and V */
@ -6239,7 +6320,6 @@ static void VULKAN_SetTextureDataYUV(
imageCopy.imageSubresource.baseArrayLayer = 0;
imageCopy.imageSubresource.layerCount = 1;
imageCopy.imageSubresource.mipLevel = 0;
imageCopy.bufferOffset = 0;
/* Y */
@ -6248,7 +6328,7 @@ static void VULKAN_SetTextureDataYUV(
vulkanResult = renderer->vkMapMemory(
renderer->logicalDevice,
renderer->textureStagingBuffer->subBuffers[0]->allocation->memory,
renderer->textureStagingBuffer->subBuffers[0]->offset,
renderer->textureStagingBuffer->subBuffers[0]->offset + renderer->textureStagingBufferOffset,
renderer->textureStagingBuffer->subBuffers[0]->size,
0,
(void**) &mapPointer
@ -6280,8 +6360,10 @@ static void VULKAN_SetTextureDataYUV(
&tex->resourceAccessType
);
imageCopy.imageExtent.width = yWidth;
imageCopy.imageExtent.height = yHeight;
imageCopy.bufferOffset = renderer->textureStagingBufferOffset;
imageCopy.bufferRowLength = yWidth;
imageCopy.bufferImageHeight = yHeight;
@ -6303,7 +6385,7 @@ static void VULKAN_SetTextureDataYUV(
/* U */
imageCopy.bufferOffset = yDataLength;
imageCopy.bufferOffset = renderer->textureStagingBufferOffset + yDataLength;
tex = (VulkanTexture*) u;
@ -6338,7 +6420,7 @@ static void VULKAN_SetTextureDataYUV(
/* V */
imageCopy.bufferOffset = yDataLength + uvDataLength;
imageCopy.bufferOffset = renderer->textureStagingBufferOffset + uvDataLength;
tex = (VulkanTexture*) v;
@ -6376,6 +6458,8 @@ static void VULKAN_SetTextureDataYUV(
&imageCopy
);
renderer->textureStagingBufferOffset += dataLength;
if (tex->usageFlags & REFRESH_TEXTUREUSAGE_SAMPLER_BIT)
{
VULKAN_INTERNAL_ImageMemoryBarrier(
@ -7154,18 +7238,29 @@ static void VULKAN_AddDisposeSampler(
SDL_UnlockMutex(renderer->disposeLock);
}
static void VULKAN_AddDisposeVertexBuffer(
static void VULKAN_AddDisposeBuffer(
REFRESH_Renderer *driverData,
REFRESH_Buffer *buffer
) {
VULKAN_INTERNAL_RemoveBuffer(driverData, buffer);
}
VulkanRenderer *renderer = (VulkanRenderer*) driverData;
VulkanBuffer *vulkanBuffer = (VulkanBuffer*) buffer;
static void VULKAN_AddDisposeIndexBuffer(
REFRESH_Renderer *driverData,
REFRESH_Buffer *buffer
) {
VULKAN_INTERNAL_RemoveBuffer(driverData, buffer);
SDL_LockMutex(renderer->disposeLock);
EXPAND_ARRAY_IF_NEEDED(
renderer->buffersToDestroy,
VulkanBuffer*,
renderer->buffersToDestroyCount + 1,
renderer->buffersToDestroyCapacity,
renderer->buffersToDestroyCapacity * 2
)
renderer->buffersToDestroy[
renderer->buffersToDestroyCount
] = vulkanBuffer;
renderer->buffersToDestroyCount += 1;
SDL_UnlockMutex(renderer->disposeLock);
}
static void VULKAN_AddDisposeColorTarget(
@ -8216,7 +8311,9 @@ static void VULKAN_Submit(
uint32_t i;
uint8_t present;
VkPipelineStageFlags waitStages = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
VkPipelineStageFlags waitStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
VkSemaphore waitSemaphores[2];
uint32_t waitSemaphoreCount = 0;
VkPresentInfoKHR presentInfo;
if (renderer->pendingTransfer)
@ -8232,6 +8329,9 @@ static void VULKAN_Submit(
transferSubmitInfo.waitSemaphoreCount = 0;
transferSubmitInfo.pSignalSemaphores = &renderer->transferFinishedSemaphore;
transferSubmitInfo.signalSemaphoreCount = 1;
waitSemaphores[waitSemaphoreCount] = renderer->transferFinishedSemaphore;
waitSemaphoreCount += 1;
}
present = !renderer->headless && renderer->shouldPresent;
@ -8252,21 +8352,23 @@ static void VULKAN_Submit(
if (present)
{
submitInfo.waitSemaphoreCount = 1;
submitInfo.pWaitSemaphores = &renderer->imageAvailableSemaphore;
submitInfo.pWaitDstStageMask = &waitStages;
waitSemaphores[waitSemaphoreCount] = renderer->imageAvailableSemaphore;
waitSemaphoreCount += 1;
submitInfo.pWaitDstStageMask = &waitStage;
submitInfo.signalSemaphoreCount = 1;
submitInfo.pSignalSemaphores = &renderer->renderFinishedSemaphore;
}
else
{
submitInfo.waitSemaphoreCount = 0;
submitInfo.pWaitSemaphores = NULL;
submitInfo.pWaitDstStageMask = NULL;
submitInfo.signalSemaphoreCount = 0;
submitInfo.pSignalSemaphores = NULL;
}
submitInfo.waitSemaphoreCount = waitSemaphoreCount;
submitInfo.pWaitSemaphores = waitSemaphores;
/* Wait for the previous submission to complete */
vulkanResult = renderer->vkWaitForFences(
renderer->logicalDevice,
@ -8394,6 +8496,7 @@ static void VULKAN_Submit(
renderer->swapChainImageAcquired = 0;
renderer->shouldPresent = 0;
renderer->pendingTransfer = 0;
renderer->textureStagingBufferOffset = 0;
SDL_stack_free(commandBuffers);
}
@ -8901,12 +9004,11 @@ static uint8_t VULKAN_INTERNAL_CreateLogicalDevice(
VkDeviceCreateInfo deviceCreateInfo;
VkPhysicalDeviceFeatures deviceFeatures;
VkDeviceQueueCreateInfo queueCreateInfos[3];
VkDeviceQueueCreateInfo queueCreateInfos[2];
VkDeviceQueueCreateInfo queueCreateInfoGraphics;
VkDeviceQueueCreateInfo queueCreateInfoPresent;
VkDeviceQueueCreateInfo queueCreateInfoTransfer;
int32_t queueInfoCount = 2;
int32_t queueInfoCount = 1;
float queuePriority = 1.0f;
queueCreateInfoGraphics.sType =
@ -8920,17 +9022,6 @@ static uint8_t VULKAN_INTERNAL_CreateLogicalDevice(
queueCreateInfos[0] = queueCreateInfoGraphics;
queueCreateInfoTransfer.sType =
VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queueCreateInfoTransfer.pNext = NULL;
queueCreateInfoTransfer.flags = 0;
queueCreateInfoTransfer.queueFamilyIndex =
renderer->queueFamilyIndices.transferFamily;
queueCreateInfoTransfer.queueCount = 1;
queueCreateInfoTransfer.pQueuePriorities = &queuePriority;
queueCreateInfos[1] = queueCreateInfoTransfer;
if (renderer->queueFamilyIndices.presentFamily != renderer->queueFamilyIndices.graphicsFamily)
{
queueCreateInfoPresent.sType =
@ -9606,6 +9697,8 @@ static REFRESH_Device* VULKAN_CreateDevice(
return NULL;
}
renderer->textureStagingBufferOffset = 0;
/* Dummy Uniform Buffers */
renderer->dummyVertexUniformBuffer = (VulkanBuffer*) SDL_malloc(sizeof(VulkanBuffer));