2016-11-23 6:28 GMT+01:00 Dave Airlie <airl...@gmail.com>: > From: Dave Airlie <airl...@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. >
I might not be that much familiar with Vulkan, but I believe you can specify the transfer queue as a present queue and then the Vulkan applications would be required to perform the present operation on this queue. Wouldn't that be enough for the prime to work? Regards, Gustaw > > 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 <airl...@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_GetPhysicalDeviceSurfacePresen > tModesKHR( > 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@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/mesa-dev >
_______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev