[Mesa-dev] [RFC v4 20/23] vulkan/wsi: Add modifiers to wsi_image_create
Louis-Francis Ratté-Boulianne
lfrb at collabora.com
Mon Oct 16 07:04:30 UTC 2017
From: Daniel Stone <daniels at collabora.com>
Allow the winsys to provide a set of acceptable modifiers to the driver
when creating WSI images.
Signed-off-by: Daniel Stone <daniels at collabora.com>
---
src/amd/vulkan/radv_wsi.c | 36 +++++++++++++++++++++++++++++--
src/intel/vulkan/anv_image.c | 9 ++++++--
src/intel/vulkan/anv_private.h | 3 +++
src/intel/vulkan/anv_wsi.c | 42 ++++++++++++++++++++++++++++++++++---
src/vulkan/wsi/wsi_common.h | 3 +++
src/vulkan/wsi/wsi_common_wayland.c | 3 +++
src/vulkan/wsi/wsi_common_x11.c | 3 +++
7 files changed, 92 insertions(+), 7 deletions(-)
diff --git a/src/amd/vulkan/radv_wsi.c b/src/amd/vulkan/radv_wsi.c
index dd820dc431..31448ae981 100644
--- a/src/amd/vulkan/radv_wsi.c
+++ b/src/amd/vulkan/radv_wsi.c
@@ -226,11 +226,42 @@ radv_wsi_image_create(VkDevice device_h,
const VkSwapchainCreateInfoKHR *pCreateInfo,
const VkAllocationCallbacks* pAllocator,
bool different_gpu,
+ uint64_t **modifiers,
+ int *num_modifiers,
+ int num_tranches,
struct wsi_image_base *wsi_image)
{
VkResult result = VK_SUCCESS;
struct radeon_surf *surface;
struct radv_image *image;
+ bool linear;
+
+ /* If modifiers are provided, then try to use them. Unfortunately,
+ * as there are no modifiers actually defined for AMD, if we're
+ * provided with an explicit list of modifiers, then all we can do
+ * is try to use linear.
+ */
+ if (num_tranches == 0) {
+ linear = different_gpu;
+ } else {
+ bool linear_found = false;
+ for (int i = 0; i < num_tranches; i++) {
+ for (int j = 0; j < num_modifiers[i]; j++) {
+ if (modifiers[i][j] == DRM_FORMAT_MOD_LINEAR) {
+ linear = true;
+ linear_found = true;
+ break;
+ }
+ }
+ }
+
+ /* The right error is probably more like SURFACE_LOST, since
+ * we'll never be able to allocate for the surface with these
+ * attributes, but then we'd have to lose the surface.
+ */
+ if (!linear_found)
+ return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+ }
result = radv_wsi_image_alloc(device_h, pCreateInfo, pAllocator,
false, &wsi_image->image,
@@ -238,7 +269,7 @@ radv_wsi_image_create(VkDevice device_h,
if (result != VK_SUCCESS)
return result;
- if (different_gpu) {
+ if (linear) {
result = radv_wsi_image_alloc(device_h, pCreateInfo, pAllocator,
true, &wsi_image->linear_image,
&wsi_image->linear_memory);
@@ -260,7 +291,8 @@ radv_wsi_image_create(VkDevice device_h,
goto fail;
wsi_image->num_planes = 1;
- wsi_image->drm_modifier = DRM_FORMAT_MOD_INVALID;
+ wsi_image->drm_modifier =
+ linear ? DRM_FORMAT_MOD_LINEAR : DRM_FORMAT_MOD_INVALID;
wsi_image->sizes[0] = image->size;
wsi_image->offsets[0] = image->offset;
if (device->physical_device->rad_info.chip_class >= GFX9)
diff --git a/src/intel/vulkan/anv_image.c b/src/intel/vulkan/anv_image.c
index c8ebdce0b4..f266c7bc91 100644
--- a/src/intel/vulkan/anv_image.c
+++ b/src/intel/vulkan/anv_image.c
@@ -273,12 +273,16 @@ make_surface(const struct anv_device *dev,
/* Translate the Vulkan tiling to an equivalent ISL tiling, then filter the
* result with an optionally provided ISL tiling argument.
*/
- isl_tiling_flags_t tiling_flags =
+ isl_tiling_flags_t mask =
(vk_info->tiling == VK_IMAGE_TILING_LINEAR) ?
ISL_TILING_LINEAR_BIT : ISL_TILING_ANY_MASK;
+ isl_tiling_flags_t tiling_flags = mask;
+ isl_tiling_flags_t suboptimal_tiling_flags = 0;
if (anv_info->isl_tiling_flags)
tiling_flags &= anv_info->isl_tiling_flags;
+ if (anv_info->isl_suboptimal_tiling_flags)
+ suboptimal_tiling_flags = anv_info->isl_suboptimal_tiling_flags & mask;
assert(tiling_flags);
@@ -317,7 +321,8 @@ make_surface(const struct anv_device *dev,
.min_alignment = 0,
.row_pitch = anv_info->stride,
.usage = choose_isl_surf_usage(vk_info->flags, image->usage, aspect),
- .tiling_flags = tiling_flags);
+ .tiling_flags = tiling_flags,
+ .suboptimal_tiling_flags = suboptimal_tiling_flags);
/* isl_surf_init() will fail only if provided invalid input. Invalid input
* is illegal in Vulkan.
diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h
index abc278b40b..6cca45c479 100644
--- a/src/intel/vulkan/anv_private.h
+++ b/src/intel/vulkan/anv_private.h
@@ -2625,6 +2625,9 @@ struct anv_image_create_info {
/** An opt-in bitmask which filters an ISL-mapping of the Vulkan tiling. */
isl_tiling_flags_t isl_tiling_flags;
+ /** Set of possible but suboptimal tiling flags. */
+ isl_tiling_flags_t isl_suboptimal_tiling_flags;
+
uint32_t stride;
};
diff --git a/src/intel/vulkan/anv_wsi.c b/src/intel/vulkan/anv_wsi.c
index 61073a9788..8919a82d94 100644
--- a/src/intel/vulkan/anv_wsi.c
+++ b/src/intel/vulkan/anv_wsi.c
@@ -173,18 +173,54 @@ anv_wsi_image_create(VkDevice device_h,
const VkSwapchainCreateInfoKHR *pCreateInfo,
const VkAllocationCallbacks* pAllocator,
bool different_gpu,
+ uint64_t **modifiers,
+ int *num_modifiers,
+ int num_tranches,
struct wsi_image_base *wsi_image)
{
struct anv_device *device = anv_device_from_handle(device_h);
VkImage image_h;
struct anv_image *image;
- isl_tiling_flags_t isl_tiling = ISL_TILING_X_BIT;
+ isl_tiling_flags_t isl_tiling[2] = {0,};
VkImageTiling vk_tiling = VK_IMAGE_TILING_OPTIMAL;
+ assert(num_tranches >= 0 && num_tranches <= 2);
+
+ /* If we haven't been provided any modifiers, fall back to our previous
+ * default of X-tiling, which the other side can infer through the BO
+ * get_tiling ioctl. */
+ if (num_tranches == 0) {
+ isl_tiling[0] = ISL_TILING_X_BIT;
+ } else {
+ for (int i = 0; i < num_tranches; i++) {
+ for (int j = 0; j < num_modifiers[i]; j++) {
+ const struct isl_drm_modifier_info *info =
+ isl_drm_modifier_get_info(modifiers[i][j]);
+ if (!info || info->aux_usage != ISL_AUX_USAGE_NONE)
+ continue;
+ isl_tiling[i] |= (1 << info->tiling);
+ }
+ }
+ }
+
+ /* This isn't strictly correct; really we want something more like
+ * SURFACE_LOST, because we'll never be able to render to it in these
+ * conditions.
+ */
+ if (isl_tiling[0] == 0)
+ return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+
+ if (isl_tiling[0] & ISL_TILING_NON_LINEAR_MASK ||
+ isl_tiling[1] & ISL_TILING_NON_LINEAR_MASK)
+ vk_tiling = VK_IMAGE_TILING_OPTIMAL;
+ else
+ vk_tiling = VK_IMAGE_TILING_LINEAR;
+
VkResult result;
result = anv_image_create(anv_device_to_handle(device),
&(struct anv_image_create_info) {
- .isl_tiling_flags = isl_tiling,
+ .isl_tiling_flags = isl_tiling[0],
+ .isl_suboptimal_tiling_flags = isl_tiling[1],
.stride = 0,
.vk_info =
&(VkImageCreateInfo) {
@@ -238,7 +274,7 @@ anv_wsi_image_create(VkDevice device_h,
assert(image->planes[0].offset == 0);
struct anv_surface *surface = &image->planes[0].surface;
- assert(isl_tiling & (1 << surface->isl.tiling));
+ assert((isl_tiling[0] | isl_tiling[1]) & (1 << surface->isl.tiling));
int ret = anv_gem_set_tiling(device, memory->bo->gem_handle,
surface->isl.row_pitch,
diff --git a/src/vulkan/wsi/wsi_common.h b/src/vulkan/wsi/wsi_common.h
index 8172f4b318..99836054ca 100644
--- a/src/vulkan/wsi/wsi_common.h
+++ b/src/vulkan/wsi/wsi_common.h
@@ -50,6 +50,9 @@ struct wsi_image_fns {
const VkSwapchainCreateInfoKHR *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
bool different_gpu,
+ uint64_t **modifiers,
+ int *num_modifiers,
+ int num_tranches,
struct wsi_image_base *image_p);
void (*free_wsi_image)(VkDevice device,
const VkAllocationCallbacks *pAllocator,
diff --git a/src/vulkan/wsi/wsi_common_wayland.c b/src/vulkan/wsi/wsi_common_wayland.c
index 8df30d993c..0ab73f0957 100644
--- a/src/vulkan/wsi/wsi_common_wayland.c
+++ b/src/vulkan/wsi/wsi_common_wayland.c
@@ -731,6 +731,9 @@ wsi_wl_image_init(struct wsi_wl_swapchain *chain,
pCreateInfo,
pAllocator,
false,
+ NULL,
+ NULL,
+ 0,
&image->base);
if (result != VK_SUCCESS)
return result;
diff --git a/src/vulkan/wsi/wsi_common_x11.c b/src/vulkan/wsi/wsi_common_x11.c
index 784d275dc5..8bc6dc9125 100644
--- a/src/vulkan/wsi/wsi_common_x11.c
+++ b/src/vulkan/wsi/wsi_common_x11.c
@@ -962,6 +962,9 @@ x11_image_init(VkDevice device_h, struct x11_swapchain *chain,
pCreateInfo,
pAllocator,
chain->base.needs_linear_copy,
+ NULL,
+ NULL,
+ 0,
&image->base);
if (result != VK_SUCCESS)
return result;
--
2.13.0
More information about the mesa-dev
mailing list