vk: Implement fences
This basic implementation uses a throw-away bo for synchronization.
This commit is contained in:
@@ -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
|
||||||
|
@@ -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];
|
||||||
|
Reference in New Issue
Block a user