<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>