First pass at fence infrastructure

pull/47/head
Caleb Cornett 2024-02-08 22:53:36 -06:00
parent ebf96ff423
commit 0d6043cfef
1 changed files with 104 additions and 22 deletions

View File

@ -443,6 +443,11 @@ typedef struct D3D11UniformBuffer
uint32_t offset; uint32_t offset;
} D3D11UniformBuffer; } D3D11UniformBuffer;
typedef struct D3D11Fence
{
ID3D11Query *handle;
} D3D11Fence;
typedef struct D3D11CommandBuffer typedef struct D3D11CommandBuffer
{ {
/* D3D11 Object References */ /* D3D11 Object References */
@ -459,7 +464,7 @@ typedef struct D3D11CommandBuffer
/* State */ /* State */
SDL_threadID threadID; SDL_threadID threadID;
ID3D11Query *completionQuery; D3D11Fence *fence;
/* Uniforms */ /* Uniforms */
D3D11UniformBuffer *vertexUniformBuffer; D3D11UniformBuffer *vertexUniformBuffer;
@ -509,9 +514,14 @@ typedef struct D3D11Renderer
uint32_t availableUniformBufferCount; uint32_t availableUniformBufferCount;
uint32_t availableUniformBufferCapacity; uint32_t availableUniformBufferCapacity;
D3D11Fence **availableFences;
uint32_t availableFenceCount;
uint32_t availableFenceCapacity;
SDL_mutex *contextLock; SDL_mutex *contextLock;
SDL_mutex *acquireCommandBufferLock; SDL_mutex *acquireCommandBufferLock;
SDL_mutex *uniformBufferLock; SDL_mutex *uniformBufferLock;
SDL_mutex *acquireFenceLock;
} D3D11Renderer; } D3D11Renderer;
/* Logging */ /* Logging */
@ -606,7 +616,6 @@ static void D3D11_DestroyDevice(
for (uint32_t i = 0; i < renderer->availableCommandBufferCount; i += 1) for (uint32_t i = 0; i < renderer->availableCommandBufferCount; i += 1)
{ {
D3D11CommandBuffer *commandBuffer = renderer->availableCommandBuffers[i]; D3D11CommandBuffer *commandBuffer = renderer->availableCommandBuffers[i];
ID3D11Query_Release(commandBuffer->completionQuery);
ID3D11DeviceContext_Release(commandBuffer->context); ID3D11DeviceContext_Release(commandBuffer->context);
SDL_free(commandBuffer); SDL_free(commandBuffer);
} }
@ -623,10 +632,20 @@ static void D3D11_DestroyDevice(
} }
SDL_free(renderer->availableUniformBuffers); SDL_free(renderer->availableUniformBuffers);
/* Release fence infrastructure */
for (uint32_t i = 0; i < renderer->availableFenceCount; i += 1)
{
D3D11Fence *fence = renderer->availableFences[i];
ID3D11Query_Release(fence->handle);
SDL_free(fence);
}
SDL_free(renderer->availableFences);
/* Release the mutexes */ /* Release the mutexes */
SDL_DestroyMutex(renderer->acquireCommandBufferLock); SDL_DestroyMutex(renderer->acquireCommandBufferLock);
SDL_DestroyMutex(renderer->contextLock); SDL_DestroyMutex(renderer->contextLock);
SDL_DestroyMutex(renderer->uniformBufferLock); SDL_DestroyMutex(renderer->uniformBufferLock);
SDL_DestroyMutex(renderer->acquireFenceLock);
/* Release the device and associated objects */ /* Release the device and associated objects */
ID3D11DeviceContext_Release(renderer->immediateContext); ID3D11DeviceContext_Release(renderer->immediateContext);
@ -2193,7 +2212,6 @@ static void D3D11_INTERNAL_AllocateCommandBuffers(
uint32_t allocateCount uint32_t allocateCount
) { ) {
D3D11CommandBuffer *commandBuffer; D3D11CommandBuffer *commandBuffer;
D3D11_QUERY_DESC queryDesc;
HRESULT res; HRESULT res;
renderer->availableCommandBufferCapacity += allocateCount; renderer->availableCommandBufferCapacity += allocateCount;
@ -2215,16 +2233,6 @@ static void D3D11_INTERNAL_AllocateCommandBuffers(
); );
ERROR_CHECK("Could not create deferred context"); ERROR_CHECK("Could not create deferred context");
/* Fence Query */
queryDesc.Query = D3D11_QUERY_EVENT;
queryDesc.MiscFlags = 0;
res = ID3D11Device_CreateQuery(
renderer->device,
&queryDesc,
&commandBuffer->completionQuery
);
ERROR_CHECK("Could not create query");
/* Bound Uniform Buffers */ /* Bound Uniform Buffers */
commandBuffer->boundUniformBufferCapacity = 16; commandBuffer->boundUniformBufferCapacity = 16;
commandBuffer->boundUniformBufferCount = 0; commandBuffer->boundUniformBufferCount = 0;
@ -2232,8 +2240,6 @@ static void D3D11_INTERNAL_AllocateCommandBuffers(
commandBuffer->boundUniformBufferCapacity * sizeof(D3D11UniformBuffer*) commandBuffer->boundUniformBufferCapacity * sizeof(D3D11UniformBuffer*)
); );
/* FIXME: Resource tracking? */
renderer->availableCommandBuffers[renderer->availableCommandBufferCount] = commandBuffer; renderer->availableCommandBuffers[renderer->availableCommandBufferCount] = commandBuffer;
renderer->availableCommandBufferCount += 1; renderer->availableCommandBufferCount += 1;
} }
@ -2258,6 +2264,59 @@ static D3D11CommandBuffer* D3D11_INTERNAL_GetInactiveCommandBufferFromPool(
return commandBuffer; return commandBuffer;
} }
static void D3D11_INTERNAL_AllocateFences(
D3D11Renderer *renderer,
uint32_t allocateCount
) {
D3D11Fence *fence;
D3D11_QUERY_DESC queryDesc;
HRESULT res;
renderer->availableFenceCapacity += allocateCount;
renderer->availableFences = SDL_realloc(
renderer->availableFences,
sizeof(D3D11Fence*) * renderer->availableFenceCapacity
);
for (uint32_t i = 0; i < allocateCount; i += 1)
{
fence = SDL_malloc(sizeof(D3D11Fence));
queryDesc.Query = D3D11_QUERY_EVENT;
queryDesc.MiscFlags = 0;
res = ID3D11Device_CreateQuery(
renderer->device,
&queryDesc,
&fence->handle
);
ERROR_CHECK("Could not create query"); /* FIXME: Should this return an error code? */
renderer->availableFences[renderer->availableFenceCount] = fence;
renderer->availableFenceCount += 1;
}
}
static D3D11Fence* D3D11_INTERNAL_GetFenceFromPool(
D3D11Renderer* renderer
) {
D3D11Fence *fence;
SDL_LockMutex(renderer->acquireFenceLock);
if (renderer->availableFenceCount == 0)
{
D3D11_INTERNAL_AllocateFences(renderer, renderer->availableFenceCapacity);
}
fence = renderer->availableFences[renderer->availableFenceCount - 1];
renderer->availableFenceCount -= 1;
SDL_UnlockMutex(renderer->acquireFenceLock);
return fence;
}
static Refresh_CommandBuffer* D3D11_AcquireCommandBuffer( static Refresh_CommandBuffer* D3D11_AcquireCommandBuffer(
Refresh_Renderer *driverData Refresh_Renderer *driverData
) { ) {
@ -2267,8 +2326,8 @@ static Refresh_CommandBuffer* D3D11_AcquireCommandBuffer(
SDL_LockMutex(renderer->acquireCommandBufferLock); SDL_LockMutex(renderer->acquireCommandBufferLock);
/* Set up the command buffer */
commandBuffer = D3D11_INTERNAL_GetInactiveCommandBufferFromPool(renderer); commandBuffer = D3D11_INTERNAL_GetInactiveCommandBufferFromPool(renderer);
commandBuffer->threadID = SDL_ThreadID(); commandBuffer->threadID = SDL_ThreadID();
commandBuffer->swapchainData = NULL; commandBuffer->swapchainData = NULL;
commandBuffer->graphicsPipeline = NULL; commandBuffer->graphicsPipeline = NULL;
@ -2277,11 +2336,16 @@ static Refresh_CommandBuffer* D3D11_AcquireCommandBuffer(
commandBuffer->fragmentUniformBuffer = NULL; commandBuffer->fragmentUniformBuffer = NULL;
commandBuffer->computeUniformBuffer = NULL; commandBuffer->computeUniformBuffer = NULL;
commandBuffer->dsView = NULL; commandBuffer->dsView = NULL;
for (i = 0; i < MAX_COLOR_TARGET_BINDINGS; i += 1) for (i = 0; i < MAX_COLOR_TARGET_BINDINGS; i += 1)
{ {
commandBuffer->rtViews[i] = NULL; commandBuffer->rtViews[i] = NULL;
} }
SDL_LockMutex(renderer->acquireFenceLock);
commandBuffer->fence = D3D11_INTERNAL_GetFenceFromPool(renderer);
SDL_UnlockMutex(renderer->acquireFenceLock);
SDL_UnlockMutex(renderer->acquireCommandBufferLock); SDL_UnlockMutex(renderer->acquireCommandBufferLock);
return (Refresh_CommandBuffer*) commandBuffer; return (Refresh_CommandBuffer*) commandBuffer;
@ -3111,6 +3175,22 @@ static void D3D11_INTERNAL_CleanCommandBuffer(
commandBuffer->boundUniformBufferCount = 0; commandBuffer->boundUniformBufferCount = 0;
/* The fence is now available */
/* FIXME: Not if auto-release is false! */
SDL_LockMutex(renderer->acquireFenceLock);
if (renderer->availableFenceCount == renderer->availableFenceCapacity)
{
renderer->availableFenceCapacity *= 2;
renderer->availableFences = SDL_realloc(
renderer->availableFences,
renderer->availableFenceCapacity * sizeof(D3D11Fence*)
);
}
renderer->availableFences[renderer->availableFenceCount] = commandBuffer->fence;
renderer->availableFenceCount += 1;
SDL_UnlockMutex(renderer->acquireFenceLock);
/* Return command buffer to pool */ /* Return command buffer to pool */
SDL_LockMutex(renderer->acquireCommandBufferLock); SDL_LockMutex(renderer->acquireCommandBufferLock);
@ -3155,7 +3235,7 @@ static void D3D11_Submit(
/* Notify the command buffer completion query that we have completed recording */ /* Notify the command buffer completion query that we have completed recording */
ID3D11DeviceContext_End( ID3D11DeviceContext_End(
renderer->immediateContext, renderer->immediateContext,
(ID3D11Asynchronous*) d3d11CommandBuffer->completionQuery (ID3D11Asynchronous*) d3d11CommandBuffer->fence->handle
); );
/* Serialize the commands into the command list */ /* Serialize the commands into the command list */
@ -3205,7 +3285,7 @@ static void D3D11_Submit(
res = ID3D11DeviceContext_GetData( res = ID3D11DeviceContext_GetData(
renderer->immediateContext, renderer->immediateContext,
(ID3D11Asynchronous*) renderer->submittedCommandBuffers[i]->completionQuery, (ID3D11Asynchronous*) renderer->submittedCommandBuffers[i]->fence->handle,
&queryData, &queryData,
sizeof(queryData), sizeof(queryData),
0 0
@ -3245,7 +3325,7 @@ static void D3D11_Wait(
{ {
while (S_OK != ID3D11DeviceContext_GetData( while (S_OK != ID3D11DeviceContext_GetData(
renderer->immediateContext, renderer->immediateContext,
(ID3D11Asynchronous*) renderer->submittedCommandBuffers[i]->completionQuery, (ID3D11Asynchronous*) renderer->submittedCommandBuffers[i]->fence->handle,
&queryData, &queryData,
sizeof(queryData), sizeof(queryData),
0 0
@ -3262,8 +3342,6 @@ static void D3D11_Wait(
D3D11_INTERNAL_CleanCommandBuffer(renderer, commandBuffer); D3D11_INTERNAL_CleanCommandBuffer(renderer, commandBuffer);
} }
/* FIXME: D3D11_INTERNAL_PerformPendingDestroys(renderer); */
SDL_UnlockMutex(renderer->contextLock); SDL_UnlockMutex(renderer->contextLock);
} }
@ -3615,17 +3693,21 @@ tryCreateDevice:
renderer->contextLock = SDL_CreateMutex(); renderer->contextLock = SDL_CreateMutex();
renderer->acquireCommandBufferLock = SDL_CreateMutex(); renderer->acquireCommandBufferLock = SDL_CreateMutex();
renderer->uniformBufferLock = SDL_CreateMutex(); renderer->uniformBufferLock = SDL_CreateMutex();
renderer->acquireFenceLock = SDL_CreateMutex();
/* Initialize miscellaneous renderer members */ /* Initialize miscellaneous renderer members */
renderer->debugMode = (flags & D3D11_CREATE_DEVICE_DEBUG); renderer->debugMode = (flags & D3D11_CREATE_DEVICE_DEBUG);
/* Create command buffers to initialize the pool */ /* Create command buffer pool */
D3D11_INTERNAL_AllocateCommandBuffers(renderer, 2); D3D11_INTERNAL_AllocateCommandBuffers(renderer, 2);
/* Create uniform buffer pool */ /* Create uniform buffer pool */
renderer->availableUniformBufferCapacity = 2; renderer->availableUniformBufferCapacity = 2;
renderer->availableUniformBuffers = SDL_malloc(sizeof(D3D11UniformBuffer*) * renderer->availableUniformBufferCapacity); renderer->availableUniformBuffers = SDL_malloc(sizeof(D3D11UniformBuffer*) * renderer->availableUniformBufferCapacity);
/* Create fence pool */
D3D11_INTERNAL_AllocateFences(renderer, 2);
/* Create the Refresh Device */ /* Create the Refresh Device */
result = (Refresh_Device*) SDL_malloc(sizeof(Refresh_Device)); result = (Refresh_Device*) SDL_malloc(sizeof(Refresh_Device));
ASSIGN_DRIVER(D3D11) ASSIGN_DRIVER(D3D11)