<div dir="ltr">I think it would be good to keep the DRI_PRIME switch to allow for switching between anvil and radv, handy for testing / comparing / benchmarking both<div><br></div><div>It seems that Vulkan automatically uses the first card listed in vulkaninfo (in my case it's the amdgpu card) with no way to select which is used, hence why I've only been seeing garbage since the radv driver was added into mesa</div><div><br></div><div>If DRI_PRIME=0 is passed will this now automatically use anvil?</div><div><br></div><div>Thanks</div><div><br></div><div>Mike</div></div><br><div class="gmail_quote"><div dir="ltr">On Wed, 23 Nov 2016 at 10:47 Nicolai Hähnle <<a href="mailto:nhaehnle@gmail.com">nhaehnle@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">On 23.11.2016 06:28, Dave Airlie wrote:<br class="gmail_msg">
> 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">
Why is there a problem here? What stops you from just having multiple<br class="gmail_msg">
SDMA queues?<br class="gmail_msg">
<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">
So I'm not too deep into Vulkan, but isn't conceptually the blit to<br class="gmail_msg">
shadow image a part of the present operation, not of the image<br class="gmail_msg">
transition? I'd somehow expect the present part to have its own queue<br class="gmail_msg">
(which could be SDMA) on which the blit happens.<br class="gmail_msg">
<br class="gmail_msg">
Cheers,<br class="gmail_msg">
Nicolai<br class="gmail_msg">
<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">
_______________________________________________<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>