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