<div dir="ltr">You are a star :D<div><br></div><div>I'll test this out tonight<br><br><div class="gmail_quote"><div dir="ltr">On Wed, 23 Nov 2016 at 05:29 Dave Airlie <<a href="mailto:airlied@gmail.com">airlied@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">From: Dave Airlie <<a href="mailto:airlied@redhat.com" class="gmail_msg" target="_blank">airlied@redhat.com</a>><br class="gmail_msg">
<br class="gmail_msg">
This is kind of a gross hacks, but vulkan doesn't specify anything<br class="gmail_msg">
but it would be nice to let people with prime systems at least<br class="gmail_msg">
see some stuff rendering for now.<br class="gmail_msg">
<br class="gmail_msg">
This creates a linear shadow image in GART that gets blitted to at the<br class="gmail_msg">
image transition.<br class="gmail_msg">
<br class="gmail_msg">
Now ideally:<br class="gmail_msg">
this would use SDMA - but we want to use SDMA for transfer queues<br class="gmail_msg">
maybe we don't expose a transfer queue on prime cards who knows.<br class="gmail_msg">
<br class="gmail_msg">
we wouldn't have to add two pointers to every image, but my other<br class="gmail_msg">
attempts at this were ugly.<br class="gmail_msg">
<br class="gmail_msg">
Is the image transition the proper place to hack this in? not<br class="gmail_msg">
really sure anywhere else is appropriate.<br class="gmail_msg">
<br class="gmail_msg">
It also relies on DRI_PRIME=1 being set, I should be able<br class="gmail_msg">
to work this out somehow automatically I think, probably getting<br class="gmail_msg">
a DRI3 fd from the X server and doing drmGetDevice on it, and<br class="gmail_msg">
comparing where we end up.<br class="gmail_msg">
<br class="gmail_msg">
Signed-off-by: Dave Airlie <<a href="mailto:airlied@redhat.com" class="gmail_msg" target="_blank">airlied@redhat.com</a>><br class="gmail_msg">
---<br class="gmail_msg">
 src/amd/vulkan/radv_cmd_buffer.c |  18 +++++++<br class="gmail_msg">
 src/amd/vulkan/radv_device.c     |   3 ++<br class="gmail_msg">
 src/amd/vulkan/radv_meta.h       |   2 +<br class="gmail_msg">
 src/amd/vulkan/radv_meta_copy.c  |  31 +++++++++++<br class="gmail_msg">
 src/amd/vulkan/radv_private.h    |   4 ++<br class="gmail_msg">
 src/amd/vulkan/radv_wsi.c        | 111 ++++++++++++++++++++++++++++++---------<br class="gmail_msg">
 6 files changed, 144 insertions(+), 25 deletions(-)<br class="gmail_msg">
<br class="gmail_msg">
diff --git a/src/amd/vulkan/radv_cmd_buffer.c b/src/amd/vulkan/radv_cmd_buffer.c<br class="gmail_msg">
index a2d55833..4432afc 100644<br class="gmail_msg">
--- a/src/amd/vulkan/radv_cmd_buffer.c<br class="gmail_msg">
+++ b/src/amd/vulkan/radv_cmd_buffer.c<br class="gmail_msg">
@@ -2296,6 +2296,20 @@ static void radv_handle_dcc_image_transition(struct radv_cmd_buffer *cmd_buffer,<br class="gmail_msg">
        }<br class="gmail_msg">
 }<br class="gmail_msg">
