vk: Implement fences

This basic implementation uses a throw-away bo for synchronization.
This commit is contained in:
Kristian Høgsberg
2015-05-18 08:49:15 -07:00
parent e26a7ffbd9
commit 6afb26452b
2 changed files with 127 additions and 11 deletions

View File

@@ -574,10 +574,11 @@ VkResult anv_QueueSubmit(
VkQueue _queue, VkQueue _queue,
uint32_t cmdBufferCount, uint32_t cmdBufferCount,
const VkCmdBuffer* pCmdBuffers, const VkCmdBuffer* pCmdBuffers,
VkFence fence) VkFence _fence)
{ {
struct anv_queue *queue = (struct anv_queue *) _queue; struct anv_queue *queue = (struct anv_queue *) _queue;
struct anv_device *device = queue->device; struct anv_device *device = queue->device;
struct anv_fence *fence = (struct anv_fence *) _fence;
int ret; int ret;
for (uint32_t i = 0; i < cmdBufferCount; i++) { for (uint32_t i = 0; i < cmdBufferCount; i++) {
@@ -592,6 +593,12 @@ VkResult anv_QueueSubmit(
if (ret != 0) if (ret != 0)
return vk_error(VK_ERROR_UNKNOWN); return vk_error(VK_ERROR_UNKNOWN);
if (fence) {
ret = anv_gem_execbuffer(device, &fence->execbuf);
if (ret != 0)
return vk_error(VK_ERROR_UNKNOWN);
}
for (uint32_t i = 0; i < cmd_buffer->bo_count; i++) for (uint32_t i = 0; i < cmd_buffer->bo_count; i++)
cmd_buffer->exec2_bos[i]->offset = cmd_buffer->exec2_objects[i].offset; cmd_buffer->exec2_bos[i]->offset = cmd_buffer->exec2_objects[i].offset;
} else { } else {
@@ -936,6 +943,19 @@ anv_free_destructor(struct anv_device * device,
return VK_SUCCESS; return VK_SUCCESS;
} }
static VkResult
anv_fence_destructor(struct anv_device * device,
VkObject object)
{
struct anv_fence *fence = (struct anv_fence *) object;
anv_gem_munmap(fence->bo.map, fence->bo.size);
anv_gem_close(device, fence->bo.gem_handle);
anv_device_free(device, fence);
return VK_SUCCESS;
}
static VkResult (*anv_object_destructors[])(struct anv_device *device, static VkResult (*anv_object_destructors[])(struct anv_device *device,
VkObject object) = { VkObject object) = {
[VK_OBJECT_TYPE_INSTANCE] = anv_instance_destructor, [VK_OBJECT_TYPE_INSTANCE] = anv_instance_destructor,
@@ -947,7 +967,8 @@ static VkResult (*anv_object_destructors[])(struct anv_device *device,
[VK_OBJECT_TYPE_SHADER] = anv_free_destructor, [VK_OBJECT_TYPE_SHADER] = anv_free_destructor,
[VK_OBJECT_TYPE_BUFFER] = anv_free_destructor, [VK_OBJECT_TYPE_BUFFER] = anv_free_destructor,
[VK_OBJECT_TYPE_IMAGE] = anv_free_destructor, [VK_OBJECT_TYPE_IMAGE] = anv_free_destructor,
[VK_OBJECT_TYPE_RENDER_PASS] = anv_free_destructor [VK_OBJECT_TYPE_RENDER_PASS] = anv_free_destructor,
[VK_OBJECT_TYPE_FENCE] = anv_fence_destructor
}; };
VkResult anv_DestroyObject( VkResult anv_DestroyObject(
@@ -1102,36 +1123,124 @@ VkResult anv_QueueBindImageMemoryRange(
} }
VkResult anv_CreateFence( VkResult anv_CreateFence(
VkDevice device, VkDevice _device,
const VkFenceCreateInfo* pCreateInfo, const VkFenceCreateInfo* pCreateInfo,
VkFence* pFence) VkFence* pFence)
{ {
stub_return(VK_UNSUPPORTED); struct anv_device *device = (struct anv_device *) _device;
struct anv_fence *fence;
struct anv_batch batch;
VkResult result;
const uint32_t fence_size = 128;
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_FENCE_CREATE_INFO);
fence = anv_device_alloc(device, sizeof(*fence), 8,
VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
if (fence == NULL)
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
result = anv_bo_init_new(&fence->bo, device, fence_size);
if (result != VK_SUCCESS)
goto fail;
fence->bo.map =
anv_gem_mmap(device, fence->bo.gem_handle, 0, fence->bo.size);
batch.next = fence->bo.map;
anv_batch_emit(&batch, GEN8_MI_BATCH_BUFFER_END);
anv_batch_emit(&batch, GEN8_MI_NOOP);
fence->exec2_objects[0].handle = fence->bo.gem_handle;
fence->exec2_objects[0].relocation_count = 0;
fence->exec2_objects[0].relocs_ptr = 0;
fence->exec2_objects[0].alignment = 0;
fence->exec2_objects[0].offset = fence->bo.offset;
fence->exec2_objects[0].flags = 0;
fence->exec2_objects[0].rsvd1 = 0;
fence->exec2_objects[0].rsvd2 = 0;
fence->execbuf.buffers_ptr = (uintptr_t) fence->exec2_objects;
fence->execbuf.buffer_count = 1;
fence->execbuf.batch_start_offset = 0;
fence->execbuf.batch_len = batch.next - fence->bo.map;
fence->execbuf.cliprects_ptr = 0;
fence->execbuf.num_cliprects = 0;
fence->execbuf.DR1 = 0;
fence->execbuf.DR4 = 0;
fence->execbuf.flags =
I915_EXEC_HANDLE_LUT | I915_EXEC_NO_RELOC | I915_EXEC_RENDER;
fence->execbuf.rsvd1 = device->context_id;
fence->execbuf.rsvd2 = 0;
*pFence = (VkQueryPool) fence;
return VK_SUCCESS;
fail:
anv_device_free(device, fence);
return result;
} }
VkResult anv_ResetFences( VkResult anv_ResetFences(
VkDevice device, VkDevice _device,
uint32_t fenceCount, uint32_t fenceCount,
VkFence* pFences) VkFence* pFences)
{ {
stub_return(VK_UNSUPPORTED); struct anv_fence **fences = (struct anv_fence **) pFences;
for (uint32_t i; i < fenceCount; i++)
fences[i]->ready = false;
return VK_SUCCESS;
} }
VkResult anv_GetFenceStatus( VkResult anv_GetFenceStatus(
VkDevice device, VkDevice _device,
VkFence fence) VkFence _fence)
{ {
stub_return(VK_UNSUPPORTED); struct anv_device *device = (struct anv_device *) _device;
struct anv_fence *fence = (struct anv_fence *) _fence;
int64_t t = 0;
int ret;
if (fence->ready)
return VK_SUCCESS;
ret = anv_gem_wait(device, fence->bo.gem_handle, &t);
if (ret == 0) {
fence->ready = true;
return VK_SUCCESS;
}
return VK_NOT_READY;
} }
VkResult anv_WaitForFences( VkResult anv_WaitForFences(
VkDevice device, VkDevice _device,
uint32_t fenceCount, uint32_t fenceCount,
const VkFence* pFences, const VkFence* pFences,
bool32_t waitAll, bool32_t waitAll,
uint64_t timeout) uint64_t timeout)
{ {
stub_return(VK_UNSUPPORTED); struct anv_device *device = (struct anv_device *) _device;
struct anv_fence **fences = (struct anv_fence **) pFences;
int64_t t = timeout;
int ret;
/* FIXME: handle !waitAll */
for (uint32_t i = 0; i < fenceCount; i++) {
ret = anv_gem_wait(device, fences[i]->bo.gem_handle, &t);
if (ret == -1 && errno == ETIME)
return VK_TIMEOUT;
else if (ret == -1)
return vk_error(VK_ERROR_UNKNOWN);
}
return VK_SUCCESS;
} }
// Queue semaphore functions // Queue semaphore functions

View File

@@ -550,6 +550,13 @@ struct anv_cmd_buffer {
void anv_cmd_buffer_dump(struct anv_cmd_buffer *cmd_buffer); void anv_cmd_buffer_dump(struct anv_cmd_buffer *cmd_buffer);
void anv_aub_writer_destroy(struct anv_aub_writer *writer); void anv_aub_writer_destroy(struct anv_aub_writer *writer);
struct anv_fence {
struct anv_bo bo;
struct drm_i915_gem_execbuffer2 execbuf;
struct drm_i915_gem_exec_object2 exec2_objects[1];
bool ready;
};
struct anv_shader { struct anv_shader {
uint32_t size; uint32_t size;
char data[0]; char data[0];