From: Rémi Bernon <rbernon(a)codeweavers.com> --- dlls/win32u/vulkan.c | 112 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 109 insertions(+), 3 deletions(-) diff --git a/dlls/win32u/vulkan.c b/dlls/win32u/vulkan.c index a31563e07c8..1eea15024a5 100644 --- a/dlls/win32u/vulkan.c +++ b/dlls/win32u/vulkan.c @@ -59,6 +59,40 @@ static const UINT EXTERNAL_SEMAPHORE_WIN32_BITS = VK_EXTERNAL_SEMAPHORE_HANDLE_T static const UINT EXTERNAL_FENCE_WIN32_BITS = VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT | VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT; +#define ROUND_SIZE(size, mask) ((((SIZE_T)(size) + (mask)) & ~(SIZE_T)(mask))) + +struct mempool +{ + struct mempool *next; + size_t mem_used; + char mem[2048]; +}; + +static void mem_free( struct mempool *pool ) +{ + struct mempool *iter, *next = pool->next; + while ((iter = next)) { next = iter->next; free( iter ); } + pool->mem_used = 0; + pool->next = NULL; +} + +static void *mem_alloc( struct mempool *pool, size_t size ) +{ + struct mempool *next = pool; + if (pool->mem_used + size > sizeof(pool->mem)) next = pool->next; + if (next && next->mem_used <= sizeof(next->mem) && next->mem_used + size <= sizeof(next->mem)) + { + void *ret = next->mem + next->mem_used; + next->mem_used += ROUND_SIZE( size, sizeof(UINT64) - 1 ); + return ret; + } + if (!(next = malloc( max( sizeof(*next), offsetof(struct mempool, mem[size]) ) ))) return NULL; + next->next = pool->next; + next->mem_used = size; + pool->next = next; + return next->mem; +} + struct device_memory { struct vulkan_device_memory obj; @@ -1367,6 +1401,8 @@ static VkResult win32u_vkQueueSubmit( VkQueue client_queue, uint32_t count, cons struct vulkan_fence *fence = client_fence ? vulkan_fence_from_handle( client_fence ) : NULL; struct vulkan_queue *queue = vulkan_queue_from_handle( client_queue ); struct vulkan_device *device = queue->device; + VkResult res = VK_ERROR_OUT_OF_HOST_MEMORY; + struct mempool pool = {0}; TRACE( "queue %p, count %u, submits %p, fence %p\n", queue, count, submits, fence ); @@ -1374,6 +1410,13 @@ static VkResult win32u_vkQueueSubmit( VkQueue client_queue, uint32_t count, cons { VkSubmitInfo *submit = (VkSubmitInfo *)submits + i; /* cast away const, chain has been copied in the thunks */ VkBaseOutStructure **next, *prev = (VkBaseOutStructure *)submit; + VkSemaphore *wait_semaphores, *signal_semaphores; + VkTimelineSemaphoreSubmitInfo *timeline = NULL; + VkDeviceGroupSubmitInfo *device_group = NULL; + UINT wait_count = 0, signal_count = 0; + VkPipelineStageFlags *wait_stages; + uint32_t *indexes; + uint64_t *values; for (uint32_t j = 0; j < submit->commandBufferCount; j++) { @@ -1404,23 +1447,86 @@ static VkResult win32u_vkQueueSubmit( VkQueue client_queue, uint32_t count, cons FIXME( "VK_STRUCTURE_TYPE_D3D12_FENCE_SUBMIT_INFO_KHR not implemented!\n" ); *next = (*next)->pNext; next = &prev; break; - case VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO: break; + case VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO: + device_group = (VkDeviceGroupSubmitInfo *)*next; + break; case VK_STRUCTURE_TYPE_FRAME_BOUNDARY_EXT: break; case VK_STRUCTURE_TYPE_FRAME_BOUNDARY_TENSORS_ARM: break; case VK_STRUCTURE_TYPE_LATENCY_SUBMISSION_PRESENT_ID_NV: break; case VK_STRUCTURE_TYPE_PERFORMANCE_QUERY_SUBMIT_INFO_KHR: break; case VK_STRUCTURE_TYPE_PROTECTED_SUBMIT_INFO: break; - case VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO: break; + case VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO: + timeline = (VkTimelineSemaphoreSubmitInfo *)*next; + break; case VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_KHR: + { + VkWin32KeyedMutexAcquireReleaseInfoKHR *mutex_info = (VkWin32KeyedMutexAcquireReleaseInfoKHR *)*next; FIXME( "VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_KHR not implemented!\n" ); + wait_count = mutex_info->acquireCount; + signal_count = mutex_info->releaseCount; *next = (*next)->pNext; next = &prev; break; + } default: FIXME( "Unhandled sType %u.\n", (*next)->sType ); break; } } + + if (wait_count) /* extra wait semaphores, need to update arrays and counts */ + { + if (!(wait_semaphores = mem_alloc( &pool, (submit->waitSemaphoreCount + wait_count) * sizeof(*wait_semaphores) ))) goto failed; + memcpy( wait_semaphores, submit->pWaitSemaphores, submit->waitSemaphoreCount * sizeof(*wait_semaphores) ); + submit->pWaitSemaphores = wait_semaphores; + + if (!(wait_stages = mem_alloc( &pool, (submit->waitSemaphoreCount + wait_count) * sizeof(*wait_stages) ))) goto failed; + memcpy( wait_stages, submit->pWaitDstStageMask, submit->waitSemaphoreCount * sizeof(*wait_stages) ); + submit->pWaitDstStageMask = wait_stages; + + if (timeline) + { + if (!(values = mem_alloc( &pool, (timeline->waitSemaphoreValueCount + wait_count) * sizeof(*values) ))) goto failed; + memcpy( values, timeline->pWaitSemaphoreValues, timeline->waitSemaphoreValueCount * sizeof(*values) ); + timeline->waitSemaphoreValueCount = submit->waitSemaphoreCount; + timeline->pWaitSemaphoreValues = values; + } + + if (device_group) + { + if (!(indexes = mem_alloc( &pool, submit->waitSemaphoreCount * sizeof(*indexes) ))) goto failed; + memcpy( indexes, device_group->pWaitSemaphoreDeviceIndices, device_group->waitSemaphoreCount * sizeof(*indexes) ); + device_group->waitSemaphoreCount = submit->waitSemaphoreCount; + device_group->pWaitSemaphoreDeviceIndices = indexes; + } + } + + if (signal_count) /* extra signal semaphores, need to update arrays and counts */ + { + if (!(signal_semaphores = mem_alloc( &pool, (submit->signalSemaphoreCount + signal_count) * sizeof(*signal_semaphores) ))) goto failed; + memcpy( signal_semaphores, submit->pSignalSemaphores, submit->signalSemaphoreCount * sizeof(*signal_semaphores) ); + submit->pSignalSemaphores = signal_semaphores; + + if (timeline) + { + if (!(values = mem_alloc( &pool, submit->signalSemaphoreCount * sizeof(*values) ))) goto failed; + memcpy( values, timeline->pSignalSemaphoreValues, timeline->signalSemaphoreValueCount * sizeof(*values) ); + timeline->signalSemaphoreValueCount = submit->signalSemaphoreCount; + timeline->pSignalSemaphoreValues = values; + } + + if (device_group) + { + if (!(indexes = mem_alloc( &pool, submit->signalSemaphoreCount * sizeof(*indexes) ))) goto failed; + memcpy( indexes, device_group->pSignalSemaphoreDeviceIndices, device_group->signalSemaphoreCount * sizeof(*indexes) ); + device_group->signalSemaphoreCount = submit->signalSemaphoreCount; + device_group->pSignalSemaphoreDeviceIndices = indexes; + } + } } - return device->p_vkQueueSubmit( queue->host.queue, count, submits, fence ? fence->host.fence : 0 ); + res = device->p_vkQueueSubmit( queue->host.queue, count, submits, fence ? fence->host.fence : 0 ); + +failed: + mem_free( &pool ); + return res; } static VkResult win32u_vkQueueSubmit2( VkQueue client_queue, uint32_t count, const VkSubmitInfo2 *submits, VkFence client_fence ) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9268