Re: [Mesa-dev] [PATCH 16/21] anv: Implement VK_KHX_external_semaphore_fd

2017-05-03 Thread Jason Ekstrand
On Wed, May 3, 2017 at 12:04 PM, Chad Versace 
wrote:

> On Wed 03 May 2017, Jason Ekstrand wrote:
> > On Tue, May 2, 2017 at 5:15 PM, Chad Versace <[1]
> chadvers...@chromium.org>
> > wrote:
> >
> > On Fri 14 Apr 2017, Jason Ekstrand wrote:
> > > This implementation allocates a 4k BO for each semaphore that can
> be
> > > exported using OPAQUE_FD and uses the kernel's already-existing
> > > synchronization mechanism on BOs.
> > > ---
> > >  src/intel/vulkan/anv_batch_chain.c  |  53 ++--
> > >  src/intel/vulkan/anv_device.c   |   4 +
> > >  src/intel/vulkan/anv_entrypoints_gen.py |   1 +
> > >  src/intel/vulkan/anv_private.h  |  16 +++-
> > >  src/intel/vulkan/anv_queue.c| 141
> > ++--
> > >  5 files changed, 199 insertions(+), 16 deletions(-)
> >
> > [snip]
> >
> > > @@ -513,14 +533,33 @@ VkResult anv_CreateSemaphore(
> > >  VkExternalSemaphoreHandleTypeFlagsKHX handleTypes =
> > >export ? export->handleTypes : 0;
> > >
> > > -   /* External semaphores are not yet supported */
> > > -   assert(handleTypes == 0);
> > > +   if (handleTypes == 0) {
> > > +  /* The DRM execbuffer ioctl always execute in-oder so long
> as you
> > stay
> > > +   * on the same ring.  Since we don't expose the blit engine
> as a
> > DMA
> > > +   * queue, a dummy no-op semaphore is a perfectly valid
> > implementation.
> > > +   */
> > > +  semaphore->permanent.type = ANV_SEMAPHORE_TYPE_DUMMY;
> > > +   } else if (handleTypes & VK_EXTERNAL_SEMAPHORE_HANDLE_
> > TYPE_OPAQUE_FD_BIT_KHX) {
> > > +  assert(handleTypes == VK_EXTERNAL_SEMAPHORE_HANDLE_
> > TYPE_OPAQUE_FD_BIT_KHX);
> > > +
> > > +  semaphore->permanent.type = ANV_SEMAPHORE_TYPE_BO;
> > > +  VkResult result = anv_bo_cache_alloc(device,
> >bo_cache,
> > > +   4096, >[2]
> > permanent.bo);
> > > +  if (result != VK_SUCCESS) {
> > > + vk_free2(>alloc, pAllocator, semaphore);
> > > + return result;
> > > +  }
> > > +
> > > +  /* If we're going to use this as a fence, we need to *not*
> have
> > the
> > > +   * EXEC_OBJECT_ASYNC bit set.
> > > +   */
> > > +  semaphore->permanent.bo->flags &= ~EXEC_OBJECT_ASYNC;
> > > +   } else {
> > > +  assert(!"Unknown handle type");
> > > +  vk_free2(>alloc, pAllocator, semaphore);
> > > +  return vk_error(VK_ERROR_INVALID_EXTERNAL_HANDLE_KHX);
> >
> > The Vulkan 1.0.49 spec does not list
> > VK_ERROR_INVALID_EXTERNAL_HANDLE_KHX as a possible error code for
> > vkCreateSemaphore. The reason is that
> > VK_ERROR_INVALID_EXTERNAL_HANDLE_KHX indicates that an external
> handle
> > does not match the expected handle type. Since vkCreateSemaphore has
> no
> > parameter that's an external handle, it can't return the error.
> > VK_ERROR_INVALID_EXTERNAL_HANDLE_KHX only makes sense for functions
> that
> > import a handle or query the properties of a handle.
> >
> > This 'else' branch is capturing invalid application usage the API.
> Since
> > invalid usages leads to undefined behavior, we could claim that
> Mesa's
> > undefined behavior is to return a helpful error code. But...
> >
> > I much prefer disastrous undefined behavior here instead of helpful
> > undefined behavior. If we return VK_ERROR_INVALID_EXTERNAL_
> HANDLE_KHX,
> > then appsy may accidentally rely on our out-of-spec behavior. It
> would
> > be better to just abort() or, like anvil does in most cases, silently
> > ignore the invalid case and continue blindly ahead.
> >
> >
> > They do get disastrous behavior in debug builds because of the assert.
> In
> > release builds, however, I'm not sure what I think.  I don't know that I
> like
> > the idea of silently continuing because it would most likely give them a
> > perfectly "valid" dummy semaphore and they would get an error much later
> when
> > they try to export from it.  We could abort().  I don't know.  I really
> don't
> > think apps will rely on that error.
>
> After sleeping on this, I also don't know what the best behavior is.
> I still *prefer* that vkCreateSemaphore fail with disaster rather than
> fail with a helpful error code, but I'm no longer *confident* that's the
> right choice.
>
> More below.
>
> > [snip]
>
> > > +static void
> > > +anv_semaphore_impl_cleanup(struct anv_device *device,
> > > +   struct anv_semaphore_impl *impl)
> > > +{
> > > +   switch (impl->type) {
> > > +   case ANV_SEMAPHORE_TYPE_NONE:
> > > +   case ANV_SEMAPHORE_TYPE_DUMMY:
> > > +  /* Dummy.  Nothing to do */
> > > +  break;
> > > +
> > > +   case 

Re: [Mesa-dev] [PATCH 16/21] anv: Implement VK_KHX_external_semaphore_fd

2017-05-03 Thread Chad Versace
On Wed 03 May 2017, Jason Ekstrand wrote:
> On Tue, May 2, 2017 at 5:15 PM, Chad Versace <[1]chadvers...@chromium.org>
> wrote:
> 
> On Fri 14 Apr 2017, Jason Ekstrand wrote:
> > This implementation allocates a 4k BO for each semaphore that can be
> > exported using OPAQUE_FD and uses the kernel's already-existing
> > synchronization mechanism on BOs.
> > ---
> >  src/intel/vulkan/anv_batch_chain.c      |  53 ++--
> >  src/intel/vulkan/anv_device.c           |   4 +
> >  src/intel/vulkan/anv_entrypoints_gen.py |   1 +
> >  src/intel/vulkan/anv_private.h          |  16 +++-
> >  src/intel/vulkan/anv_queue.c            | 141
> ++--
> >  5 files changed, 199 insertions(+), 16 deletions(-)
> 
> [snip]
> 
> > @@ -513,14 +533,33 @@ VkResult anv_CreateSemaphore(
> >      VkExternalSemaphoreHandleTypeFlagsKHX handleTypes =
> >        export ? export->handleTypes : 0;
> >
> > -   /* External semaphores are not yet supported */
> > -   assert(handleTypes == 0);
> > +   if (handleTypes == 0) {
> > +      /* The DRM execbuffer ioctl always execute in-oder so long as you
> stay
> > +       * on the same ring.  Since we don't expose the blit engine as a
> DMA
> > +       * queue, a dummy no-op semaphore is a perfectly valid
> implementation.
> > +       */
> > +      semaphore->permanent.type = ANV_SEMAPHORE_TYPE_DUMMY;
> > +   } else if (handleTypes & VK_EXTERNAL_SEMAPHORE_HANDLE_
> TYPE_OPAQUE_FD_BIT_KHX) {
> > +      assert(handleTypes == VK_EXTERNAL_SEMAPHORE_HANDLE_
> TYPE_OPAQUE_FD_BIT_KHX);
> > +
> > +      semaphore->permanent.type = ANV_SEMAPHORE_TYPE_BO;
> > +      VkResult result = anv_bo_cache_alloc(device, >bo_cache,
> > +                                           4096, >[2]
> permanent.bo);
> > +      if (result != VK_SUCCESS) {
> > +         vk_free2(>alloc, pAllocator, semaphore);
> > +         return result;
> > +      }
> > +
> > +      /* If we're going to use this as a fence, we need to *not* have
> the
> > +       * EXEC_OBJECT_ASYNC bit set.
> > +       */
> > +      semaphore->permanent.bo->flags &= ~EXEC_OBJECT_ASYNC;
> > +   } else {
> > +      assert(!"Unknown handle type");
> > +      vk_free2(>alloc, pAllocator, semaphore);
> > +      return vk_error(VK_ERROR_INVALID_EXTERNAL_HANDLE_KHX);
> 
> The Vulkan 1.0.49 spec does not list
> VK_ERROR_INVALID_EXTERNAL_HANDLE_KHX as a possible error code for
> vkCreateSemaphore. The reason is that
> VK_ERROR_INVALID_EXTERNAL_HANDLE_KHX indicates that an external handle
> does not match the expected handle type. Since vkCreateSemaphore has no
> parameter that's an external handle, it can't return the error.
> VK_ERROR_INVALID_EXTERNAL_HANDLE_KHX only makes sense for functions that
> import a handle or query the properties of a handle.
> 
> This 'else' branch is capturing invalid application usage the API. Since
> invalid usages leads to undefined behavior, we could claim that Mesa's
> undefined behavior is to return a helpful error code. But...
> 
> I much prefer disastrous undefined behavior here instead of helpful
> undefined behavior. If we return VK_ERROR_INVALID_EXTERNAL_HANDLE_KHX,
> then appsy may accidentally rely on our out-of-spec behavior. It would
> be better to just abort() or, like anvil does in most cases, silently
> ignore the invalid case and continue blindly ahead.
> 
> 
> They do get disastrous behavior in debug builds because of the assert.  In
> release builds, however, I'm not sure what I think.  I don't know that I like
> the idea of silently continuing because it would most likely give them a
> perfectly "valid" dummy semaphore and they would get an error much later when
> they try to export from it.  We could abort().  I don't know.  I really don't
> think apps will rely on that error.

After sleeping on this, I also don't know what the best behavior is.
I still *prefer* that vkCreateSemaphore fail with disaster rather than
fail with a helpful error code, but I'm no longer *confident* that's the
right choice.

More below.

> [snip]

> > +static void
> > +anv_semaphore_impl_cleanup(struct anv_device *device,
> > +                           struct anv_semaphore_impl *impl)
> > +{
> > +   switch (impl->type) {
> > +   case ANV_SEMAPHORE_TYPE_NONE:
> > +   case ANV_SEMAPHORE_TYPE_DUMMY:
> > +      /* Dummy.  Nothing to do */
> > +      break;
> > +
> > +   case ANV_SEMAPHORE_TYPE_BO:
> > +      anv_bo_cache_release(device, >bo_cache, impl->bo);
> > +      break;
> > +
> > +   default:
> > +      unreachable("Invalid semaphore type");
> > +   }
> 
> This switch statement is a good candidate for exhaustive switch warnings
> (-Wswitch).  But we don't get the 

Re: [Mesa-dev] [PATCH 16/21] anv: Implement VK_KHX_external_semaphore_fd

2017-05-03 Thread Jason Ekstrand
On Tue, May 2, 2017 at 5:15 PM, Chad Versace 
wrote:

> On Fri 14 Apr 2017, Jason Ekstrand wrote:
> > This implementation allocates a 4k BO for each semaphore that can be
> > exported using OPAQUE_FD and uses the kernel's already-existing
> > synchronization mechanism on BOs.
> > ---
> >  src/intel/vulkan/anv_batch_chain.c  |  53 ++--
> >  src/intel/vulkan/anv_device.c   |   4 +
> >  src/intel/vulkan/anv_entrypoints_gen.py |   1 +
> >  src/intel/vulkan/anv_private.h  |  16 +++-
> >  src/intel/vulkan/anv_queue.c| 141
> ++--
> >  5 files changed, 199 insertions(+), 16 deletions(-)
>
> [snip]
>
> > @@ -513,14 +533,33 @@ VkResult anv_CreateSemaphore(
> >  VkExternalSemaphoreHandleTypeFlagsKHX handleTypes =
> >export ? export->handleTypes : 0;
> >
> > -   /* External semaphores are not yet supported */
> > -   assert(handleTypes == 0);
> > +   if (handleTypes == 0) {
> > +  /* The DRM execbuffer ioctl always execute in-oder so long as you
> stay
> > +   * on the same ring.  Since we don't expose the blit engine as a
> DMA
> > +   * queue, a dummy no-op semaphore is a perfectly valid
> implementation.
> > +   */
> > +  semaphore->permanent.type = ANV_SEMAPHORE_TYPE_DUMMY;
> > +   } else if (handleTypes & 
> > VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHX)
> {
> > +  assert(handleTypes == VK_EXTERNAL_SEMAPHORE_HANDLE_
> TYPE_OPAQUE_FD_BIT_KHX);
> > +
> > +  semaphore->permanent.type = ANV_SEMAPHORE_TYPE_BO;
> > +  VkResult result = anv_bo_cache_alloc(device, >bo_cache,
> > +   4096, >
> permanent.bo);
> > +  if (result != VK_SUCCESS) {
> > + vk_free2(>alloc, pAllocator, semaphore);
> > + return result;
> > +  }
> > +
> > +  /* If we're going to use this as a fence, we need to *not* have
> the
> > +   * EXEC_OBJECT_ASYNC bit set.
> > +   */
> > +  semaphore->permanent.bo->flags &= ~EXEC_OBJECT_ASYNC;
> > +   } else {
> > +  assert(!"Unknown handle type");
> > +  vk_free2(>alloc, pAllocator, semaphore);
> > +  return vk_error(VK_ERROR_INVALID_EXTERNAL_HANDLE_KHX);
>
> The Vulkan 1.0.49 spec does not list
> VK_ERROR_INVALID_EXTERNAL_HANDLE_KHX as a possible error code for
> vkCreateSemaphore. The reason is that
> VK_ERROR_INVALID_EXTERNAL_HANDLE_KHX indicates that an external handle
> does not match the expected handle type. Since vkCreateSemaphore has no
> parameter that's an external handle, it can't return the error.
> VK_ERROR_INVALID_EXTERNAL_HANDLE_KHX only makes sense for functions that
> import a handle or query the properties of a handle.
>
> This 'else' branch is capturing invalid application usage the API. Since
> invalid usages leads to undefined behavior, we could claim that Mesa's
> undefined behavior is to return a helpful error code. But...
>
> I much prefer disastrous undefined behavior here instead of helpful
> undefined behavior. If we return VK_ERROR_INVALID_EXTERNAL_HANDLE_KHX,
> then appsy may accidentally rely on our out-of-spec behavior. It would
> be better to just abort() or, like anvil does in most cases, silently
> ignore the invalid case and continue blindly ahead.
>

They do get disastrous behavior in debug builds because of the assert.  In
release builds, however, I'm not sure what I think.  I don't know that I
like the idea of silently continuing because it would most likely give them
a perfectly "valid" dummy semaphore and they would get an error much later
when they try to export from it.  We could abort().  I don't know.  I
really don't think apps will rely on that error.


> [snip]
>
> > +static void
> > +anv_semaphore_impl_cleanup(struct anv_device *device,
> > +   struct anv_semaphore_impl *impl)
> > +{
> > +   switch (impl->type) {
> > +   case ANV_SEMAPHORE_TYPE_NONE:
> > +   case ANV_SEMAPHORE_TYPE_DUMMY:
> > +  /* Dummy.  Nothing to do */
> > +  break;
> > +
> > +   case ANV_SEMAPHORE_TYPE_BO:
> > +  anv_bo_cache_release(device, >bo_cache, impl->bo);
> > +  break;
> > +
> > +   default:
> > +  unreachable("Invalid semaphore type");
> > +   }
>
> This switch statement is a good candidate for exhaustive switch warnings
> (-Wswitch).  But we don't get the warnings unless the default is dropped
> and the unreachable is moved to after the switch statement.
>

Sure, I can do that.


> > +}
>
> [snip]
>
> >
> > @@ -548,9 +609,73 @@ void anv_GetPhysicalDeviceExternalSemap
> horePropertiesKHX(
> >  VkExternalSemaphorePropertiesKHX*
>  pExternalSemaphoreProperties)
> >  {
> > switch (pExternalSemaphoreInfo->handleType) {
> > +   case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHX:
> > +  pExternalSemaphoreProperties->exportFromImportedHandleTypes = 0;
>
> I expected exportFromImportedHandleTypes to be
> VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHX.  Why is it 0?
> I admit I don't fully 

Re: [Mesa-dev] [PATCH 16/21] anv: Implement VK_KHX_external_semaphore_fd

2017-05-02 Thread Chad Versace
On Fri 14 Apr 2017, Jason Ekstrand wrote:
> This implementation allocates a 4k BO for each semaphore that can be
> exported using OPAQUE_FD and uses the kernel's already-existing
> synchronization mechanism on BOs.
> ---
>  src/intel/vulkan/anv_batch_chain.c  |  53 ++--
>  src/intel/vulkan/anv_device.c   |   4 +
>  src/intel/vulkan/anv_entrypoints_gen.py |   1 +
>  src/intel/vulkan/anv_private.h  |  16 +++-
>  src/intel/vulkan/anv_queue.c| 141 
> ++--
>  5 files changed, 199 insertions(+), 16 deletions(-)

[snip]

> @@ -513,14 +533,33 @@ VkResult anv_CreateSemaphore(
>  VkExternalSemaphoreHandleTypeFlagsKHX handleTypes =
>export ? export->handleTypes : 0;
>  
> -   /* External semaphores are not yet supported */
> -   assert(handleTypes == 0);
> +   if (handleTypes == 0) {
> +  /* The DRM execbuffer ioctl always execute in-oder so long as you stay
> +   * on the same ring.  Since we don't expose the blit engine as a DMA
> +   * queue, a dummy no-op semaphore is a perfectly valid implementation.
> +   */
> +  semaphore->permanent.type = ANV_SEMAPHORE_TYPE_DUMMY;
> +   } else if (handleTypes & 
> VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHX) {
> +  assert(handleTypes == 
> VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHX);
> +
> +  semaphore->permanent.type = ANV_SEMAPHORE_TYPE_BO;
> +  VkResult result = anv_bo_cache_alloc(device, >bo_cache,
> +   4096, >permanent.bo);
> +  if (result != VK_SUCCESS) {
> + vk_free2(>alloc, pAllocator, semaphore);
> + return result;
> +  }
> +
> +  /* If we're going to use this as a fence, we need to *not* have the
> +   * EXEC_OBJECT_ASYNC bit set.
> +   */
> +  semaphore->permanent.bo->flags &= ~EXEC_OBJECT_ASYNC;
> +   } else {
> +  assert(!"Unknown handle type");
> +  vk_free2(>alloc, pAllocator, semaphore);
> +  return vk_error(VK_ERROR_INVALID_EXTERNAL_HANDLE_KHX);

The Vulkan 1.0.49 spec does not list
VK_ERROR_INVALID_EXTERNAL_HANDLE_KHX as a possible error code for
vkCreateSemaphore. The reason is that
VK_ERROR_INVALID_EXTERNAL_HANDLE_KHX indicates that an external handle
does not match the expected handle type. Since vkCreateSemaphore has no
parameter that's an external handle, it can't return the error.
VK_ERROR_INVALID_EXTERNAL_HANDLE_KHX only makes sense for functions that
import a handle or query the properties of a handle.

This 'else' branch is capturing invalid application usage the API. Since
invalid usages leads to undefined behavior, we could claim that Mesa's
undefined behavior is to return a helpful error code. But...

I much prefer disastrous undefined behavior here instead of helpful
undefined behavior. If we return VK_ERROR_INVALID_EXTERNAL_HANDLE_KHX,
then appsy may accidentally rely on our out-of-spec behavior. It would
be better to just abort() or, like anvil does in most cases, silently
ignore the invalid case and continue blindly ahead.

[snip]

> +static void
> +anv_semaphore_impl_cleanup(struct anv_device *device,
> +   struct anv_semaphore_impl *impl)
> +{
> +   switch (impl->type) {
> +   case ANV_SEMAPHORE_TYPE_NONE:
> +   case ANV_SEMAPHORE_TYPE_DUMMY:
> +  /* Dummy.  Nothing to do */
> +  break;
> +
> +   case ANV_SEMAPHORE_TYPE_BO:
> +  anv_bo_cache_release(device, >bo_cache, impl->bo);
> +  break;
> +
> +   default:
> +  unreachable("Invalid semaphore type");
> +   }

This switch statement is a good candidate for exhaustive switch warnings
(-Wswitch).  But we don't get the warnings unless the default is dropped
and the unreachable is moved to after the switch statement.

> +}

[snip]

>  
> @@ -548,9 +609,73 @@ void anv_GetPhysicalDeviceExternalSemaphorePropertiesKHX(
>  VkExternalSemaphorePropertiesKHX*   pExternalSemaphoreProperties)
>  {
> switch (pExternalSemaphoreInfo->handleType) {
> +   case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHX:
> +  pExternalSemaphoreProperties->exportFromImportedHandleTypes = 0;

I expected exportFromImportedHandleTypes to be
VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHX.  Why is it 0?
I admit I don't fully understand the VK_KHX_external_semaphore spec. (To
be fair, I doubt anyone fully understands it).

> +  pExternalSemaphoreProperties->compatibleHandleTypes =
> + VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHX;
> +  pExternalSemaphoreProperties->externalSemaphoreFeatures =
> + VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT_KHX |
> + VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT_KHX;
> +  break;
> +
> default:
>pExternalSemaphoreProperties->exportFromImportedHandleTypes = 0;
>pExternalSemaphoreProperties->compatibleHandleTypes = 0;
>pExternalSemaphoreProperties->externalSemaphoreFeatures = 0;
> }
>  }
> +
> +VkResult anv_ImportSemaphoreFdKHX(
> +

[Mesa-dev] [PATCH 16/21] anv: Implement VK_KHX_external_semaphore_fd

2017-04-14 Thread Jason Ekstrand
This implementation allocates a 4k BO for each semaphore that can be
exported using OPAQUE_FD and uses the kernel's already-existing
synchronization mechanism on BOs.
---
 src/intel/vulkan/anv_batch_chain.c  |  53 ++--
 src/intel/vulkan/anv_device.c   |   4 +
 src/intel/vulkan/anv_entrypoints_gen.py |   1 +
 src/intel/vulkan/anv_private.h  |  16 +++-
 src/intel/vulkan/anv_queue.c| 141 ++--
 5 files changed, 199 insertions(+), 16 deletions(-)

diff --git a/src/intel/vulkan/anv_batch_chain.c 
b/src/intel/vulkan/anv_batch_chain.c
index 136f273..0529f22 100644
--- a/src/intel/vulkan/anv_batch_chain.c
+++ b/src/intel/vulkan/anv_batch_chain.c
@@ -982,6 +982,7 @@ static VkResult
 anv_execbuf_add_bo(struct anv_execbuf *exec,
struct anv_bo *bo,
struct anv_reloc_list *relocs,
+   uint32_t extra_flags,
const VkAllocationCallbacks *alloc)
 {
struct drm_i915_gem_exec_object2 *obj = NULL;
@@ -1036,7 +1037,7 @@ anv_execbuf_add_bo(struct anv_execbuf *exec,
   obj->relocs_ptr = 0;
   obj->alignment = 0;
   obj->offset = bo->offset;
-  obj->flags = bo->flags;
+  obj->flags = bo->flags | extra_flags;
   obj->rsvd1 = 0;
   obj->rsvd2 = 0;
}
@@ -1052,7 +1053,8 @@ anv_execbuf_add_bo(struct anv_execbuf *exec,
   for (size_t i = 0; i < relocs->num_relocs; i++) {
  /* A quick sanity check on relocations */
  assert(relocs->relocs[i].offset < bo->size);
- anv_execbuf_add_bo(exec, relocs->reloc_bos[i], NULL, alloc);
+ anv_execbuf_add_bo(exec, relocs->reloc_bos[i], NULL,
+extra_flags, alloc);
   }
}
 
@@ -1261,7 +1263,7 @@ setup_execbuf_for_cmd_buffer(struct anv_execbuf *execbuf,
adjust_relocations_from_state_pool(ss_pool, _buffer->surface_relocs,
   cmd_buffer->last_ss_pool_center);
VkResult result =
-  anv_execbuf_add_bo(execbuf, _pool->bo, _buffer->surface_relocs,
+  anv_execbuf_add_bo(execbuf, _pool->bo, _buffer->surface_relocs, 0,
  _buffer->device->alloc);
if (result != VK_SUCCESS)
   return result;
@@ -1274,7 +1276,7 @@ setup_execbuf_for_cmd_buffer(struct anv_execbuf *execbuf,
   adjust_relocations_to_state_pool(ss_pool, &(*bbo)->bo, &(*bbo)->relocs,
cmd_buffer->last_ss_pool_center);
 
-  result = anv_execbuf_add_bo(execbuf, &(*bbo)->bo, &(*bbo)->relocs,
+  result = anv_execbuf_add_bo(execbuf, &(*bbo)->bo, &(*bbo)->relocs, 0,
   _buffer->device->alloc);
   if (result != VK_SUCCESS)
  return result;
@@ -1387,12 +1389,51 @@ setup_execbuf_for_cmd_buffer(struct anv_execbuf 
*execbuf,
 
 VkResult
 anv_cmd_buffer_execbuf(struct anv_device *device,
-   struct anv_cmd_buffer *cmd_buffer)
+   struct anv_cmd_buffer *cmd_buffer,
+   const VkSemaphore *in_semaphores,
+   uint32_t num_in_semaphores,
+   const VkSemaphore *out_semaphores,
+   uint32_t num_out_semaphores)
 {
struct anv_execbuf execbuf;
anv_execbuf_init();
 
-   VkResult result = setup_execbuf_for_cmd_buffer(, cmd_buffer);
+   VkResult result = VK_SUCCESS;
+   for (uint32_t i = 0; i < num_in_semaphores; i++) {
+  ANV_FROM_HANDLE(anv_semaphore, semaphore, in_semaphores[i]);
+  assert(semaphore->temporary.type == ANV_SEMAPHORE_TYPE_NONE);
+  struct anv_semaphore_impl *impl = >permanent;
+
+  switch (impl->type) {
+  case ANV_SEMAPHORE_TYPE_BO:
+ result = anv_execbuf_add_bo(, impl->bo, NULL,
+ 0, >alloc);
+ if (result != VK_SUCCESS)
+return result;
+ break;
+  default:
+ break;
+  }
+   }
+
+   for (uint32_t i = 0; i < num_out_semaphores; i++) {
+  ANV_FROM_HANDLE(anv_semaphore, semaphore, out_semaphores[i]);
+  assert(semaphore->temporary.type == ANV_SEMAPHORE_TYPE_NONE);
+  struct anv_semaphore_impl *impl = >permanent;
+
+  switch (impl->type) {
+  case ANV_SEMAPHORE_TYPE_BO:
+ result = anv_execbuf_add_bo(, impl->bo, NULL,
+ EXEC_OBJECT_WRITE, >alloc);
+ if (result != VK_SUCCESS)
+return result;
+ break;
+  default:
+ break;
+  }
+   }
+
+   result = setup_execbuf_for_cmd_buffer(, cmd_buffer);
if (result != VK_SUCCESS)
   return result;
 
diff --git a/src/intel/vulkan/anv_device.c b/src/intel/vulkan/anv_device.c
index b85cd40..f6e77ab 100644
--- a/src/intel/vulkan/anv_device.c
+++ b/src/intel/vulkan/anv_device.c
@@ -378,6 +378,10 @@ static const VkExtensionProperties device_extensions[] = {
   .extensionName = VK_KHX_EXTERNAL_SEMAPHORE_EXTENSION_NAME,
   .specVersion = 1,
},
+   {
+