<br class="gmail_msg">
+static void radv_handle_prime_image_transition(struct radv_cmd_buffer *cmd_buffer,<br class="gmail_msg">
+                                              struct radv_image *image,<br class="gmail_msg">
+                                              VkImageLayout src_layout,<br class="gmail_msg">
+                                              VkImageLayout dst_layout,<br class="gmail_msg">
+                                              VkImageSubresourceRange range,<br class="gmail_msg">
+                                              VkImageAspectFlags pending_clears)<br class="gmail_msg">
+{<br class="gmail_msg">
+       cmd_buffer->state.flush_bits |= RADV_CMD_FLUSH_AND_INV_FRAMEBUFFER;<br class="gmail_msg">
+       si_emit_cache_flush(cmd_buffer);<br class="gmail_msg">
+       radv_blit_to_prime_linear(cmd_buffer, image);<br class="gmail_msg">
+       cmd_buffer->state.flush_bits |= RADV_CMD_FLUSH_AND_INV_FRAMEBUFFER;<br class="gmail_msg">
+       si_emit_cache_flush(cmd_buffer);<br class="gmail_msg">
+}<br class="gmail_msg">
+<br class="gmail_msg">
 static void radv_handle_image_transition(struct radv_cmd_buffer *cmd_buffer,<br class="gmail_msg">
                                         struct radv_image *image,<br class="gmail_msg">
                                         VkImageLayout src_layout,<br class="gmail_msg">
@@ -2314,6 +2328,10 @@ static void radv_handle_image_transition(struct radv_cmd_buffer *cmd_buffer,<br class="gmail_msg">
        if (image->surface.dcc_size)<br class="gmail_msg">
                radv_handle_dcc_image_transition(cmd_buffer, image, src_layout,<br class="gmail_msg">
                                                 dst_layout, range, pending_clears);<br class="gmail_msg">
+<br class="gmail_msg">
+       if (image->prime_image && dst_layout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)<br class="gmail_msg">
+               radv_handle_prime_image_transition(cmd_buffer, image, src_layout,<br class="gmail_msg">
+                                                  dst_layout, range, pending_clears);<br class="gmail_msg">
 }<br class="gmail_msg">
<br class="gmail_msg">
 void radv_CmdPipelineBarrier(<br class="gmail_msg">
diff --git a/src/amd/vulkan/radv_device.c b/src/amd/vulkan/radv_device.c<br class="gmail_msg">
index c639d53..b21447f 100644<br class="gmail_msg">
--- a/src/amd/vulkan/radv_device.c<br class="gmail_msg">
+++ b/src/amd/vulkan/radv_device.c<br class="gmail_msg">
@@ -105,6 +105,9 @@ radv_physical_device_init(struct radv_physical_device *device,<br class="gmail_msg">
        }<br class="gmail_msg">
        drmFreeVersion(version);<br class="gmail_msg">
<br class="gmail_msg">
+       if (getenv("DRI_PRIME"))<br class="gmail_msg">
+               device->is_different_gpu = true;<br class="gmail_msg">
+<br class="gmail_msg">
        device->_loader_data.loaderMagic = ICD_LOADER_MAGIC;<br class="gmail_msg">
        device->instance = instance;<br class="gmail_msg">
        assert(strlen(path) < ARRAY_SIZE(device->path));<br class="gmail_msg">
diff --git a/src/amd/vulkan/radv_meta.h b/src/amd/vulkan/radv_meta.h<br class="gmail_msg">
index 97d020c..e43a0e7 100644<br class="gmail_msg">
--- a/src/amd/vulkan/radv_meta.h<br class="gmail_msg">
+++ b/src/amd/vulkan/radv_meta.h<br class="gmail_msg">
@@ -186,6 +186,8 @@ void radv_meta_resolve_compute_image(struct radv_cmd_buffer *cmd_buffer,<br class="gmail_msg">
                                     uint32_t region_count,<br class="gmail_msg">
                                     const VkImageResolve *regions);<br class="gmail_msg">
<br class="gmail_msg">
+void radv_blit_to_prime_linear(struct radv_cmd_buffer *cmd_buffer,<br class="gmail_msg">
+                              struct radv_image *image);<br class="gmail_msg">
 #ifdef __cplusplus<br class="gmail_msg">
 }<br class="gmail_msg">
 #endif<br class="gmail_msg">
diff --git a/src/amd/vulkan/radv_meta_copy.c b/src/amd/vulkan/radv_meta_copy.c<br class="gmail_msg">
index 4c01eb7..3fd8d0c 100644<br class="gmail_msg">
--- a/src/amd/vulkan/radv_meta_copy.c<br class="gmail_msg">
+++ b/src/amd/vulkan/radv_meta_copy.c<br class="gmail_msg">
@@ -397,3 +397,34 @@ void radv_CmdCopyImage(<br class="gmail_msg">
<br class="gmail_msg">
        radv_meta_restore(&saved_state, cmd_buffer);<br class="gmail_msg">
 }<br class="gmail_msg">
+<br class="gmail_msg">
+void radv_blit_to_prime_linear(struct radv_cmd_buffer *cmd_buffer,<br class="gmail_msg">
+                              struct radv_image *image)<br class="gmail_msg">
+{<br class="gmail_msg">
+       struct radv_meta_saved_state saved_state;<br class="gmail_msg">
+       struct radv_meta_saved_pass_state saved_pass_state;<br class="gmail_msg">
+<br class="gmail_msg">
+       radv_meta_save_pass(&saved_pass_state, cmd_buffer);<br class="gmail_msg">
+       radv_meta_save_graphics_reset_vport_scissor(&saved_state, cmd_buffer);<br class="gmail_msg">
+<br class="gmail_msg">
+       struct radv_meta_blit2d_surf b_src =<br class="gmail_msg">
+               blit_surf_for_image_level_layer(image,<br class="gmail_msg">
+                                               VK_IMAGE_ASPECT_COLOR_BIT,<br class="gmail_msg">
+                                               0,<br class="gmail_msg">
+                                               0);<br class="gmail_msg">
+<br class="gmail_msg">
+       struct radv_meta_blit2d_surf b_dst =<br class="gmail_msg">
+               blit_surf_for_image_level_layer(image->prime_image,<br class="gmail_msg">
+                                               VK_IMAGE_ASPECT_COLOR_BIT,<br class="gmail_msg">
+                                               0,<br class="gmail_msg">
+                                               0);<br class="gmail_msg">
+       struct radv_meta_blit2d_rect rect = {<br class="gmail_msg">
+               .width = image->extent.width,<br class="gmail_msg">
+               .height = image->extent.height,<br class="gmail_msg">
+       };<br class="gmail_msg">
+<br class="gmail_msg">
+       radv_meta_blit2d(cmd_buffer, &b_src, NULL, &b_dst, 1, &rect);<br class="gmail_msg">
+<br class="gmail_msg">
+       radv_meta_restore(&saved_state, cmd_buffer);<br class="gmail_msg">
+       radv_meta_restore_pass(&saved_pass_state, cmd_buffer);<br class="gmail_msg">
+}<br class="gmail_msg">
diff --git a/src/amd/vulkan/radv_private.h b/src/amd/vulkan/radv_private.h<br class="gmail_msg">
index e1c24cb..5027431 100644<br class="gmail_msg">
--- a/src/amd/vulkan/radv_private.h<br class="gmail_msg">
+++ b/src/amd/vulkan/radv_private.h<br class="gmail_msg">
@@ -261,6 +261,7 @@ struct radv_physical_device {<br class="gmail_msg">
        uint8_t                                     uuid[VK_UUID_SIZE];<br class="gmail_msg">
<br class="gmail_msg">
        struct wsi_device                       wsi_device;<br class="gmail_msg">
+       bool is_different_gpu;<br class="gmail_msg">
 };<br class="gmail_msg">
<br class="gmail_msg">
 struct radv_instance {<br class="gmail_msg">
@@ -987,6 +988,9 @@ struct radv_image {<br class="gmail_msg">
<br class="gmail_msg">
        /* Depth buffer compression and fast clear. */<br class="gmail_msg">
        struct r600_htile_info htile;<br class="gmail_msg">
+<br class="gmail_msg">
+       struct radv_image *prime_image;<br class="gmail_msg">
+       struct radv_device_memory *prime_memory;<br class="gmail_msg">
 };<br class="gmail_msg">
<br class="gmail_msg">
 bool radv_layout_has_htile(const struct radv_image *image,<br class="gmail_msg">
diff --git a/src/amd/vulkan/radv_wsi.c b/src/amd/vulkan/radv_wsi.c<br class="gmail_msg">
index 1f1ab1c..31aeb77 100644<br class="gmail_msg">
--- a/src/amd/vulkan/radv_wsi.c<br class="gmail_msg">
+++ b/src/amd/vulkan/radv_wsi.c<br class="gmail_msg">
@@ -135,23 +135,27 @@ VkResult radv_GetPhysicalDeviceSurfacePresentModesKHR(<br class="gmail_msg">
                                        pPresentModes);<br class="gmail_msg">
 }<br class="gmail_msg">
<br class="gmail_msg">
+static void<br class="gmail_msg">
+radv_wsi_image_destroy_single(VkDevice device_h,<br class="gmail_msg">
+                             const VkAllocationCallbacks* pAllocator,<br class="gmail_msg">
+                             VkImage image_h,<br class="gmail_msg">
+                             VkDeviceMemory memory_h)<br class="gmail_msg">
+{<br class="gmail_msg">
+       radv_DestroyImage(device_h, image_h, pAllocator);<br class="gmail_msg">
+       radv_FreeMemory(device_h, memory_h, pAllocator);<br class="gmail_msg">
+}<br class="gmail_msg">
+<br class="gmail_msg">
 static VkResult<br class="gmail_msg">
-radv_wsi_image_create(VkDevice device_h,<br class="gmail_msg">
-                     const VkSwapchainCreateInfoKHR *pCreateInfo,<br class="gmail_msg">
-                     const VkAllocationCallbacks* pAllocator,<br class="gmail_msg">
-                     VkImage *image_p,<br class="gmail_msg">
-                     VkDeviceMemory *memory_p,<br class="gmail_msg">
-                     uint32_t *size,<br class="gmail_msg">
-                     uint32_t *offset,<br class="gmail_msg">
-                     uint32_t *row_pitch, int *fd_p)<br class="gmail_msg">
+radv_wsi_image_create_single(VkDevice device_h,<br class="gmail_msg">
+                            const VkSwapchainCreateInfoKHR *pCreateInfo,<br class="gmail_msg">
+                            const VkAllocationCallbacks* pAllocator,<br class="gmail_msg">
+                            VkImage *image_p,<br class="gmail_msg">
+                            VkDeviceMemory *memory_p,<br class="gmail_msg">
+                            bool tiled)<br class="gmail_msg">
 {<br class="gmail_msg">
-       struct radv_device *device = radv_device_from_handle(device_h);<br class="gmail_msg">
-       VkResult result = VK_SUCCESS;<br class="gmail_msg">
-       struct radeon_surf *surface;<br class="gmail_msg">
+       VkResult result;<br class="gmail_msg">
        VkImage image_h;<br class="gmail_msg">
        struct radv_image *image;<br class="gmail_msg">
-       bool bret;<br class="gmail_msg">
-       int fd;<br class="gmail_msg">
<br class="gmail_msg">
        result = radv_image_create(device_h,<br class="gmail_msg">
                                   &(struct radv_image_create_info) {<br class="gmail_msg">
@@ -169,7 +173,7 @@ radv_wsi_image_create(VkDevice device_h,<br class="gmail_msg">
                                                   .arrayLayers = 1,<br class="gmail_msg">
                                                   .samples = 1,<br class="gmail_msg">
                                                   /* FIXME: Need a way to use X tiling to allow scanout */<br class="gmail_msg">
-                                                  .tiling = VK_IMAGE_TILING_OPTIMAL,<br class="gmail_msg">
+                                                  .tiling = tiled ? VK_IMAGE_TILING_OPTIMAL : VK_IMAGE_TILING_LINEAR,<br class="gmail_msg">
                                                   .usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,<br class="gmail_msg">
                                                   .flags = 0,<br class="gmail_msg">
                                           },<br class="gmail_msg">
@@ -180,24 +184,74 @@ radv_wsi_image_create(VkDevice device_h,<br class="gmail_msg">
                return result;<br class="gmail_msg">
<br class="gmail_msg">
        image = radv_image_from_handle(image_h);<br class="gmail_msg">
-<br class="gmail_msg">
        VkDeviceMemory memory_h;<br class="gmail_msg">
-       struct radv_device_memory *memory;<br class="gmail_msg">
+<br class="gmail_msg">
        result = radv_AllocateMemory(device_h,<br class="gmail_msg">
                                     &(VkMemoryAllocateInfo) {<br class="gmail_msg">
                                             .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,<br class="gmail_msg">
                                                     .allocationSize = image->size,<br class="gmail_msg">
-                                                    .memoryTypeIndex = 0,<br class="gmail_msg">
+                                                    .memoryTypeIndex = tiled ? 0 : 1,<br class="gmail_msg">
                                                     },<br class="gmail_msg">
                                     NULL /* XXX: pAllocator */,<br class="gmail_msg">
                                     &memory_h);<br class="gmail_msg">
        if (result != VK_SUCCESS)<br class="gmail_msg">
                goto fail_create_image;<br class="gmail_msg">
<br class="gmail_msg">
-       memory = radv_device_memory_from_handle(memory_h);<br class="gmail_msg">
-<br class="gmail_msg">
        radv_BindImageMemory(VK_NULL_HANDLE, image_h, memory_h, 0);<br class="gmail_msg">
<br class="gmail_msg">
+       *image_p = image_h;<br class="gmail_msg">
+       *memory_p = memory_h;<br class="gmail_msg">
+       return VK_SUCCESS;<br class="gmail_msg">
+fail_create_image:<br class="gmail_msg">
+       radv_DestroyImage(device_h, image_h, pAllocator);<br class="gmail_msg">
+       return result;<br class="gmail_msg">
+}<br class="gmail_msg">
+<br class="gmail_msg">
+static VkResult<br class="gmail_msg">
+radv_wsi_image_create(VkDevice device_h,<br class="gmail_msg">
+                     const VkSwapchainCreateInfoKHR *pCreateInfo,<br class="gmail_msg">
+                     const VkAllocationCallbacks* pAllocator,<br class="gmail_msg">
+                     VkImage *image_p,<br class="gmail_msg">
+                     VkDeviceMemory *memory_p,<br class="gmail_msg">
+                     uint32_t *size,<br class="gmail_msg">
+                     uint32_t *offset,<br class="gmail_msg">
+                     uint32_t *row_pitch, int *fd_p)<br class="gmail_msg">
+{<br class="gmail_msg">
+       struct radv_device *device = radv_device_from_handle(device_h);<br class="gmail_msg">
+       VkResult result = VK_SUCCESS;<br class="gmail_msg">
+       struct radeon_surf *surface;<br class="gmail_msg">
+       VkImage image_h, image_prime_h;<br class="gmail_msg">
+       VkDeviceMemory memory_h, memory_prime_h;<br class="gmail_msg">
+       struct radv_image *image;<br class="gmail_msg">
+       struct radv_device_memory *memory;<br class="gmail_msg">
+       bool bret;<br class="gmail_msg">
+       int fd;<br class="gmail_msg">
+       bool prime = device->instance->physicalDevice.is_different_gpu;<br class="gmail_msg">
+<br class="gmail_msg">
+       result = radv_wsi_image_create_single(device_h, pCreateInfo,<br class="gmail_msg">
+                                             pAllocator, &image_h, &memory_h,<br class="gmail_msg">
+                                             true);<br class="gmail_msg">
+       if (result != VK_SUCCESS)<br class="gmail_msg">
+               return result;<br class="gmail_msg">
+<br class="gmail_msg">
+       image = radv_image_from_handle(image_h);<br class="gmail_msg">
+       if (prime) {<br class="gmail_msg">
+               result = radv_wsi_image_create_single(device_h, pCreateInfo,<br class="gmail_msg">
+                                                     pAllocator, &image_prime_h,<br class="gmail_msg">
+                                                     &memory_prime_h, false);<br class="gmail_msg">
+<br class="gmail_msg">
+               if (result != VK_SUCCESS)<br class="gmail_msg">
+                       goto fail_create_image;<br class="gmail_msg">
+<br class="gmail_msg">
+               image->prime_image = radv_image_from_handle(image_prime_h);<br class="gmail_msg">
+               image->prime_memory = radv_device_memory_from_handle(memory_prime_h);<br class="gmail_msg">
+<br class="gmail_msg">
+               memory = image->prime_memory;<br class="gmail_msg">
+               image = image->prime_image;<br class="gmail_msg">
+       } else {<br class="gmail_msg">
+               memory = radv_device_memory_from_handle(memory_h);<br class="gmail_msg">
+       }<br class="gmail_msg">
+<br class="gmail_msg">
        bret = device->ws->buffer_get_fd(device->ws,<br class="gmail_msg">
                                         memory->bo, &fd);<br class="gmail_msg">
        if (bret == false)<br class="gmail_msg">
@@ -217,24 +271,31 @@ radv_wsi_image_create(VkDevice device_h,<br class="gmail_msg">
        *offset = image->offset;<br class="gmail_msg">
        *row_pitch = surface->level[0].pitch_bytes;<br class="gmail_msg">
        return VK_SUCCESS;<br class="gmail_msg">
- fail_alloc_memory:<br class="gmail_msg">
-       radv_FreeMemory(device_h, memory_h, pAllocator);<br class="gmail_msg">
+<br class="gmail_msg">
+fail_alloc_memory:<br class="gmail_msg">
+       if (prime)<br class="gmail_msg">
+               radv_wsi_image_destroy_single(device_h, pAllocator, image_prime_h, memory_prime_h);<br class="gmail_msg">
<br class="gmail_msg">
 fail_create_image:<br class="gmail_msg">
-       radv_DestroyImage(device_h, image_h, pAllocator);<br class="gmail_msg">
+       radv_wsi_image_destroy_single(device_h, pAllocator, image_h, memory_h);<br class="gmail_msg">
<br class="gmail_msg">
        return result;<br class="gmail_msg">
 }<br class="gmail_msg">
<br class="gmail_msg">
 static void<br class="gmail_msg">
-radv_wsi_image_free(VkDevice device,<br class="gmail_msg">
+radv_wsi_image_free(VkDevice device_h,<br class="gmail_msg">
                    const VkAllocationCallbacks* pAllocator,<br class="gmail_msg">
                    VkImage image_h,<br class="gmail_msg">
                    VkDeviceMemory memory_h)<br class="gmail_msg">
 {<br class="gmail_msg">
-       radv_DestroyImage(device, image_h, pAllocator);<br class="gmail_msg">
+       RADV_FROM_HANDLE(radv_image, image, image_h);<br class="gmail_msg">
+<br class="gmail_msg">
+       if (image->prime_image)<br class="gmail_msg">
+               radv_wsi_image_destroy_single(device_h, pAllocator,<br class="gmail_msg">
+                                             radv_image_to_handle(image->prime_image),<br class="gmail_msg">
+                                             radv_device_memory_to_handle(image->prime_memory));<br class="gmail_msg">
<br class="gmail_msg">
-       radv_FreeMemory(device, memory_h, pAllocator);<br class="gmail_msg">
+       radv_wsi_image_destroy_single(device_h, pAllocator, image_h, memory_h);<br class="gmail_msg">
 }<br class="gmail_msg">
<br class="gmail_msg">
 static const struct wsi_image_fns radv_wsi_image_fns = {<br class="gmail_msg">
--<br class="gmail_msg">
2.9.3<br class="gmail_msg">
<br class="gmail_msg">
_______________________________________________<br class="gmail_msg">
mesa-dev mailing list<br class="gmail_msg">
<a href="mailto:mesa-dev@lists.freedesktop.org" class="gmail_msg" target="_blank">mesa-dev@lists.freedesktop.org</a><br class="gmail_msg">
<a href="https://lists.freedesktop.org/mailman/listinfo/mesa-dev" rel="noreferrer" class="gmail_msg" target="_blank">https://lists.freedesktop.org/mailman/listinfo/mesa-dev</a><br class="gmail_msg">
</blockquote></div></div></div>