bool has_client_visible_address:1;
};
+static inline struct anv_bo *
+anv_bo_ref(struct anv_bo *bo)
+{
+ p_atomic_inc(&bo->refcount);
+ return bo;
+}
+
static inline struct anv_bo *
anv_bo_unwrap(struct anv_bo *bo)
{
enum anv_fence_type {
ANV_FENCE_TYPE_NONE = 0,
ANV_FENCE_TYPE_BO,
+ ANV_FENCE_TYPE_WSI_BO,
ANV_FENCE_TYPE_SYNCOBJ,
ANV_FENCE_TYPE_WSI,
};
ANV_SEMAPHORE_TYPE_NONE = 0,
ANV_SEMAPHORE_TYPE_DUMMY,
ANV_SEMAPHORE_TYPE_BO,
+ ANV_SEMAPHORE_TYPE_WSI_BO,
ANV_SEMAPHORE_TYPE_SYNC_FILE,
ANV_SEMAPHORE_TYPE_DRM_SYNCOBJ,
ANV_SEMAPHORE_TYPE_TIMELINE,
enum anv_semaphore_type type;
union {
- /* A BO representing this semaphore when type == ANV_SEMAPHORE_TYPE_BO.
- * This BO will be added to the object list on any execbuf2 calls for
- * which this semaphore is used as a wait or signal fence. When used as
- * a signal fence, the EXEC_OBJECT_WRITE flag will be set.
+ /* A BO representing this semaphore when type == ANV_SEMAPHORE_TYPE_BO
+ * or type == ANV_SEMAPHORE_TYPE_WSI_BO. This BO will be added to the
+ * object list on any execbuf2 calls for which this semaphore is used as
+ * a wait or signal fence. When used as a signal fence or when type ==
+ * ANV_SEMAPHORE_TYPE_WSI_BO, the EXEC_OBJECT_WRITE flag will be set.
*/
struct anv_bo *bo;
goto error;
break;
+ case ANV_SEMAPHORE_TYPE_WSI_BO:
+ /* When using a window-system buffer as a semaphore, always enable
+ * EXEC_OBJECT_WRITE. This gives us a WaR hazard with the display or
+ * compositor's read of the buffer and enforces that we don't start
+ * rendering until they are finished. This is exactly the
+ * synchronization we want with vkAcquireNextImage.
+ */
+ result = anv_queue_submit_add_fence_bo(submit, impl->bo, true /* signal */);
+ if (result != VK_SUCCESS)
+ goto error;
+ break;
+
case ANV_SEMAPHORE_TYPE_SYNC_FILE:
assert(!pdevice->has_syncobj);
if (submit->in_fence == -1) {
anv_bo_pool_free(&device->batch_bo_pool, impl->bo.bo);
break;
+ case ANV_FENCE_TYPE_WSI_BO:
+ anv_device_release_bo(device, impl->bo.bo);
+ break;
+
case ANV_FENCE_TYPE_SYNCOBJ:
anv_gem_syncobj_destroy(device, impl->syncobj);
break;
switch (impl->type) {
case ANV_FENCE_TYPE_BO:
+ case ANV_FENCE_TYPE_WSI_BO:
/* BO fences don't support import/export */
assert(fence->temporary.type == ANV_FENCE_TYPE_NONE);
switch (impl->bo.state) {
for (uint32_t i = 0; i < fenceCount; i++) {
ANV_FROM_HANDLE(anv_fence, fence, pFences[i]);
- /* This function assumes that all fences are BO fences and that they
- * have no temporary state. Since BO fences will never be exported,
- * this should be a safe assumption.
- */
- assert(fence->permanent.type == ANV_FENCE_TYPE_BO);
- assert(fence->temporary.type == ANV_FENCE_TYPE_NONE);
- struct anv_fence_impl *impl = &fence->permanent;
+ struct anv_fence_impl *impl =
+ fence->temporary.type != ANV_FENCE_TYPE_NONE ?
+ &fence->temporary : &fence->permanent;
+ assert(impl->type == ANV_FENCE_TYPE_BO ||
+ impl->type == ANV_FENCE_TYPE_WSI_BO);
switch (impl->bo.state) {
case ANV_BO_FENCE_STATE_RESET:
ANV_FROM_HANDLE(anv_fence, fence, pFences[i]);
switch (fence->permanent.type) {
case ANV_FENCE_TYPE_BO:
+ case ANV_FENCE_TYPE_WSI_BO:
result = anv_wait_for_bo_fences(device, 1, &pFences[i],
true, abs_timeout);
break;
break;
case ANV_SEMAPHORE_TYPE_BO:
+ case ANV_SEMAPHORE_TYPE_WSI_BO:
anv_device_release_bo(device, impl->bo);
break;
return image->drm_format_mod;
}
+static void
+anv_wsi_signal_semaphore_for_memory(VkDevice _device,
+ VkSemaphore _semaphore,
+ VkDeviceMemory _memory)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ ANV_FROM_HANDLE(anv_semaphore, semaphore, _semaphore);
+ ANV_FROM_HANDLE(anv_device_memory, memory, _memory);
+
+ /* Put a BO semaphore with the image BO in the temporary. For BO binary
+ * semaphores, we always set EXEC_OBJECT_WRITE so this creates a WaR
+ * hazard with the display engine's read to ensure that no one writes to
+ * the image before the read is complete.
+ */
+ anv_semaphore_reset_temporary(device, semaphore);
+
+ struct anv_semaphore_impl *impl = &semaphore->temporary;
+ impl->type = ANV_SEMAPHORE_TYPE_WSI_BO;
+ impl->bo = anv_bo_ref(memory->bo);
+}
+
+static void
+anv_wsi_signal_fence_for_memory(VkDevice _device,
+ VkFence _fence,
+ VkDeviceMemory _memory)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ ANV_FROM_HANDLE(anv_fence, fence, _fence);
+ ANV_FROM_HANDLE(anv_device_memory, memory, _memory);
+
+ /* Put a BO fence with the image BO in the temporary. For BO fences, we
+ * always just wait until the BO isn't busy and reads from the BO should
+ * count as busy.
+ */
+ anv_fence_reset_temporary(device, fence);
+
+ struct anv_fence_impl *impl = &fence->temporary;
+ impl->type = ANV_FENCE_TYPE_WSI_BO;
+ impl->bo.bo = anv_bo_ref(memory->bo);
+ impl->bo.state = ANV_BO_FENCE_STATE_SUBMITTED;
+}
+
VkResult
anv_init_wsi(struct anv_physical_device *physical_device)
{
physical_device->wsi_device.supports_modifiers = true;
physical_device->wsi_device.image_get_modifier = anv_wsi_image_get_modifier;
+ physical_device->wsi_device.signal_semaphore_for_memory =
+ anv_wsi_signal_semaphore_for_memory;
+ physical_device->wsi_device.signal_fence_for_memory =
+ anv_wsi_signal_fence_for_memory;
return VK_SUCCESS;
}
ANV_FROM_HANDLE(anv_device, device, _device);
struct anv_physical_device *pdevice = &device->instance->physicalDevice;
- VkResult result = wsi_common_acquire_next_image2(&pdevice->wsi_device,
- _device,
- pAcquireInfo,
- pImageIndex);
-
- /* Thanks to implicit sync, the image is ready immediately. However, we
- * should wait for the current GPU state to finish. Regardless of the
- * result of the presentation, we need to signal the semaphore & fence.
- */
-
- if (pAcquireInfo->semaphore != VK_NULL_HANDLE) {
- /* Put a dummy semaphore in temporary, this is the fastest way to avoid
- * any kind of work yet still provide some kind of synchronization. This
- * only works because the Mesa WSI code always returns an image
- * immediately if available.
- */
- ANV_FROM_HANDLE(anv_semaphore, semaphore, pAcquireInfo->semaphore);
- anv_semaphore_reset_temporary(device, semaphore);
-
- struct anv_semaphore_impl *impl = &semaphore->temporary;
-
- impl->type = ANV_SEMAPHORE_TYPE_DUMMY;
- }
-
- if (pAcquireInfo->fence != VK_NULL_HANDLE) {
- result = anv_QueueSubmit(anv_queue_to_handle(&device->queue),
- 0, NULL, pAcquireInfo->fence);
- }
-
- return result;
+ return wsi_common_acquire_next_image2(&pdevice->wsi_device, _device,
+ pAcquireInfo, pImageIndex);
}
VkResult anv_QueuePresentKHR(