2015-05-08 22:32:37 -07:00
|
|
|
/*
|
|
|
|
|
* Copyright © 2015 Intel Corporation
|
|
|
|
|
*
|
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
|
|
|
* to deal in the Software without restriction, including without limitation
|
|
|
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
|
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
|
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
|
|
|
*
|
|
|
|
|
* The above copyright notice and this permission notice (including the next
|
|
|
|
|
* paragraph) shall be included in all copies or substantial portions of the
|
|
|
|
|
* Software.
|
|
|
|
|
*
|
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
|
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
|
|
|
* IN THE SOFTWARE.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <assert.h>
|
|
|
|
|
#include <stdbool.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
#include <fcntl.h>
|
2017-05-03 08:02:21 +02:00
|
|
|
#include <sys/mman.h>
|
2019-02-12 18:18:03 +00:00
|
|
|
#include "drm-uapi/drm_fourcc.h"
|
2015-05-08 22:32:37 -07:00
|
|
|
|
2015-07-17 15:04:27 -07:00
|
|
|
#include "anv_private.h"
|
2016-10-06 15:21:49 -07:00
|
|
|
#include "util/debug.h"
|
2017-06-19 08:38:48 -07:00
|
|
|
#include "vk_util.h"
|
2018-08-21 09:46:46 -07:00
|
|
|
#include "util/u_math.h"
|
2015-05-08 22:32:37 -07:00
|
|
|
|
2016-05-13 16:47:39 -07:00
|
|
|
#include "vk_format_info.h"
|
|
|
|
|
|
2015-12-02 16:46:16 -08:00
|
|
|
static isl_surf_usage_flags_t
|
2017-07-17 15:18:51 -07:00
|
|
|
choose_isl_surf_usage(VkImageCreateFlags vk_create_flags,
|
|
|
|
|
VkImageUsageFlags vk_usage,
|
anv: Implement VK_ANDROID_native_buffer (v9)
This implementation is correct (afaict), but takes two shortcuts
regarding the import/export of Android sync fds.
Shortcut 1. When Android calls vkAcquireImageANDROID to import a sync
fd into a VkSemaphore or VkFence, the driver instead simply blocks on
the sync fd, then puts the VkSemaphore or VkFence into the signalled
state. Thanks to implicit sync, this produces correct behavior (with
extra latency overhead, perhaps) despite its ugliness.
Shortcut 2. When Android calls vkQueueSignalReleaseImageANDROID to export
a collection of wait semaphores as a sync fd, the driver instead
submits the semaphores to the queue, then returns sync fd -1, which
informs the caller that no additional synchronization is needed.
Again, thanks to implicit sync, this produces correct behavior (with
extra batch submission overhead) despite its ugliness.
I chose to take the shortcuts instead of properly importing/exporting
the sync fds for two reasons:
Reason 1. I've already tested this patch with dEQP and with demos
apps. It works. I wanted to get the tested patches into the tree now,
and polish the implementation afterwards.
Reason 2. I want to run this on a 3.18 kernel (gasp!). In 3.18, i915
supports neither Android's sync_fence, nor upstream's sync_file, nor
drm_syncobj. Again, I tested these patches on Android with a 3.18
kernel and they work.
I plan to quickly follow-up with patches that remove the shortcuts and
properly import/export the sync fds.
Non-Testing
===========
I did not test at all using the Android.mk buildsystem. I may have broke
it. Please test and review that.
Testing
=======
I tested with 64-bit ARC++ on a Skylake Chromebook and a 3.18 kernel.
The following pass (as of patchset v9):
- a little spinning cube demo APK
- several Sascha demos
- dEQP-VK.info.*
- dEQP-VK.api.wsi.android.*
(except dEQP-VK.api.wsi.android.swapchain.*.image_usage, because
dEQP wants to create swapchains with VK_IMAGE_USAGE_STORAGE_BIT)
- dEQP-VK.api.smoke.*
- dEQP-VK.api.info.instance.*
- dEQP-VK.api.info.device.*
v2:
- Reject VkNativeBufferANDROID if the dma-buf's size is too small for
the VkImage.
- Stop abusing VkNativeBufferANDROID by passing it to vkAllocateMemory
during vkCreateImage. Instead, directly import its dma-buf during
vkCreateImage with anv_bo_cache_import(). [for jekstrand]
- Rebase onto Tapani's VK_EXT_debug_report changes.
- Drop `CPPFLAGS += $(top_srcdir)/include/android`. The dir does not
exist.
v3:
- Delete duplicate #include "anv_private.h". [per Tapani]
- Try to fix the Android-IA build in Android.vulkan.mk by following
Tapani's example.
v4:
- Unset EXEC_OBJECT_ASYNC and set EXEC_OBJECT_WRITE on the imported
gralloc buffer, just as we do for all other winsys buffers in
anv_wsi.c. [found by Tapani]
v5:
- Really fix the Android-IA build by ensuring that Android.vulkan.mk
uses Mesa' vulkan.h and not Android's. Insert -I$(MESA_TOP)/include
before -Iframeworks/native/vulkan/include. [for Tapani]
- In vkAcquireImageANDROID, submit signal operations to the
VkSemaphore and VkFence. [for zhou]
v6:
- Drop copy-paste duplication in vkGetSwapchainGrallocUsageANDROID().
[found by zhou]
- Improve comments in vkGetSwapchainGrallocUsageANDROID().
v7:
- Fix vkGetSwapchainGrallocUsageANDROID() to inspect its
VkImageUsageFlags parameter. [for tfiga]
- This fix regresses dEQP-VK.api.wsi.android.swapchain.*.image_usage
because dEQP wants to create swapchains with
VK_IMAGE_USAGE_STORAGE_BIT.
v8:
- Drop unneeded goto in vkAcquireImageANDROID. [for tfiga]
v8.1: (minor changes)
- Drop errant hunks added by rerere in anv_device.c.
- Drop explicit mention of VK_ANDROID_native_buffer in
anv_entrypoints_gen.py. [for jekstrand]
v9:
- Isolate as much Android code as possible, moving it from anv_image.c
to anv_android.c. Connect the files with anv_image_from_gralloc().
Remove VkNativeBufferANDROID params from all anv_image.c
funcs. [for krh]
- Replace some intel_loge() with vk_errorf() in anv_android.c.
- Use © in copyright line. [for krh]
Reviewed-by: Tapani Pälli <tapani.palli@intel.com> (v5)
Reviewed-by: Kristian H. Kristensen <hoegsberg@google.com> (v9)
Reviewed-by: Jason Ekstrand <jason@jlekstrand.net> (v9)
Cc: zhoucm1 <david1.zhou@amd.com>
Cc: Tomasz Figa <tfiga@chromium.org>
2016-11-14 16:13:51 -08:00
|
|
|
isl_surf_usage_flags_t isl_extra_usage,
|
2017-11-02 17:26:51 -07:00
|
|
|
VkImageAspectFlagBits aspect)
|
2015-06-26 18:48:34 -07:00
|
|
|
{
|
anv: Implement VK_ANDROID_native_buffer (v9)
This implementation is correct (afaict), but takes two shortcuts
regarding the import/export of Android sync fds.
Shortcut 1. When Android calls vkAcquireImageANDROID to import a sync
fd into a VkSemaphore or VkFence, the driver instead simply blocks on
the sync fd, then puts the VkSemaphore or VkFence into the signalled
state. Thanks to implicit sync, this produces correct behavior (with
extra latency overhead, perhaps) despite its ugliness.
Shortcut 2. When Android calls vkQueueSignalReleaseImageANDROID to export
a collection of wait semaphores as a sync fd, the driver instead
submits the semaphores to the queue, then returns sync fd -1, which
informs the caller that no additional synchronization is needed.
Again, thanks to implicit sync, this produces correct behavior (with
extra batch submission overhead) despite its ugliness.
I chose to take the shortcuts instead of properly importing/exporting
the sync fds for two reasons:
Reason 1. I've already tested this patch with dEQP and with demos
apps. It works. I wanted to get the tested patches into the tree now,
and polish the implementation afterwards.
Reason 2. I want to run this on a 3.18 kernel (gasp!). In 3.18, i915
supports neither Android's sync_fence, nor upstream's sync_file, nor
drm_syncobj. Again, I tested these patches on Android with a 3.18
kernel and they work.
I plan to quickly follow-up with patches that remove the shortcuts and
properly import/export the sync fds.
Non-Testing
===========
I did not test at all using the Android.mk buildsystem. I may have broke
it. Please test and review that.
Testing
=======
I tested with 64-bit ARC++ on a Skylake Chromebook and a 3.18 kernel.
The following pass (as of patchset v9):
- a little spinning cube demo APK
- several Sascha demos
- dEQP-VK.info.*
- dEQP-VK.api.wsi.android.*
(except dEQP-VK.api.wsi.android.swapchain.*.image_usage, because
dEQP wants to create swapchains with VK_IMAGE_USAGE_STORAGE_BIT)
- dEQP-VK.api.smoke.*
- dEQP-VK.api.info.instance.*
- dEQP-VK.api.info.device.*
v2:
- Reject VkNativeBufferANDROID if the dma-buf's size is too small for
the VkImage.
- Stop abusing VkNativeBufferANDROID by passing it to vkAllocateMemory
during vkCreateImage. Instead, directly import its dma-buf during
vkCreateImage with anv_bo_cache_import(). [for jekstrand]
- Rebase onto Tapani's VK_EXT_debug_report changes.
- Drop `CPPFLAGS += $(top_srcdir)/include/android`. The dir does not
exist.
v3:
- Delete duplicate #include "anv_private.h". [per Tapani]
- Try to fix the Android-IA build in Android.vulkan.mk by following
Tapani's example.
v4:
- Unset EXEC_OBJECT_ASYNC and set EXEC_OBJECT_WRITE on the imported
gralloc buffer, just as we do for all other winsys buffers in
anv_wsi.c. [found by Tapani]
v5:
- Really fix the Android-IA build by ensuring that Android.vulkan.mk
uses Mesa' vulkan.h and not Android's. Insert -I$(MESA_TOP)/include
before -Iframeworks/native/vulkan/include. [for Tapani]
- In vkAcquireImageANDROID, submit signal operations to the
VkSemaphore and VkFence. [for zhou]
v6:
- Drop copy-paste duplication in vkGetSwapchainGrallocUsageANDROID().
[found by zhou]
- Improve comments in vkGetSwapchainGrallocUsageANDROID().
v7:
- Fix vkGetSwapchainGrallocUsageANDROID() to inspect its
VkImageUsageFlags parameter. [for tfiga]
- This fix regresses dEQP-VK.api.wsi.android.swapchain.*.image_usage
because dEQP wants to create swapchains with
VK_IMAGE_USAGE_STORAGE_BIT.
v8:
- Drop unneeded goto in vkAcquireImageANDROID. [for tfiga]
v8.1: (minor changes)
- Drop errant hunks added by rerere in anv_device.c.
- Drop explicit mention of VK_ANDROID_native_buffer in
anv_entrypoints_gen.py. [for jekstrand]
v9:
- Isolate as much Android code as possible, moving it from anv_image.c
to anv_android.c. Connect the files with anv_image_from_gralloc().
Remove VkNativeBufferANDROID params from all anv_image.c
funcs. [for krh]
- Replace some intel_loge() with vk_errorf() in anv_android.c.
- Use © in copyright line. [for krh]
Reviewed-by: Tapani Pälli <tapani.palli@intel.com> (v5)
Reviewed-by: Kristian H. Kristensen <hoegsberg@google.com> (v9)
Reviewed-by: Jason Ekstrand <jason@jlekstrand.net> (v9)
Cc: zhoucm1 <david1.zhou@amd.com>
Cc: Tomasz Figa <tfiga@chromium.org>
2016-11-14 16:13:51 -08:00
|
|
|
isl_surf_usage_flags_t isl_usage = isl_extra_usage;
|
2015-06-26 18:48:34 -07:00
|
|
|
|
2016-02-09 12:35:39 -08:00
|
|
|
if (vk_usage & VK_IMAGE_USAGE_SAMPLED_BIT)
|
2016-02-09 12:36:54 -08:00
|
|
|
isl_usage |= ISL_SURF_USAGE_TEXTURE_BIT;
|
2015-11-13 10:24:57 -08:00
|
|
|
|
2016-02-09 12:35:39 -08:00
|
|
|
if (vk_usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)
|
2016-02-09 12:36:54 -08:00
|
|
|
isl_usage |= ISL_SURF_USAGE_TEXTURE_BIT;
|
2015-09-14 10:58:43 -07:00
|
|
|
|
2016-02-09 12:35:39 -08:00
|
|
|
if (vk_usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)
|
2016-02-09 12:36:54 -08:00
|
|
|
isl_usage |= ISL_SURF_USAGE_RENDER_TARGET_BIT;
|
2015-09-14 10:58:43 -07:00
|
|
|
|
2017-07-17 15:18:51 -07:00
|
|
|
if (vk_create_flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT)
|
2016-02-09 12:36:54 -08:00
|
|
|
isl_usage |= ISL_SURF_USAGE_CUBE_BIT;
|
2015-09-14 10:58:43 -07:00
|
|
|
|
2016-10-07 22:07:04 -07:00
|
|
|
/* Even if we're only using it for transfer operations, clears to depth and
|
|
|
|
|
* stencil images happen as depth and stencil so they need the right ISL
|
|
|
|
|
* usage bits or else things will fall apart.
|
|
|
|
|
*/
|
|
|
|
|
switch (aspect) {
|
|
|
|
|
case VK_IMAGE_ASPECT_DEPTH_BIT:
|
|
|
|
|
isl_usage |= ISL_SURF_USAGE_DEPTH_BIT;
|
|
|
|
|
break;
|
|
|
|
|
case VK_IMAGE_ASPECT_STENCIL_BIT:
|
|
|
|
|
isl_usage |= ISL_SURF_USAGE_STENCIL_BIT;
|
|
|
|
|
break;
|
|
|
|
|
case VK_IMAGE_ASPECT_COLOR_BIT:
|
2017-09-20 13:16:26 -07:00
|
|
|
case VK_IMAGE_ASPECT_PLANE_0_BIT:
|
|
|
|
|
case VK_IMAGE_ASPECT_PLANE_1_BIT:
|
|
|
|
|
case VK_IMAGE_ASPECT_PLANE_2_BIT:
|
2016-10-07 22:07:04 -07:00
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
unreachable("bad VkImageAspect");
|
2015-09-14 10:58:43 -07:00
|
|
|
}
|
2015-09-14 11:04:08 -07:00
|
|
|
|
2016-02-09 12:35:39 -08:00
|
|
|
if (vk_usage & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) {
|
2016-10-07 22:07:04 -07:00
|
|
|
/* blorp implements transfers by sampling from the source image. */
|
2016-02-09 12:36:54 -08:00
|
|
|
isl_usage |= ISL_SURF_USAGE_TEXTURE_BIT;
|
2015-06-26 21:27:54 -07:00
|
|
|
}
|
|
|
|
|
|
2017-01-19 16:20:00 +00:00
|
|
|
if (vk_usage & VK_IMAGE_USAGE_TRANSFER_DST_BIT &&
|
|
|
|
|
aspect == VK_IMAGE_ASPECT_COLOR_BIT) {
|
|
|
|
|
/* blorp implements transfers by rendering into the destination image.
|
|
|
|
|
* Only request this with color images, as we deal with depth/stencil
|
|
|
|
|
* formats differently. */
|
2016-02-09 12:36:54 -08:00
|
|
|
isl_usage |= ISL_SURF_USAGE_RENDER_TARGET_BIT;
|
2015-06-26 21:27:54 -07:00
|
|
|
}
|
|
|
|
|
|
2016-02-09 12:36:54 -08:00
|
|
|
return isl_usage;
|
2015-12-02 16:46:16 -08:00
|
|
|
}
|
2015-06-26 21:27:54 -07:00
|
|
|
|
2017-11-06 18:51:53 -08:00
|
|
|
static isl_tiling_flags_t
|
2017-11-15 22:11:46 -08:00
|
|
|
choose_isl_tiling_flags(const struct anv_image_create_info *anv_info,
|
2018-01-24 19:47:14 -08:00
|
|
|
const struct isl_drm_modifier_info *isl_mod_info,
|
|
|
|
|
bool legacy_scanout)
|
2017-11-06 18:51:53 -08:00
|
|
|
{
|
|
|
|
|
const VkImageCreateInfo *base_info = anv_info->vk_info;
|
|
|
|
|
isl_tiling_flags_t flags = 0;
|
|
|
|
|
|
|
|
|
|
switch (base_info->tiling) {
|
|
|
|
|
default:
|
|
|
|
|
unreachable("bad VkImageTiling");
|
|
|
|
|
case VK_IMAGE_TILING_OPTIMAL:
|
|
|
|
|
flags = ISL_TILING_ANY_MASK;
|
|
|
|
|
break;
|
|
|
|
|
case VK_IMAGE_TILING_LINEAR:
|
|
|
|
|
flags = ISL_TILING_LINEAR_BIT;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (anv_info->isl_tiling_flags)
|
|
|
|
|
flags &= anv_info->isl_tiling_flags;
|
|
|
|
|
|
2018-01-24 19:47:14 -08:00
|
|
|
if (legacy_scanout)
|
|
|
|
|
flags &= ISL_TILING_LINEAR_BIT | ISL_TILING_X_BIT;
|
|
|
|
|
|
2017-11-15 22:11:46 -08:00
|
|
|
if (isl_mod_info)
|
|
|
|
|
flags &= 1 << isl_mod_info->tiling;
|
|
|
|
|
|
2017-11-06 18:51:53 -08:00
|
|
|
assert(flags);
|
|
|
|
|
|
|
|
|
|
return flags;
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-07 09:22:49 -08:00
|
|
|
static struct anv_surface *
|
2017-11-02 17:26:51 -07:00
|
|
|
get_surface(struct anv_image *image, VkImageAspectFlagBits aspect)
|
2015-12-07 09:22:49 -08:00
|
|
|
{
|
2017-07-19 12:14:19 +01:00
|
|
|
uint32_t plane = anv_image_aspect_to_plane(image->aspects, aspect);
|
|
|
|
|
return &image->planes[plane].surface;
|
2015-12-07 09:22:49 -08:00
|
|
|
}
|
|
|
|
|
|
2016-10-06 15:21:49 -07:00
|
|
|
static void
|
2017-07-19 12:14:19 +01:00
|
|
|
add_surface(struct anv_image *image, struct anv_surface *surf, uint32_t plane)
|
2016-10-06 15:21:49 -07:00
|
|
|
{
|
2018-09-05 14:02:12 -05:00
|
|
|
assert(surf->isl.size_B > 0); /* isl surface must be initialized */
|
2016-10-06 15:21:49 -07:00
|
|
|
|
2017-07-19 12:14:19 +01:00
|
|
|
if (image->disjoint) {
|
2018-09-05 14:02:12 -05:00
|
|
|
surf->offset = align_u32(image->planes[plane].size,
|
|
|
|
|
surf->isl.alignment_B);
|
2017-07-19 12:14:19 +01:00
|
|
|
/* Plane offset is always 0 when it's disjoint. */
|
|
|
|
|
} else {
|
2018-09-05 14:02:12 -05:00
|
|
|
surf->offset = align_u32(image->size, surf->isl.alignment_B);
|
2017-07-19 12:14:19 +01:00
|
|
|
/* Determine plane's offset only once when the first surface is added. */
|
|
|
|
|
if (image->planes[plane].size == 0)
|
|
|
|
|
image->planes[plane].offset = image->size;
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-05 14:02:12 -05:00
|
|
|
image->size = surf->offset + surf->isl.size_B;
|
|
|
|
|
image->planes[plane].size = (surf->offset + surf->isl.size_B) - image->planes[plane].offset;
|
2017-07-19 12:14:19 +01:00
|
|
|
|
2018-09-05 14:02:12 -05:00
|
|
|
image->alignment = MAX2(image->alignment, surf->isl.alignment_B);
|
2017-07-19 12:14:19 +01:00
|
|
|
image->planes[plane].alignment = MAX2(image->planes[plane].alignment,
|
2018-09-05 14:02:12 -05:00
|
|
|
surf->isl.alignment_B);
|
2016-10-06 15:21:49 -07:00
|
|
|
}
|
|
|
|
|
|
2017-06-19 08:38:48 -07:00
|
|
|
|
|
|
|
|
static bool
|
|
|
|
|
all_formats_ccs_e_compatible(const struct gen_device_info *devinfo,
|
2018-09-27 08:00:53 +03:00
|
|
|
const VkImageFormatListCreateInfoKHR *fmt_list,
|
|
|
|
|
struct anv_image *image)
|
2017-06-19 08:38:48 -07:00
|
|
|
{
|
|
|
|
|
enum isl_format format =
|
2018-09-27 08:00:53 +03:00
|
|
|
anv_get_isl_format(devinfo, image->vk_format,
|
|
|
|
|
VK_IMAGE_ASPECT_COLOR_BIT, image->tiling);
|
2017-06-19 08:38:48 -07:00
|
|
|
|
|
|
|
|
if (!isl_format_supports_ccs_e(devinfo, format))
|
|
|
|
|
return false;
|
|
|
|
|
|
2018-09-27 08:00:53 +03:00
|
|
|
if (!(image->create_flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT))
|
2017-06-19 08:38:48 -07:00
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
if (!fmt_list || fmt_list->viewFormatCount == 0)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < fmt_list->viewFormatCount; i++) {
|
|
|
|
|
enum isl_format view_format =
|
|
|
|
|
anv_get_isl_format(devinfo, fmt_list->pViewFormats[i],
|
2018-09-27 08:00:53 +03:00
|
|
|
VK_IMAGE_ASPECT_COLOR_BIT, image->tiling);
|
2017-06-19 08:38:48 -07:00
|
|
|
|
|
|
|
|
if (!isl_formats_are_ccs_e_compatible(devinfo, format, view_format))
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-18 17:39:53 -08:00
|
|
|
/**
|
|
|
|
|
* For color images that have an auxiliary surface, request allocation for an
|
|
|
|
|
* additional buffer that mainly stores fast-clear values. Use of this buffer
|
|
|
|
|
* allows us to access the image's subresources while being aware of their
|
|
|
|
|
* fast-clear values in non-trivial cases (e.g., outside of a render pass in
|
|
|
|
|
* which a fast clear has occurred).
|
|
|
|
|
*
|
2017-11-21 08:46:25 -08:00
|
|
|
* In order to avoid having multiple clear colors for a single plane of an
|
|
|
|
|
* image (hence a single RENDER_SURFACE_STATE), we only allow fast-clears on
|
|
|
|
|
* the first slice (level 0, layer 0). At the time of our testing (Jan 17,
|
|
|
|
|
* 2018), there were no known applications which would benefit from fast-
|
|
|
|
|
* clearing more than just the first slice.
|
2017-01-18 17:39:53 -08:00
|
|
|
*
|
2017-11-21 08:46:25 -08:00
|
|
|
* The fast clear portion of the image is laid out in the following order:
|
2017-01-18 17:39:53 -08:00
|
|
|
*
|
2017-11-21 08:46:25 -08:00
|
|
|
* * 1 or 4 dwords (depending on hardware generation) for the clear color
|
|
|
|
|
* * 1 dword for the anv_fast_clear_type of the clear color
|
|
|
|
|
* * On gen9+, 1 dword per level and layer of the image (3D levels count
|
|
|
|
|
* multiple layers) in level-major order for compression state.
|
2017-01-18 17:39:53 -08:00
|
|
|
*
|
2017-11-21 08:46:25 -08:00
|
|
|
* For the purpose of discoverability, the algorithm used to manage
|
|
|
|
|
* compression and fast-clears is described here:
|
2017-01-18 17:39:53 -08:00
|
|
|
*
|
2017-11-21 08:46:25 -08:00
|
|
|
* * On a transition from UNDEFINED or PREINITIALIZED to a defined layout,
|
|
|
|
|
* all of the values in the fast clear portion of the image are initialized
|
|
|
|
|
* to default values.
|
2017-01-18 17:39:53 -08:00
|
|
|
*
|
2017-11-21 08:46:25 -08:00
|
|
|
* * On fast-clear, the clear value is written into surface state and also
|
|
|
|
|
* into the buffer and the fast clear type is set appropriately. Both
|
|
|
|
|
* setting the fast-clear value in the buffer and setting the fast-clear
|
|
|
|
|
* type happen from the GPU using MI commands.
|
|
|
|
|
*
|
|
|
|
|
* * Whenever a render or blorp operation is performed with CCS_E, we call
|
|
|
|
|
* genX(cmd_buffer_mark_image_written) to set the compression state to
|
|
|
|
|
* true (which is represented by UINT32_MAX).
|
|
|
|
|
*
|
|
|
|
|
* * On pipeline barrier transitions, the worst-case transition is computed
|
|
|
|
|
* from the image layouts. The command streamer inspects the fast clear
|
|
|
|
|
* type and compression state dwords and constructs a predicate. The
|
|
|
|
|
* worst-case resolve is performed with the given predicate and the fast
|
|
|
|
|
* clear and compression state is set accordingly.
|
|
|
|
|
*
|
|
|
|
|
* See anv_layout_to_aux_usage and anv_layout_to_fast_clear_type functions for
|
|
|
|
|
* details on exactly what is allowed in what layouts.
|
|
|
|
|
*
|
|
|
|
|
* On gen7-9, we do not have a concept of indirect clear colors in hardware.
|
|
|
|
|
* In order to deal with this, we have to do some clear color management.
|
|
|
|
|
*
|
|
|
|
|
* * For LOAD_OP_LOAD at the top of a renderpass, we have to copy the clear
|
|
|
|
|
* value from the buffer into the surface state with MI commands.
|
|
|
|
|
*
|
|
|
|
|
* * For any blorp operations, we pass the address to the clear value into
|
|
|
|
|
* blorp and it knows to copy the clear color.
|
2017-01-18 17:39:53 -08:00
|
|
|
*/
|
|
|
|
|
static void
|
2017-11-21 08:46:25 -08:00
|
|
|
add_aux_state_tracking_buffer(struct anv_image *image,
|
|
|
|
|
uint32_t plane,
|
|
|
|
|
const struct anv_device *device)
|
2017-01-18 17:39:53 -08:00
|
|
|
{
|
|
|
|
|
assert(image && device);
|
2018-09-05 14:02:12 -05:00
|
|
|
assert(image->planes[plane].aux_surface.isl.size_B > 0 &&
|
2017-11-02 16:05:45 -07:00
|
|
|
image->aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT_ANV);
|
2017-01-18 17:39:53 -08:00
|
|
|
|
2018-01-18 09:17:17 -08:00
|
|
|
/* Compressed images must be tiled and therefore everything should be 4K
|
|
|
|
|
* aligned. The CCS has the same alignment requirements. This is good
|
|
|
|
|
* because we need at least dword-alignment for MI_LOAD/STORE operations.
|
2017-01-18 17:39:53 -08:00
|
|
|
*/
|
|
|
|
|
assert(image->alignment % 4 == 0);
|
2017-07-19 12:14:19 +01:00
|
|
|
assert((image->planes[plane].offset + image->planes[plane].size) % 4 == 0);
|
2017-01-18 17:39:53 -08:00
|
|
|
|
2017-07-19 12:14:19 +01:00
|
|
|
/* This buffer should be at the very end of the plane. */
|
|
|
|
|
if (image->disjoint) {
|
|
|
|
|
assert(image->planes[plane].size ==
|
|
|
|
|
(image->planes[plane].offset + image->planes[plane].size));
|
|
|
|
|
} else {
|
|
|
|
|
assert(image->size ==
|
|
|
|
|
(image->planes[plane].offset + image->planes[plane].size));
|
|
|
|
|
}
|
2017-01-18 17:39:53 -08:00
|
|
|
|
2018-03-27 15:51:21 -07:00
|
|
|
const unsigned clear_color_state_size = device->info.gen >= 10 ?
|
|
|
|
|
device->isl_dev.ss.clear_color_state_size :
|
|
|
|
|
device->isl_dev.ss.clear_value_size;
|
|
|
|
|
|
2017-11-21 08:46:25 -08:00
|
|
|
/* Clear color and fast clear type */
|
2018-03-27 15:51:21 -07:00
|
|
|
unsigned state_size = clear_color_state_size + 4;
|
2017-07-19 12:14:19 +01:00
|
|
|
|
2017-11-21 08:46:25 -08:00
|
|
|
/* We only need to track compression on CCS_E surfaces. */
|
|
|
|
|
if (image->planes[plane].aux_usage == ISL_AUX_USAGE_CCS_E) {
|
|
|
|
|
if (image->type == VK_IMAGE_TYPE_3D) {
|
|
|
|
|
for (uint32_t l = 0; l < image->levels; l++)
|
|
|
|
|
state_size += anv_minify(image->extent.depth, l) * 4;
|
|
|
|
|
} else {
|
|
|
|
|
state_size += image->levels * image->array_size * 4;
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-07-19 12:14:19 +01:00
|
|
|
|
|
|
|
|
image->planes[plane].fast_clear_state_offset =
|
|
|
|
|
image->planes[plane].offset + image->planes[plane].size;
|
|
|
|
|
|
2017-11-21 08:46:25 -08:00
|
|
|
image->planes[plane].size += state_size;
|
|
|
|
|
image->size += state_size;
|
2017-01-18 17:39:53 -08:00
|
|
|
}
|
|
|
|
|
|
2015-12-07 09:22:49 -08:00
|
|
|
/**
|
|
|
|
|
* Initialize the anv_image::*_surface selected by \a aspect. Then update the
|
|
|
|
|
* image's memory requirements (that is, the image's size and alignment).
|
2015-12-02 16:46:16 -08:00
|
|
|
*/
|
|
|
|
|
static VkResult
|
2015-12-07 09:22:49 -08:00
|
|
|
make_surface(const struct anv_device *dev,
|
|
|
|
|
struct anv_image *image,
|
2018-09-27 08:00:53 +03:00
|
|
|
uint32_t stride,
|
2017-11-06 18:51:53 -08:00
|
|
|
isl_tiling_flags_t tiling_flags,
|
2018-09-27 08:00:53 +03:00
|
|
|
isl_surf_usage_flags_t isl_extra_usage_flags,
|
2017-11-02 17:26:51 -07:00
|
|
|
VkImageAspectFlagBits aspect)
|
2015-12-02 16:46:16 -08:00
|
|
|
{
|
2018-07-24 09:54:33 +01:00
|
|
|
bool ok;
|
2015-08-14 10:02:19 -07:00
|
|
|
|
2015-12-02 16:46:16 -08:00
|
|
|
static const enum isl_surf_dim vk_to_isl_surf_dim[] = {
|
|
|
|
|
[VK_IMAGE_TYPE_1D] = ISL_SURF_DIM_1D,
|
|
|
|
|
[VK_IMAGE_TYPE_2D] = ISL_SURF_DIM_2D,
|
|
|
|
|
[VK_IMAGE_TYPE_3D] = ISL_SURF_DIM_3D,
|
|
|
|
|
};
|
2015-06-26 18:48:34 -07:00
|
|
|
|
2018-09-27 08:00:53 +03:00
|
|
|
image->extent = anv_sanitize_image_extent(image->type, image->extent);
|
2016-02-17 17:20:03 -08:00
|
|
|
|
2017-07-19 12:14:19 +01:00
|
|
|
const unsigned plane = anv_image_aspect_to_plane(image->aspects, aspect);
|
|
|
|
|
const struct anv_format_plane plane_format =
|
|
|
|
|
anv_get_format_plane(&dev->info, image->vk_format, aspect, image->tiling);
|
|
|
|
|
struct anv_surface *anv_surf = &image->planes[plane].surface;
|
2016-07-20 21:10:20 -07:00
|
|
|
|
anv: Implement VK_ANDROID_native_buffer (v9)
This implementation is correct (afaict), but takes two shortcuts
regarding the import/export of Android sync fds.
Shortcut 1. When Android calls vkAcquireImageANDROID to import a sync
fd into a VkSemaphore or VkFence, the driver instead simply blocks on
the sync fd, then puts the VkSemaphore or VkFence into the signalled
state. Thanks to implicit sync, this produces correct behavior (with
extra latency overhead, perhaps) despite its ugliness.
Shortcut 2. When Android calls vkQueueSignalReleaseImageANDROID to export
a collection of wait semaphores as a sync fd, the driver instead
submits the semaphores to the queue, then returns sync fd -1, which
informs the caller that no additional synchronization is needed.
Again, thanks to implicit sync, this produces correct behavior (with
extra batch submission overhead) despite its ugliness.
I chose to take the shortcuts instead of properly importing/exporting
the sync fds for two reasons:
Reason 1. I've already tested this patch with dEQP and with demos
apps. It works. I wanted to get the tested patches into the tree now,
and polish the implementation afterwards.
Reason 2. I want to run this on a 3.18 kernel (gasp!). In 3.18, i915
supports neither Android's sync_fence, nor upstream's sync_file, nor
drm_syncobj. Again, I tested these patches on Android with a 3.18
kernel and they work.
I plan to quickly follow-up with patches that remove the shortcuts and
properly import/export the sync fds.
Non-Testing
===========
I did not test at all using the Android.mk buildsystem. I may have broke
it. Please test and review that.
Testing
=======
I tested with 64-bit ARC++ on a Skylake Chromebook and a 3.18 kernel.
The following pass (as of patchset v9):
- a little spinning cube demo APK
- several Sascha demos
- dEQP-VK.info.*
- dEQP-VK.api.wsi.android.*
(except dEQP-VK.api.wsi.android.swapchain.*.image_usage, because
dEQP wants to create swapchains with VK_IMAGE_USAGE_STORAGE_BIT)
- dEQP-VK.api.smoke.*
- dEQP-VK.api.info.instance.*
- dEQP-VK.api.info.device.*
v2:
- Reject VkNativeBufferANDROID if the dma-buf's size is too small for
the VkImage.
- Stop abusing VkNativeBufferANDROID by passing it to vkAllocateMemory
during vkCreateImage. Instead, directly import its dma-buf during
vkCreateImage with anv_bo_cache_import(). [for jekstrand]
- Rebase onto Tapani's VK_EXT_debug_report changes.
- Drop `CPPFLAGS += $(top_srcdir)/include/android`. The dir does not
exist.
v3:
- Delete duplicate #include "anv_private.h". [per Tapani]
- Try to fix the Android-IA build in Android.vulkan.mk by following
Tapani's example.
v4:
- Unset EXEC_OBJECT_ASYNC and set EXEC_OBJECT_WRITE on the imported
gralloc buffer, just as we do for all other winsys buffers in
anv_wsi.c. [found by Tapani]
v5:
- Really fix the Android-IA build by ensuring that Android.vulkan.mk
uses Mesa' vulkan.h and not Android's. Insert -I$(MESA_TOP)/include
before -Iframeworks/native/vulkan/include. [for Tapani]
- In vkAcquireImageANDROID, submit signal operations to the
VkSemaphore and VkFence. [for zhou]
v6:
- Drop copy-paste duplication in vkGetSwapchainGrallocUsageANDROID().
[found by zhou]
- Improve comments in vkGetSwapchainGrallocUsageANDROID().
v7:
- Fix vkGetSwapchainGrallocUsageANDROID() to inspect its
VkImageUsageFlags parameter. [for tfiga]
- This fix regresses dEQP-VK.api.wsi.android.swapchain.*.image_usage
because dEQP wants to create swapchains with
VK_IMAGE_USAGE_STORAGE_BIT.
v8:
- Drop unneeded goto in vkAcquireImageANDROID. [for tfiga]
v8.1: (minor changes)
- Drop errant hunks added by rerere in anv_device.c.
- Drop explicit mention of VK_ANDROID_native_buffer in
anv_entrypoints_gen.py. [for jekstrand]
v9:
- Isolate as much Android code as possible, moving it from anv_image.c
to anv_android.c. Connect the files with anv_image_from_gralloc().
Remove VkNativeBufferANDROID params from all anv_image.c
funcs. [for krh]
- Replace some intel_loge() with vk_errorf() in anv_android.c.
- Use © in copyright line. [for krh]
Reviewed-by: Tapani Pälli <tapani.palli@intel.com> (v5)
Reviewed-by: Kristian H. Kristensen <hoegsberg@google.com> (v9)
Reviewed-by: Jason Ekstrand <jason@jlekstrand.net> (v9)
Cc: zhoucm1 <david1.zhou@amd.com>
Cc: Tomasz Figa <tfiga@chromium.org>
2016-11-14 16:13:51 -08:00
|
|
|
const isl_surf_usage_flags_t usage =
|
2018-09-27 08:00:53 +03:00
|
|
|
choose_isl_surf_usage(image->create_flags, image->usage,
|
|
|
|
|
isl_extra_usage_flags, aspect);
|
anv: Implement VK_ANDROID_native_buffer (v9)
This implementation is correct (afaict), but takes two shortcuts
regarding the import/export of Android sync fds.
Shortcut 1. When Android calls vkAcquireImageANDROID to import a sync
fd into a VkSemaphore or VkFence, the driver instead simply blocks on
the sync fd, then puts the VkSemaphore or VkFence into the signalled
state. Thanks to implicit sync, this produces correct behavior (with
extra latency overhead, perhaps) despite its ugliness.
Shortcut 2. When Android calls vkQueueSignalReleaseImageANDROID to export
a collection of wait semaphores as a sync fd, the driver instead
submits the semaphores to the queue, then returns sync fd -1, which
informs the caller that no additional synchronization is needed.
Again, thanks to implicit sync, this produces correct behavior (with
extra batch submission overhead) despite its ugliness.
I chose to take the shortcuts instead of properly importing/exporting
the sync fds for two reasons:
Reason 1. I've already tested this patch with dEQP and with demos
apps. It works. I wanted to get the tested patches into the tree now,
and polish the implementation afterwards.
Reason 2. I want to run this on a 3.18 kernel (gasp!). In 3.18, i915
supports neither Android's sync_fence, nor upstream's sync_file, nor
drm_syncobj. Again, I tested these patches on Android with a 3.18
kernel and they work.
I plan to quickly follow-up with patches that remove the shortcuts and
properly import/export the sync fds.
Non-Testing
===========
I did not test at all using the Android.mk buildsystem. I may have broke
it. Please test and review that.
Testing
=======
I tested with 64-bit ARC++ on a Skylake Chromebook and a 3.18 kernel.
The following pass (as of patchset v9):
- a little spinning cube demo APK
- several Sascha demos
- dEQP-VK.info.*
- dEQP-VK.api.wsi.android.*
(except dEQP-VK.api.wsi.android.swapchain.*.image_usage, because
dEQP wants to create swapchains with VK_IMAGE_USAGE_STORAGE_BIT)
- dEQP-VK.api.smoke.*
- dEQP-VK.api.info.instance.*
- dEQP-VK.api.info.device.*
v2:
- Reject VkNativeBufferANDROID if the dma-buf's size is too small for
the VkImage.
- Stop abusing VkNativeBufferANDROID by passing it to vkAllocateMemory
during vkCreateImage. Instead, directly import its dma-buf during
vkCreateImage with anv_bo_cache_import(). [for jekstrand]
- Rebase onto Tapani's VK_EXT_debug_report changes.
- Drop `CPPFLAGS += $(top_srcdir)/include/android`. The dir does not
exist.
v3:
- Delete duplicate #include "anv_private.h". [per Tapani]
- Try to fix the Android-IA build in Android.vulkan.mk by following
Tapani's example.
v4:
- Unset EXEC_OBJECT_ASYNC and set EXEC_OBJECT_WRITE on the imported
gralloc buffer, just as we do for all other winsys buffers in
anv_wsi.c. [found by Tapani]
v5:
- Really fix the Android-IA build by ensuring that Android.vulkan.mk
uses Mesa' vulkan.h and not Android's. Insert -I$(MESA_TOP)/include
before -Iframeworks/native/vulkan/include. [for Tapani]
- In vkAcquireImageANDROID, submit signal operations to the
VkSemaphore and VkFence. [for zhou]
v6:
- Drop copy-paste duplication in vkGetSwapchainGrallocUsageANDROID().
[found by zhou]
- Improve comments in vkGetSwapchainGrallocUsageANDROID().
v7:
- Fix vkGetSwapchainGrallocUsageANDROID() to inspect its
VkImageUsageFlags parameter. [for tfiga]
- This fix regresses dEQP-VK.api.wsi.android.swapchain.*.image_usage
because dEQP wants to create swapchains with
VK_IMAGE_USAGE_STORAGE_BIT.
v8:
- Drop unneeded goto in vkAcquireImageANDROID. [for tfiga]
v8.1: (minor changes)
- Drop errant hunks added by rerere in anv_device.c.
- Drop explicit mention of VK_ANDROID_native_buffer in
anv_entrypoints_gen.py. [for jekstrand]
v9:
- Isolate as much Android code as possible, moving it from anv_image.c
to anv_android.c. Connect the files with anv_image_from_gralloc().
Remove VkNativeBufferANDROID params from all anv_image.c
funcs. [for krh]
- Replace some intel_loge() with vk_errorf() in anv_android.c.
- Use © in copyright line. [for krh]
Reviewed-by: Tapani Pälli <tapani.palli@intel.com> (v5)
Reviewed-by: Kristian H. Kristensen <hoegsberg@google.com> (v9)
Reviewed-by: Jason Ekstrand <jason@jlekstrand.net> (v9)
Cc: zhoucm1 <david1.zhou@amd.com>
Cc: Tomasz Figa <tfiga@chromium.org>
2016-11-14 16:13:51 -08:00
|
|
|
|
anv/image: Support creating uncompressed views of compressed images
In order to get support everywhere, this gets a bit complicated. On Sky
Lake and later, everything is fine because HALIGN/VALIGN are specified
in surface elements and are required to be at least 4 so any offsetting
we may need to do falls neatly within the heavy restrictions placed on
the X/Y Offset parameter of RENDER_SURFACE_STATE. On Broadwell and
earlier, HALIGN/VALIGN are specified in pixels and are hard-coded to
align to exactly the block size of the compressed texture. This means
that, when reinterpreted as a non-compressed texture, the tile offsets
may be anything and we can't rely on X/Y Offset.
In order to work around this issue, we fall back to linear where we can
trivially offset to whatever element we so choose. However, since
linear texturing performance is terrible, we create a tiled shadow copy
of the image to use for texturing. Whenever the user does a layout
transition from anything to SHADER_READ_ONLY_OPTIMAL, we use blorp to
copy the contents of the texture from the linear copy to the tiled
shadow copy. This assumes that the client will use the image far more
for texturing than as a storage image or render target.
Even though we don't need the shadow copy on Sky Lake, we implement it
this way first to make testing easier. Due to the hardware restriction
that ASTC must not be linear, ASTC does not work yet.
Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
2017-07-11 13:17:06 -07:00
|
|
|
/* If an image is created as BLOCK_TEXEL_VIEW_COMPATIBLE, then we need to
|
2017-07-11 15:32:30 -07:00
|
|
|
* fall back to linear on Broadwell and earlier because we aren't
|
|
|
|
|
* guaranteed that we can handle offsets correctly. On Sky Lake, the
|
|
|
|
|
* horizontal and vertical alignments are sufficiently high that we can
|
|
|
|
|
* just use RENDER_SURFACE_STATE::X/Y Offset.
|
anv/image: Support creating uncompressed views of compressed images
In order to get support everywhere, this gets a bit complicated. On Sky
Lake and later, everything is fine because HALIGN/VALIGN are specified
in surface elements and are required to be at least 4 so any offsetting
we may need to do falls neatly within the heavy restrictions placed on
the X/Y Offset parameter of RENDER_SURFACE_STATE. On Broadwell and
earlier, HALIGN/VALIGN are specified in pixels and are hard-coded to
align to exactly the block size of the compressed texture. This means
that, when reinterpreted as a non-compressed texture, the tile offsets
may be anything and we can't rely on X/Y Offset.
In order to work around this issue, we fall back to linear where we can
trivially offset to whatever element we so choose. However, since
linear texturing performance is terrible, we create a tiled shadow copy
of the image to use for texturing. Whenever the user does a layout
transition from anything to SHADER_READ_ONLY_OPTIMAL, we use blorp to
copy the contents of the texture from the linear copy to the tiled
shadow copy. This assumes that the client will use the image far more
for texturing than as a storage image or render target.
Even though we don't need the shadow copy on Sky Lake, we implement it
this way first to make testing easier. Due to the hardware restriction
that ASTC must not be linear, ASTC does not work yet.
Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
2017-07-11 13:17:06 -07:00
|
|
|
*/
|
|
|
|
|
bool needs_shadow = false;
|
2017-07-11 15:32:30 -07:00
|
|
|
if (dev->info.gen <= 8 &&
|
2018-09-27 08:00:53 +03:00
|
|
|
(image->create_flags & VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT) &&
|
|
|
|
|
image->tiling == VK_IMAGE_TILING_OPTIMAL) {
|
2017-07-19 12:14:19 +01:00
|
|
|
assert(isl_format_is_compressed(plane_format.isl_format));
|
anv/image: Support creating uncompressed views of compressed images
In order to get support everywhere, this gets a bit complicated. On Sky
Lake and later, everything is fine because HALIGN/VALIGN are specified
in surface elements and are required to be at least 4 so any offsetting
we may need to do falls neatly within the heavy restrictions placed on
the X/Y Offset parameter of RENDER_SURFACE_STATE. On Broadwell and
earlier, HALIGN/VALIGN are specified in pixels and are hard-coded to
align to exactly the block size of the compressed texture. This means
that, when reinterpreted as a non-compressed texture, the tile offsets
may be anything and we can't rely on X/Y Offset.
In order to work around this issue, we fall back to linear where we can
trivially offset to whatever element we so choose. However, since
linear texturing performance is terrible, we create a tiled shadow copy
of the image to use for texturing. Whenever the user does a layout
transition from anything to SHADER_READ_ONLY_OPTIMAL, we use blorp to
copy the contents of the texture from the linear copy to the tiled
shadow copy. This assumes that the client will use the image far more
for texturing than as a storage image or render target.
Even though we don't need the shadow copy on Sky Lake, we implement it
this way first to make testing easier. Due to the hardware restriction
that ASTC must not be linear, ASTC does not work yet.
Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
2017-07-11 13:17:06 -07:00
|
|
|
tiling_flags = ISL_TILING_LINEAR_BIT;
|
|
|
|
|
needs_shadow = true;
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-07 09:22:49 -08:00
|
|
|
ok = isl_surf_init(&dev->isl_dev, &anv_surf->isl,
|
2018-09-27 08:00:53 +03:00
|
|
|
.dim = vk_to_isl_surf_dim[image->type],
|
2017-07-19 12:14:19 +01:00
|
|
|
.format = plane_format.isl_format,
|
|
|
|
|
.width = image->extent.width / plane_format.denominator_scales[0],
|
|
|
|
|
.height = image->extent.height / plane_format.denominator_scales[1],
|
2016-03-22 10:53:37 -07:00
|
|
|
.depth = image->extent.depth,
|
2018-09-27 08:00:53 +03:00
|
|
|
.levels = image->levels,
|
|
|
|
|
.array_len = image->array_size,
|
|
|
|
|
.samples = image->samples,
|
2018-09-05 14:02:12 -05:00
|
|
|
.min_alignment_B = 0,
|
2018-09-27 08:00:53 +03:00
|
|
|
.row_pitch_B = stride,
|
anv: Implement VK_ANDROID_native_buffer (v9)
This implementation is correct (afaict), but takes two shortcuts
regarding the import/export of Android sync fds.
Shortcut 1. When Android calls vkAcquireImageANDROID to import a sync
fd into a VkSemaphore or VkFence, the driver instead simply blocks on
the sync fd, then puts the VkSemaphore or VkFence into the signalled
state. Thanks to implicit sync, this produces correct behavior (with
extra latency overhead, perhaps) despite its ugliness.
Shortcut 2. When Android calls vkQueueSignalReleaseImageANDROID to export
a collection of wait semaphores as a sync fd, the driver instead
submits the semaphores to the queue, then returns sync fd -1, which
informs the caller that no additional synchronization is needed.
Again, thanks to implicit sync, this produces correct behavior (with
extra batch submission overhead) despite its ugliness.
I chose to take the shortcuts instead of properly importing/exporting
the sync fds for two reasons:
Reason 1. I've already tested this patch with dEQP and with demos
apps. It works. I wanted to get the tested patches into the tree now,
and polish the implementation afterwards.
Reason 2. I want to run this on a 3.18 kernel (gasp!). In 3.18, i915
supports neither Android's sync_fence, nor upstream's sync_file, nor
drm_syncobj. Again, I tested these patches on Android with a 3.18
kernel and they work.
I plan to quickly follow-up with patches that remove the shortcuts and
properly import/export the sync fds.
Non-Testing
===========
I did not test at all using the Android.mk buildsystem. I may have broke
it. Please test and review that.
Testing
=======
I tested with 64-bit ARC++ on a Skylake Chromebook and a 3.18 kernel.
The following pass (as of patchset v9):
- a little spinning cube demo APK
- several Sascha demos
- dEQP-VK.info.*
- dEQP-VK.api.wsi.android.*
(except dEQP-VK.api.wsi.android.swapchain.*.image_usage, because
dEQP wants to create swapchains with VK_IMAGE_USAGE_STORAGE_BIT)
- dEQP-VK.api.smoke.*
- dEQP-VK.api.info.instance.*
- dEQP-VK.api.info.device.*
v2:
- Reject VkNativeBufferANDROID if the dma-buf's size is too small for
the VkImage.
- Stop abusing VkNativeBufferANDROID by passing it to vkAllocateMemory
during vkCreateImage. Instead, directly import its dma-buf during
vkCreateImage with anv_bo_cache_import(). [for jekstrand]
- Rebase onto Tapani's VK_EXT_debug_report changes.
- Drop `CPPFLAGS += $(top_srcdir)/include/android`. The dir does not
exist.
v3:
- Delete duplicate #include "anv_private.h". [per Tapani]
- Try to fix the Android-IA build in Android.vulkan.mk by following
Tapani's example.
v4:
- Unset EXEC_OBJECT_ASYNC and set EXEC_OBJECT_WRITE on the imported
gralloc buffer, just as we do for all other winsys buffers in
anv_wsi.c. [found by Tapani]
v5:
- Really fix the Android-IA build by ensuring that Android.vulkan.mk
uses Mesa' vulkan.h and not Android's. Insert -I$(MESA_TOP)/include
before -Iframeworks/native/vulkan/include. [for Tapani]
- In vkAcquireImageANDROID, submit signal operations to the
VkSemaphore and VkFence. [for zhou]
v6:
- Drop copy-paste duplication in vkGetSwapchainGrallocUsageANDROID().
[found by zhou]
- Improve comments in vkGetSwapchainGrallocUsageANDROID().
v7:
- Fix vkGetSwapchainGrallocUsageANDROID() to inspect its
VkImageUsageFlags parameter. [for tfiga]
- This fix regresses dEQP-VK.api.wsi.android.swapchain.*.image_usage
because dEQP wants to create swapchains with
VK_IMAGE_USAGE_STORAGE_BIT.
v8:
- Drop unneeded goto in vkAcquireImageANDROID. [for tfiga]
v8.1: (minor changes)
- Drop errant hunks added by rerere in anv_device.c.
- Drop explicit mention of VK_ANDROID_native_buffer in
anv_entrypoints_gen.py. [for jekstrand]
v9:
- Isolate as much Android code as possible, moving it from anv_image.c
to anv_android.c. Connect the files with anv_image_from_gralloc().
Remove VkNativeBufferANDROID params from all anv_image.c
funcs. [for krh]
- Replace some intel_loge() with vk_errorf() in anv_android.c.
- Use © in copyright line. [for krh]
Reviewed-by: Tapani Pälli <tapani.palli@intel.com> (v5)
Reviewed-by: Kristian H. Kristensen <hoegsberg@google.com> (v9)
Reviewed-by: Jason Ekstrand <jason@jlekstrand.net> (v9)
Cc: zhoucm1 <david1.zhou@amd.com>
Cc: Tomasz Figa <tfiga@chromium.org>
2016-11-14 16:13:51 -08:00
|
|
|
.usage = usage,
|
2015-12-07 08:50:28 -08:00
|
|
|
.tiling_flags = tiling_flags);
|
2015-06-26 18:48:34 -07:00
|
|
|
|
2018-01-12 09:41:17 +01:00
|
|
|
if (!ok)
|
|
|
|
|
return VK_ERROR_OUT_OF_DEVICE_MEMORY;
|
2015-12-07 08:53:43 -08:00
|
|
|
|
2017-07-19 12:14:19 +01:00
|
|
|
image->planes[plane].aux_usage = ISL_AUX_USAGE_NONE;
|
|
|
|
|
|
|
|
|
|
add_surface(image, anv_surf, plane);
|
2016-10-06 15:21:49 -07:00
|
|
|
|
anv/image: Support creating uncompressed views of compressed images
In order to get support everywhere, this gets a bit complicated. On Sky
Lake and later, everything is fine because HALIGN/VALIGN are specified
in surface elements and are required to be at least 4 so any offsetting
we may need to do falls neatly within the heavy restrictions placed on
the X/Y Offset parameter of RENDER_SURFACE_STATE. On Broadwell and
earlier, HALIGN/VALIGN are specified in pixels and are hard-coded to
align to exactly the block size of the compressed texture. This means
that, when reinterpreted as a non-compressed texture, the tile offsets
may be anything and we can't rely on X/Y Offset.
In order to work around this issue, we fall back to linear where we can
trivially offset to whatever element we so choose. However, since
linear texturing performance is terrible, we create a tiled shadow copy
of the image to use for texturing. Whenever the user does a layout
transition from anything to SHADER_READ_ONLY_OPTIMAL, we use blorp to
copy the contents of the texture from the linear copy to the tiled
shadow copy. This assumes that the client will use the image far more
for texturing than as a storage image or render target.
Even though we don't need the shadow copy on Sky Lake, we implement it
this way first to make testing easier. Due to the hardware restriction
that ASTC must not be linear, ASTC does not work yet.
Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
2017-07-11 13:17:06 -07:00
|
|
|
/* If an image is created as BLOCK_TEXEL_VIEW_COMPATIBLE, then we need to
|
|
|
|
|
* create an identical tiled shadow surface for use while texturing so we
|
|
|
|
|
* don't get garbage performance.
|
|
|
|
|
*/
|
|
|
|
|
if (needs_shadow) {
|
|
|
|
|
assert(aspect == VK_IMAGE_ASPECT_COLOR_BIT);
|
|
|
|
|
assert(tiling_flags == ISL_TILING_LINEAR_BIT);
|
|
|
|
|
|
2017-07-19 12:14:19 +01:00
|
|
|
ok = isl_surf_init(&dev->isl_dev, &image->planes[plane].shadow_surface.isl,
|
2018-09-27 08:00:53 +03:00
|
|
|
.dim = vk_to_isl_surf_dim[image->type],
|
2017-07-19 12:14:19 +01:00
|
|
|
.format = plane_format.isl_format,
|
anv/image: Support creating uncompressed views of compressed images
In order to get support everywhere, this gets a bit complicated. On Sky
Lake and later, everything is fine because HALIGN/VALIGN are specified
in surface elements and are required to be at least 4 so any offsetting
we may need to do falls neatly within the heavy restrictions placed on
the X/Y Offset parameter of RENDER_SURFACE_STATE. On Broadwell and
earlier, HALIGN/VALIGN are specified in pixels and are hard-coded to
align to exactly the block size of the compressed texture. This means
that, when reinterpreted as a non-compressed texture, the tile offsets
may be anything and we can't rely on X/Y Offset.
In order to work around this issue, we fall back to linear where we can
trivially offset to whatever element we so choose. However, since
linear texturing performance is terrible, we create a tiled shadow copy
of the image to use for texturing. Whenever the user does a layout
transition from anything to SHADER_READ_ONLY_OPTIMAL, we use blorp to
copy the contents of the texture from the linear copy to the tiled
shadow copy. This assumes that the client will use the image far more
for texturing than as a storage image or render target.
Even though we don't need the shadow copy on Sky Lake, we implement it
this way first to make testing easier. Due to the hardware restriction
that ASTC must not be linear, ASTC does not work yet.
Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
2017-07-11 13:17:06 -07:00
|
|
|
.width = image->extent.width,
|
|
|
|
|
.height = image->extent.height,
|
|
|
|
|
.depth = image->extent.depth,
|
2018-09-27 08:00:53 +03:00
|
|
|
.levels = image->levels,
|
|
|
|
|
.array_len = image->array_size,
|
|
|
|
|
.samples = image->samples,
|
2018-09-05 14:02:12 -05:00
|
|
|
.min_alignment_B = 0,
|
2018-09-27 08:00:53 +03:00
|
|
|
.row_pitch_B = stride,
|
anv: Implement VK_ANDROID_native_buffer (v9)
This implementation is correct (afaict), but takes two shortcuts
regarding the import/export of Android sync fds.
Shortcut 1. When Android calls vkAcquireImageANDROID to import a sync
fd into a VkSemaphore or VkFence, the driver instead simply blocks on
the sync fd, then puts the VkSemaphore or VkFence into the signalled
state. Thanks to implicit sync, this produces correct behavior (with
extra latency overhead, perhaps) despite its ugliness.
Shortcut 2. When Android calls vkQueueSignalReleaseImageANDROID to export
a collection of wait semaphores as a sync fd, the driver instead
submits the semaphores to the queue, then returns sync fd -1, which
informs the caller that no additional synchronization is needed.
Again, thanks to implicit sync, this produces correct behavior (with
extra batch submission overhead) despite its ugliness.
I chose to take the shortcuts instead of properly importing/exporting
the sync fds for two reasons:
Reason 1. I've already tested this patch with dEQP and with demos
apps. It works. I wanted to get the tested patches into the tree now,
and polish the implementation afterwards.
Reason 2. I want to run this on a 3.18 kernel (gasp!). In 3.18, i915
supports neither Android's sync_fence, nor upstream's sync_file, nor
drm_syncobj. Again, I tested these patches on Android with a 3.18
kernel and they work.
I plan to quickly follow-up with patches that remove the shortcuts and
properly import/export the sync fds.
Non-Testing
===========
I did not test at all using the Android.mk buildsystem. I may have broke
it. Please test and review that.
Testing
=======
I tested with 64-bit ARC++ on a Skylake Chromebook and a 3.18 kernel.
The following pass (as of patchset v9):
- a little spinning cube demo APK
- several Sascha demos
- dEQP-VK.info.*
- dEQP-VK.api.wsi.android.*
(except dEQP-VK.api.wsi.android.swapchain.*.image_usage, because
dEQP wants to create swapchains with VK_IMAGE_USAGE_STORAGE_BIT)
- dEQP-VK.api.smoke.*
- dEQP-VK.api.info.instance.*
- dEQP-VK.api.info.device.*
v2:
- Reject VkNativeBufferANDROID if the dma-buf's size is too small for
the VkImage.
- Stop abusing VkNativeBufferANDROID by passing it to vkAllocateMemory
during vkCreateImage. Instead, directly import its dma-buf during
vkCreateImage with anv_bo_cache_import(). [for jekstrand]
- Rebase onto Tapani's VK_EXT_debug_report changes.
- Drop `CPPFLAGS += $(top_srcdir)/include/android`. The dir does not
exist.
v3:
- Delete duplicate #include "anv_private.h". [per Tapani]
- Try to fix the Android-IA build in Android.vulkan.mk by following
Tapani's example.
v4:
- Unset EXEC_OBJECT_ASYNC and set EXEC_OBJECT_WRITE on the imported
gralloc buffer, just as we do for all other winsys buffers in
anv_wsi.c. [found by Tapani]
v5:
- Really fix the Android-IA build by ensuring that Android.vulkan.mk
uses Mesa' vulkan.h and not Android's. Insert -I$(MESA_TOP)/include
before -Iframeworks/native/vulkan/include. [for Tapani]
- In vkAcquireImageANDROID, submit signal operations to the
VkSemaphore and VkFence. [for zhou]
v6:
- Drop copy-paste duplication in vkGetSwapchainGrallocUsageANDROID().
[found by zhou]
- Improve comments in vkGetSwapchainGrallocUsageANDROID().
v7:
- Fix vkGetSwapchainGrallocUsageANDROID() to inspect its
VkImageUsageFlags parameter. [for tfiga]
- This fix regresses dEQP-VK.api.wsi.android.swapchain.*.image_usage
because dEQP wants to create swapchains with
VK_IMAGE_USAGE_STORAGE_BIT.
v8:
- Drop unneeded goto in vkAcquireImageANDROID. [for tfiga]
v8.1: (minor changes)
- Drop errant hunks added by rerere in anv_device.c.
- Drop explicit mention of VK_ANDROID_native_buffer in
anv_entrypoints_gen.py. [for jekstrand]
v9:
- Isolate as much Android code as possible, moving it from anv_image.c
to anv_android.c. Connect the files with anv_image_from_gralloc().
Remove VkNativeBufferANDROID params from all anv_image.c
funcs. [for krh]
- Replace some intel_loge() with vk_errorf() in anv_android.c.
- Use © in copyright line. [for krh]
Reviewed-by: Tapani Pälli <tapani.palli@intel.com> (v5)
Reviewed-by: Kristian H. Kristensen <hoegsberg@google.com> (v9)
Reviewed-by: Jason Ekstrand <jason@jlekstrand.net> (v9)
Cc: zhoucm1 <david1.zhou@amd.com>
Cc: Tomasz Figa <tfiga@chromium.org>
2016-11-14 16:13:51 -08:00
|
|
|
.usage = usage,
|
anv/image: Support creating uncompressed views of compressed images
In order to get support everywhere, this gets a bit complicated. On Sky
Lake and later, everything is fine because HALIGN/VALIGN are specified
in surface elements and are required to be at least 4 so any offsetting
we may need to do falls neatly within the heavy restrictions placed on
the X/Y Offset parameter of RENDER_SURFACE_STATE. On Broadwell and
earlier, HALIGN/VALIGN are specified in pixels and are hard-coded to
align to exactly the block size of the compressed texture. This means
that, when reinterpreted as a non-compressed texture, the tile offsets
may be anything and we can't rely on X/Y Offset.
In order to work around this issue, we fall back to linear where we can
trivially offset to whatever element we so choose. However, since
linear texturing performance is terrible, we create a tiled shadow copy
of the image to use for texturing. Whenever the user does a layout
transition from anything to SHADER_READ_ONLY_OPTIMAL, we use blorp to
copy the contents of the texture from the linear copy to the tiled
shadow copy. This assumes that the client will use the image far more
for texturing than as a storage image or render target.
Even though we don't need the shadow copy on Sky Lake, we implement it
this way first to make testing easier. Due to the hardware restriction
that ASTC must not be linear, ASTC does not work yet.
Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
2017-07-11 13:17:06 -07:00
|
|
|
.tiling_flags = ISL_TILING_ANY_MASK);
|
|
|
|
|
|
|
|
|
|
/* isl_surf_init() will fail only if provided invalid input. Invalid input
|
|
|
|
|
* is illegal in Vulkan.
|
|
|
|
|
*/
|
|
|
|
|
assert(ok);
|
|
|
|
|
|
2017-07-19 12:14:19 +01:00
|
|
|
add_surface(image, &image->planes[plane].shadow_surface, plane);
|
anv/image: Support creating uncompressed views of compressed images
In order to get support everywhere, this gets a bit complicated. On Sky
Lake and later, everything is fine because HALIGN/VALIGN are specified
in surface elements and are required to be at least 4 so any offsetting
we may need to do falls neatly within the heavy restrictions placed on
the X/Y Offset parameter of RENDER_SURFACE_STATE. On Broadwell and
earlier, HALIGN/VALIGN are specified in pixels and are hard-coded to
align to exactly the block size of the compressed texture. This means
that, when reinterpreted as a non-compressed texture, the tile offsets
may be anything and we can't rely on X/Y Offset.
In order to work around this issue, we fall back to linear where we can
trivially offset to whatever element we so choose. However, since
linear texturing performance is terrible, we create a tiled shadow copy
of the image to use for texturing. Whenever the user does a layout
transition from anything to SHADER_READ_ONLY_OPTIMAL, we use blorp to
copy the contents of the texture from the linear copy to the tiled
shadow copy. This assumes that the client will use the image far more
for texturing than as a storage image or render target.
Even though we don't need the shadow copy on Sky Lake, we implement it
this way first to make testing easier. Due to the hardware restriction
that ASTC must not be linear, ASTC does not work yet.
Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
2017-07-11 13:17:06 -07:00
|
|
|
}
|
|
|
|
|
|
2016-10-06 15:21:49 -07:00
|
|
|
/* Add a HiZ surface to a depth buffer that will be used for rendering.
|
|
|
|
|
*/
|
2016-10-24 22:03:45 -07:00
|
|
|
if (aspect == VK_IMAGE_ASPECT_DEPTH_BIT) {
|
2017-02-21 18:17:59 -08:00
|
|
|
/* We don't advertise that depth buffers could be used as storage
|
|
|
|
|
* images.
|
|
|
|
|
*/
|
|
|
|
|
assert(!(image->usage & VK_IMAGE_USAGE_STORAGE_BIT));
|
|
|
|
|
|
2016-10-06 15:21:49 -07:00
|
|
|
/* Allow the user to control HiZ enabling. Disable by default on gen7
|
|
|
|
|
* because resolves are not currently implemented pre-BDW.
|
|
|
|
|
*/
|
2016-10-24 22:03:45 -07:00
|
|
|
if (!(image->usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) {
|
|
|
|
|
/* It will never be used as an attachment, HiZ is pointless. */
|
2017-03-13 08:10:38 -07:00
|
|
|
} else if (dev->info.gen == 7) {
|
2017-08-25 09:50:11 +03:00
|
|
|
anv_perf_warn(dev->instance, image, "Implement gen7 HiZ");
|
2018-09-27 08:00:53 +03:00
|
|
|
} else if (image->levels > 1) {
|
2017-08-25 09:50:11 +03:00
|
|
|
anv_perf_warn(dev->instance, image, "Enable multi-LOD HiZ");
|
2018-09-27 08:00:53 +03:00
|
|
|
} else if (image->array_size > 1) {
|
2017-08-25 09:50:11 +03:00
|
|
|
anv_perf_warn(dev->instance, image,
|
|
|
|
|
"Implement multi-arrayLayer HiZ clears and resolves");
|
2018-09-27 08:00:53 +03:00
|
|
|
} else if (dev->info.gen == 8 && image->samples > 1) {
|
2017-08-25 09:50:11 +03:00
|
|
|
anv_perf_warn(dev->instance, image, "Enable gen8 multisampled HiZ");
|
2017-03-13 14:23:34 -07:00
|
|
|
} else if (!unlikely(INTEL_DEBUG & DEBUG_NO_HIZ)) {
|
2018-09-05 14:02:12 -05:00
|
|
|
assert(image->planes[plane].aux_surface.isl.size_B == 0);
|
2017-07-19 12:14:19 +01:00
|
|
|
ok = isl_surf_get_hiz_surf(&dev->isl_dev,
|
|
|
|
|
&image->planes[plane].surface.isl,
|
|
|
|
|
&image->planes[plane].aux_surface.isl);
|
2017-02-17 13:48:11 -08:00
|
|
|
assert(ok);
|
2017-07-19 12:14:19 +01:00
|
|
|
add_surface(image, &image->planes[plane].aux_surface, plane);
|
|
|
|
|
image->planes[plane].aux_usage = ISL_AUX_USAGE_HIZ;
|
2016-10-06 15:21:49 -07:00
|
|
|
}
|
2018-09-27 08:00:53 +03:00
|
|
|
} else if ((aspect & VK_IMAGE_ASPECT_ANY_COLOR_BIT_ANV) && image->samples == 1) {
|
2017-07-19 12:14:19 +01:00
|
|
|
/* TODO: Disallow compression with :
|
|
|
|
|
*
|
|
|
|
|
* 1) non multiplanar images (We appear to hit a sampler bug with
|
|
|
|
|
* CCS & R16G16 format. Putting the clear state a page/4096bytes
|
|
|
|
|
* further fixes the issue).
|
|
|
|
|
*
|
|
|
|
|
* 2) alias images, because they might be aliases of images
|
|
|
|
|
* described in 1)
|
|
|
|
|
*
|
|
|
|
|
* 3) compression disabled by debug
|
|
|
|
|
*/
|
|
|
|
|
const bool allow_compression =
|
|
|
|
|
image->n_planes == 1 &&
|
2018-09-27 08:00:53 +03:00
|
|
|
(image->create_flags & VK_IMAGE_CREATE_ALIAS_BIT) == 0 &&
|
2017-07-19 12:14:19 +01:00
|
|
|
likely((INTEL_DEBUG & DEBUG_NO_RBC) == 0);
|
|
|
|
|
|
|
|
|
|
if (allow_compression) {
|
2018-09-05 14:02:12 -05:00
|
|
|
assert(image->planes[plane].aux_surface.isl.size_B == 0);
|
2017-07-19 12:14:19 +01:00
|
|
|
ok = isl_surf_get_ccs_surf(&dev->isl_dev,
|
|
|
|
|
&image->planes[plane].surface.isl,
|
|
|
|
|
&image->planes[plane].aux_surface.isl, 0);
|
2016-10-25 10:59:03 -07:00
|
|
|
if (ok) {
|
2017-07-05 12:15:24 -07:00
|
|
|
|
|
|
|
|
/* Disable CCS when it is not useful (i.e., when you can't render
|
|
|
|
|
* to the image with CCS enabled).
|
|
|
|
|
*/
|
2017-07-19 12:14:19 +01:00
|
|
|
if (!isl_format_supports_rendering(&dev->info,
|
|
|
|
|
plane_format.isl_format)) {
|
2017-07-05 12:15:24 -07:00
|
|
|
/* While it may be technically possible to enable CCS for this
|
|
|
|
|
* image, we currently don't have things hooked up to get it
|
|
|
|
|
* working.
|
|
|
|
|
*/
|
2017-08-25 09:50:11 +03:00
|
|
|
anv_perf_warn(dev->instance, image,
|
|
|
|
|
"This image format doesn't support rendering. "
|
2017-07-05 12:15:24 -07:00
|
|
|
"Not allocating an CCS buffer.");
|
2018-09-05 14:02:12 -05:00
|
|
|
image->planes[plane].aux_surface.isl.size_B = 0;
|
2017-07-05 12:15:24 -07:00
|
|
|
return VK_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
2017-07-19 12:14:19 +01:00
|
|
|
add_surface(image, &image->planes[plane].aux_surface, plane);
|
2018-11-01 16:53:48 +00:00
|
|
|
add_aux_state_tracking_buffer(image, plane, dev);
|
2016-10-25 10:59:03 -07:00
|
|
|
|
|
|
|
|
/* For images created without MUTABLE_FORMAT_BIT set, we know that
|
|
|
|
|
* they will always be used with the original format. In
|
|
|
|
|
* particular, they will always be used with a format that
|
2017-02-01 12:05:07 -08:00
|
|
|
* supports color compression. If it's never used as a storage
|
|
|
|
|
* image, then it will only be used through the sampler or the as
|
|
|
|
|
* a render target. This means that it's safe to just leave
|
|
|
|
|
* compression on at all times for these formats.
|
2016-10-25 10:59:03 -07:00
|
|
|
*/
|
2018-09-27 08:00:53 +03:00
|
|
|
if (!(image->usage & VK_IMAGE_USAGE_STORAGE_BIT) &&
|
|
|
|
|
image->ccs_e_compatible) {
|
2017-07-19 12:14:19 +01:00
|
|
|
image->planes[plane].aux_usage = ISL_AUX_USAGE_CCS_E;
|
2016-10-25 10:59:03 -07:00
|
|
|
}
|
|
|
|
|
}
|
2016-10-24 22:03:45 -07:00
|
|
|
}
|
2018-09-27 08:00:53 +03:00
|
|
|
} else if ((aspect & VK_IMAGE_ASPECT_ANY_COLOR_BIT_ANV) && image->samples > 1) {
|
|
|
|
|
assert(!(image->usage & VK_IMAGE_USAGE_STORAGE_BIT));
|
2018-09-05 14:02:12 -05:00
|
|
|
assert(image->planes[plane].aux_surface.isl.size_B == 0);
|
2017-07-19 12:14:19 +01:00
|
|
|
ok = isl_surf_get_mcs_surf(&dev->isl_dev,
|
|
|
|
|
&image->planes[plane].surface.isl,
|
|
|
|
|
&image->planes[plane].aux_surface.isl);
|
2017-02-17 14:14:48 -08:00
|
|
|
if (ok) {
|
2017-07-19 12:14:19 +01:00
|
|
|
add_surface(image, &image->planes[plane].aux_surface, plane);
|
2018-11-01 16:53:48 +00:00
|
|
|
add_aux_state_tracking_buffer(image, plane, dev);
|
2017-07-19 12:14:19 +01:00
|
|
|
image->planes[plane].aux_usage = ISL_AUX_USAGE_MCS;
|
2017-02-17 14:14:48 -08:00
|
|
|
}
|
2016-10-06 15:21:49 -07:00
|
|
|
}
|
2015-12-02 16:46:16 -08:00
|
|
|
|
2017-07-19 12:14:19 +01:00
|
|
|
assert((image->planes[plane].offset + image->planes[plane].size) == image->size);
|
|
|
|
|
|
|
|
|
|
/* Upper bound of the last surface should be smaller than the plane's
|
|
|
|
|
* size.
|
|
|
|
|
*/
|
|
|
|
|
assert((MAX2(image->planes[plane].surface.offset,
|
|
|
|
|
image->planes[plane].aux_surface.offset) +
|
2018-09-05 14:02:12 -05:00
|
|
|
(image->planes[plane].aux_surface.isl.size_B > 0 ?
|
|
|
|
|
image->planes[plane].aux_surface.isl.size_B :
|
|
|
|
|
image->planes[plane].surface.isl.size_B)) <=
|
2017-07-19 12:14:19 +01:00
|
|
|
(image->planes[plane].offset + image->planes[plane].size));
|
|
|
|
|
|
2018-09-05 14:02:12 -05:00
|
|
|
if (image->planes[plane].aux_surface.isl.size_B) {
|
2017-07-19 12:14:19 +01:00
|
|
|
/* assert(image->planes[plane].fast_clear_state_offset == */
|
2018-09-05 14:02:12 -05:00
|
|
|
/* (image->planes[plane].aux_surface.offset + image->planes[plane].aux_surface.isl.size_B)); */
|
2017-07-19 12:14:19 +01:00
|
|
|
assert(image->planes[plane].fast_clear_state_offset <
|
|
|
|
|
(image->planes[plane].offset + image->planes[plane].size));
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-26 21:27:54 -07:00
|
|
|
return VK_SUCCESS;
|
2015-06-26 18:48:34 -07:00
|
|
|
}
|
|
|
|
|
|
2017-11-13 16:44:07 -08:00
|
|
|
static uint32_t
|
|
|
|
|
score_drm_format_mod(uint64_t modifier)
|
|
|
|
|
{
|
|
|
|
|
switch (modifier) {
|
|
|
|
|
case DRM_FORMAT_MOD_LINEAR: return 1;
|
|
|
|
|
case I915_FORMAT_MOD_X_TILED: return 2;
|
|
|
|
|
case I915_FORMAT_MOD_Y_TILED: return 3;
|
2018-02-13 14:26:05 -08:00
|
|
|
case I915_FORMAT_MOD_Y_TILED_CCS: return 4;
|
2017-11-13 16:44:07 -08:00
|
|
|
default: unreachable("bad DRM format modifier");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const struct isl_drm_modifier_info *
|
|
|
|
|
choose_drm_format_mod(const struct anv_physical_device *device,
|
|
|
|
|
uint32_t modifier_count, const uint64_t *modifiers)
|
|
|
|
|
{
|
|
|
|
|
uint64_t best_mod = UINT64_MAX;
|
|
|
|
|
uint32_t best_score = 0;
|
|
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < modifier_count; ++i) {
|
|
|
|
|
uint32_t score = score_drm_format_mod(modifiers[i]);
|
|
|
|
|
if (score > best_score) {
|
|
|
|
|
best_mod = modifiers[i];
|
|
|
|
|
best_score = score;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (best_score > 0)
|
|
|
|
|
return isl_drm_modifier_get_info(best_mod);
|
|
|
|
|
else
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-26 20:12:42 -07:00
|
|
|
VkResult
|
|
|
|
|
anv_image_create(VkDevice _device,
|
|
|
|
|
const struct anv_image_create_info *create_info,
|
2015-12-02 03:28:27 -08:00
|
|
|
const VkAllocationCallbacks* alloc,
|
2015-06-26 20:12:42 -07:00
|
|
|
VkImage *pImage)
|
2015-05-08 22:32:37 -07:00
|
|
|
{
|
2015-07-09 20:24:07 -07:00
|
|
|
ANV_FROM_HANDLE(anv_device, device, _device);
|
2015-06-26 20:06:08 -07:00
|
|
|
const VkImageCreateInfo *pCreateInfo = create_info->vk_info;
|
2017-11-15 22:11:46 -08:00
|
|
|
const struct isl_drm_modifier_info *isl_mod_info = NULL;
|
2015-06-26 21:27:54 -07:00
|
|
|
struct anv_image *image = NULL;
|
|
|
|
|
VkResult r;
|
2015-05-08 22:32:37 -07:00
|
|
|
|
|
|
|
|
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO);
|
|
|
|
|
|
2017-11-15 22:11:46 -08:00
|
|
|
const struct wsi_image_create_info *wsi_info =
|
|
|
|
|
vk_find_struct_const(pCreateInfo->pNext, WSI_IMAGE_CREATE_INFO_MESA);
|
2017-11-13 16:44:07 -08:00
|
|
|
if (wsi_info && wsi_info->modifier_count > 0) {
|
|
|
|
|
isl_mod_info = choose_drm_format_mod(&device->instance->physicalDevice,
|
|
|
|
|
wsi_info->modifier_count,
|
|
|
|
|
wsi_info->modifiers);
|
|
|
|
|
assert(isl_mod_info);
|
|
|
|
|
}
|
2017-11-15 22:11:46 -08:00
|
|
|
|
2015-06-26 21:27:54 -07:00
|
|
|
anv_assert(pCreateInfo->mipLevels > 0);
|
2015-12-01 12:52:56 -08:00
|
|
|
anv_assert(pCreateInfo->arrayLayers > 0);
|
2016-01-22 17:16:20 -08:00
|
|
|
anv_assert(pCreateInfo->samples > 0);
|
2015-06-26 09:05:46 -07:00
|
|
|
anv_assert(pCreateInfo->extent.width > 0);
|
|
|
|
|
anv_assert(pCreateInfo->extent.height > 0);
|
2015-06-26 21:27:54 -07:00
|
|
|
anv_assert(pCreateInfo->extent.depth > 0);
|
2015-06-10 21:04:51 -07:00
|
|
|
|
2017-07-11 08:59:06 -07:00
|
|
|
image = vk_zalloc2(&device->alloc, alloc, sizeof(*image), 8,
|
|
|
|
|
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
|
2015-06-26 18:48:34 -07:00
|
|
|
if (!image)
|
|
|
|
|
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
|
2015-06-26 09:17:52 -07:00
|
|
|
|
2015-06-26 18:48:34 -07:00
|
|
|
image->type = pCreateInfo->imageType;
|
|
|
|
|
image->extent = pCreateInfo->extent;
|
2015-12-31 12:39:34 -08:00
|
|
|
image->vk_format = pCreateInfo->format;
|
2017-07-19 12:14:19 +01:00
|
|
|
image->format = anv_get_format(pCreateInfo->format);
|
2016-05-13 16:47:39 -07:00
|
|
|
image->aspects = vk_format_aspects(image->vk_format);
|
2015-06-26 21:27:54 -07:00
|
|
|
image->levels = pCreateInfo->mipLevels;
|
2015-12-01 12:52:56 -08:00
|
|
|
image->array_size = pCreateInfo->arrayLayers;
|
2016-01-20 16:34:23 -08:00
|
|
|
image->samples = pCreateInfo->samples;
|
2016-10-07 22:07:04 -07:00
|
|
|
image->usage = pCreateInfo->usage;
|
2018-08-21 11:12:37 +03:00
|
|
|
image->create_flags = pCreateInfo->flags;
|
2016-01-01 14:09:17 -08:00
|
|
|
image->tiling = pCreateInfo->tiling;
|
2017-09-20 13:16:26 -07:00
|
|
|
image->disjoint = pCreateInfo->flags & VK_IMAGE_CREATE_DISJOINT_BIT;
|
2018-01-24 19:47:14 -08:00
|
|
|
image->needs_set_tiling = wsi_info && wsi_info->scanout;
|
2017-11-13 16:44:07 -08:00
|
|
|
image->drm_format_mod = isl_mod_info ? isl_mod_info->modifier :
|
|
|
|
|
DRM_FORMAT_MOD_INVALID;
|
2017-07-19 12:14:19 +01:00
|
|
|
|
2018-11-08 10:37:12 +02:00
|
|
|
/* In case of external format, We don't know format yet,
|
|
|
|
|
* so skip the rest for now.
|
|
|
|
|
*/
|
|
|
|
|
if (create_info->external_format) {
|
|
|
|
|
image->external_format = true;
|
|
|
|
|
*pImage = anv_image_to_handle(image);
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
2017-07-19 12:14:19 +01:00
|
|
|
const struct anv_format *format = anv_get_format(image->vk_format);
|
|
|
|
|
assert(format != NULL);
|
|
|
|
|
|
2017-11-06 18:51:53 -08:00
|
|
|
const isl_tiling_flags_t isl_tiling_flags =
|
2018-01-24 19:47:14 -08:00
|
|
|
choose_isl_tiling_flags(create_info, isl_mod_info,
|
|
|
|
|
image->needs_set_tiling);
|
2017-11-06 18:51:53 -08:00
|
|
|
|
2017-07-19 12:14:19 +01:00
|
|
|
image->n_planes = format->n_planes;
|
2015-06-26 09:17:52 -07:00
|
|
|
|
2018-09-27 08:00:53 +03:00
|
|
|
const VkImageFormatListCreateInfoKHR *fmt_list =
|
|
|
|
|
vk_find_struct_const(pCreateInfo->pNext,
|
|
|
|
|
IMAGE_FORMAT_LIST_CREATE_INFO_KHR);
|
|
|
|
|
|
|
|
|
|
image->ccs_e_compatible =
|
|
|
|
|
all_formats_ccs_e_compatible(&device->info, fmt_list, image);
|
|
|
|
|
|
2016-05-13 16:47:39 -07:00
|
|
|
uint32_t b;
|
|
|
|
|
for_each_bit(b, image->aspects) {
|
2018-09-27 08:00:53 +03:00
|
|
|
r = make_surface(device, image, create_info->stride, isl_tiling_flags,
|
|
|
|
|
create_info->isl_extra_usage_flags, (1 << b));
|
2015-06-26 21:27:54 -07:00
|
|
|
if (r != VK_SUCCESS)
|
|
|
|
|
goto fail;
|
2015-05-22 22:59:12 -07:00
|
|
|
}
|
2015-05-08 22:32:37 -07:00
|
|
|
|
2015-07-09 20:24:07 -07:00
|
|
|
*pImage = anv_image_to_handle(image);
|
2015-05-08 22:32:37 -07:00
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
2015-06-26 21:27:54 -07:00
|
|
|
|
|
|
|
|
fail:
|
|
|
|
|
if (image)
|
2016-10-14 13:31:35 +10:00
|
|
|
vk_free2(&device->alloc, alloc, image);
|
2015-06-26 21:27:54 -07:00
|
|
|
|
|
|
|
|
return r;
|
2015-05-08 22:32:37 -07:00
|
|
|
}
|
|
|
|
|
|
2019-03-25 15:02:47 +00:00
|
|
|
static struct anv_image *
|
|
|
|
|
anv_swapchain_get_image(VkSwapchainKHR swapchain,
|
|
|
|
|
uint32_t index)
|
|
|
|
|
{
|
|
|
|
|
uint32_t n_images = index + 1;
|
|
|
|
|
VkImage *images = malloc(sizeof(*images) * n_images);
|
|
|
|
|
VkResult result = wsi_common_get_images(swapchain, &n_images, images);
|
|
|
|
|
|
|
|
|
|
if (result != VK_SUCCESS && result != VK_INCOMPLETE) {
|
|
|
|
|
free(images);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ANV_FROM_HANDLE(anv_image, image, images[index]);
|
|
|
|
|
free(images);
|
|
|
|
|
|
|
|
|
|
return image;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static VkResult
|
|
|
|
|
anv_image_from_swapchain(VkDevice device,
|
|
|
|
|
const VkImageCreateInfo *pCreateInfo,
|
|
|
|
|
const VkImageSwapchainCreateInfoKHR *swapchain_info,
|
|
|
|
|
const VkAllocationCallbacks *pAllocator,
|
|
|
|
|
VkImage *pImage)
|
|
|
|
|
{
|
|
|
|
|
struct anv_image *swapchain_image = anv_swapchain_get_image(swapchain_info->swapchain, 0);
|
|
|
|
|
assert(swapchain_image);
|
|
|
|
|
|
|
|
|
|
assert(swapchain_image->type == pCreateInfo->imageType);
|
|
|
|
|
assert(swapchain_image->vk_format == pCreateInfo->format);
|
|
|
|
|
assert(swapchain_image->extent.width == pCreateInfo->extent.width);
|
|
|
|
|
assert(swapchain_image->extent.height == pCreateInfo->extent.height);
|
|
|
|
|
assert(swapchain_image->extent.depth == pCreateInfo->extent.depth);
|
|
|
|
|
assert(swapchain_image->array_size == pCreateInfo->arrayLayers);
|
|
|
|
|
/* Color attachment is added by the wsi code. */
|
|
|
|
|
assert(swapchain_image->usage == (pCreateInfo->usage | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT));
|
|
|
|
|
|
|
|
|
|
VkImageCreateInfo local_create_info;
|
|
|
|
|
local_create_info = *pCreateInfo;
|
|
|
|
|
local_create_info.pNext = NULL;
|
|
|
|
|
/* The following parameters are implictly selected by the wsi code. */
|
|
|
|
|
local_create_info.tiling = VK_IMAGE_TILING_OPTIMAL;
|
|
|
|
|
local_create_info.samples = VK_SAMPLE_COUNT_1_BIT;
|
|
|
|
|
local_create_info.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
|
|
|
|
|
|
|
|
|
/* If the image has a particular modifier, specify that modifier. */
|
|
|
|
|
struct wsi_image_create_info local_wsi_info = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_WSI_IMAGE_CREATE_INFO_MESA,
|
|
|
|
|
.modifier_count = 1,
|
|
|
|
|
.modifiers = &swapchain_image->drm_format_mod,
|
|
|
|
|
};
|
|
|
|
|
if (swapchain_image->drm_format_mod != DRM_FORMAT_MOD_INVALID)
|
|
|
|
|
__vk_append_struct(&local_create_info, &local_wsi_info);
|
|
|
|
|
|
|
|
|
|
return anv_image_create(device,
|
|
|
|
|
&(struct anv_image_create_info) {
|
|
|
|
|
.vk_info = &local_create_info,
|
|
|
|
|
.external_format = swapchain_image->external_format,
|
|
|
|
|
},
|
|
|
|
|
pAllocator,
|
|
|
|
|
pImage);
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-26 20:12:42 -07:00
|
|
|
VkResult
|
|
|
|
|
anv_CreateImage(VkDevice device,
|
|
|
|
|
const VkImageCreateInfo *pCreateInfo,
|
2015-12-02 03:28:27 -08:00
|
|
|
const VkAllocationCallbacks *pAllocator,
|
2015-06-26 20:12:42 -07:00
|
|
|
VkImage *pImage)
|
2015-05-15 22:04:52 -07:00
|
|
|
{
|
2018-11-08 10:37:12 +02:00
|
|
|
const struct VkExternalMemoryImageCreateInfo *create_info =
|
|
|
|
|
vk_find_struct_const(pCreateInfo->pNext, EXTERNAL_MEMORY_IMAGE_CREATE_INFO);
|
|
|
|
|
|
|
|
|
|
if (create_info && (create_info->handleTypes &
|
|
|
|
|
VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID))
|
|
|
|
|
return anv_image_from_external(device, pCreateInfo, create_info,
|
|
|
|
|
pAllocator, pImage);
|
|
|
|
|
|
anv: Implement VK_ANDROID_native_buffer (v9)
This implementation is correct (afaict), but takes two shortcuts
regarding the import/export of Android sync fds.
Shortcut 1. When Android calls vkAcquireImageANDROID to import a sync
fd into a VkSemaphore or VkFence, the driver instead simply blocks on
the sync fd, then puts the VkSemaphore or VkFence into the signalled
state. Thanks to implicit sync, this produces correct behavior (with
extra latency overhead, perhaps) despite its ugliness.
Shortcut 2. When Android calls vkQueueSignalReleaseImageANDROID to export
a collection of wait semaphores as a sync fd, the driver instead
submits the semaphores to the queue, then returns sync fd -1, which
informs the caller that no additional synchronization is needed.
Again, thanks to implicit sync, this produces correct behavior (with
extra batch submission overhead) despite its ugliness.
I chose to take the shortcuts instead of properly importing/exporting
the sync fds for two reasons:
Reason 1. I've already tested this patch with dEQP and with demos
apps. It works. I wanted to get the tested patches into the tree now,
and polish the implementation afterwards.
Reason 2. I want to run this on a 3.18 kernel (gasp!). In 3.18, i915
supports neither Android's sync_fence, nor upstream's sync_file, nor
drm_syncobj. Again, I tested these patches on Android with a 3.18
kernel and they work.
I plan to quickly follow-up with patches that remove the shortcuts and
properly import/export the sync fds.
Non-Testing
===========
I did not test at all using the Android.mk buildsystem. I may have broke
it. Please test and review that.
Testing
=======
I tested with 64-bit ARC++ on a Skylake Chromebook and a 3.18 kernel.
The following pass (as of patchset v9):
- a little spinning cube demo APK
- several Sascha demos
- dEQP-VK.info.*
- dEQP-VK.api.wsi.android.*
(except dEQP-VK.api.wsi.android.swapchain.*.image_usage, because
dEQP wants to create swapchains with VK_IMAGE_USAGE_STORAGE_BIT)
- dEQP-VK.api.smoke.*
- dEQP-VK.api.info.instance.*
- dEQP-VK.api.info.device.*
v2:
- Reject VkNativeBufferANDROID if the dma-buf's size is too small for
the VkImage.
- Stop abusing VkNativeBufferANDROID by passing it to vkAllocateMemory
during vkCreateImage. Instead, directly import its dma-buf during
vkCreateImage with anv_bo_cache_import(). [for jekstrand]
- Rebase onto Tapani's VK_EXT_debug_report changes.
- Drop `CPPFLAGS += $(top_srcdir)/include/android`. The dir does not
exist.
v3:
- Delete duplicate #include "anv_private.h". [per Tapani]
- Try to fix the Android-IA build in Android.vulkan.mk by following
Tapani's example.
v4:
- Unset EXEC_OBJECT_ASYNC and set EXEC_OBJECT_WRITE on the imported
gralloc buffer, just as we do for all other winsys buffers in
anv_wsi.c. [found by Tapani]
v5:
- Really fix the Android-IA build by ensuring that Android.vulkan.mk
uses Mesa' vulkan.h and not Android's. Insert -I$(MESA_TOP)/include
before -Iframeworks/native/vulkan/include. [for Tapani]
- In vkAcquireImageANDROID, submit signal operations to the
VkSemaphore and VkFence. [for zhou]
v6:
- Drop copy-paste duplication in vkGetSwapchainGrallocUsageANDROID().
[found by zhou]
- Improve comments in vkGetSwapchainGrallocUsageANDROID().
v7:
- Fix vkGetSwapchainGrallocUsageANDROID() to inspect its
VkImageUsageFlags parameter. [for tfiga]
- This fix regresses dEQP-VK.api.wsi.android.swapchain.*.image_usage
because dEQP wants to create swapchains with
VK_IMAGE_USAGE_STORAGE_BIT.
v8:
- Drop unneeded goto in vkAcquireImageANDROID. [for tfiga]
v8.1: (minor changes)
- Drop errant hunks added by rerere in anv_device.c.
- Drop explicit mention of VK_ANDROID_native_buffer in
anv_entrypoints_gen.py. [for jekstrand]
v9:
- Isolate as much Android code as possible, moving it from anv_image.c
to anv_android.c. Connect the files with anv_image_from_gralloc().
Remove VkNativeBufferANDROID params from all anv_image.c
funcs. [for krh]
- Replace some intel_loge() with vk_errorf() in anv_android.c.
- Use © in copyright line. [for krh]
Reviewed-by: Tapani Pälli <tapani.palli@intel.com> (v5)
Reviewed-by: Kristian H. Kristensen <hoegsberg@google.com> (v9)
Reviewed-by: Jason Ekstrand <jason@jlekstrand.net> (v9)
Cc: zhoucm1 <david1.zhou@amd.com>
Cc: Tomasz Figa <tfiga@chromium.org>
2016-11-14 16:13:51 -08:00
|
|
|
const VkNativeBufferANDROID *gralloc_info =
|
|
|
|
|
vk_find_struct_const(pCreateInfo->pNext, NATIVE_BUFFER_ANDROID);
|
|
|
|
|
if (gralloc_info)
|
|
|
|
|
return anv_image_from_gralloc(device, pCreateInfo, gralloc_info,
|
|
|
|
|
pAllocator, pImage);
|
|
|
|
|
|
2019-03-25 15:02:47 +00:00
|
|
|
const VkImageSwapchainCreateInfoKHR *swapchain_info =
|
|
|
|
|
vk_find_struct_const(pCreateInfo->pNext, IMAGE_SWAPCHAIN_CREATE_INFO_KHR);
|
|
|
|
|
if (swapchain_info && swapchain_info->swapchain != VK_NULL_HANDLE)
|
|
|
|
|
return anv_image_from_swapchain(device, pCreateInfo, swapchain_info,
|
|
|
|
|
pAllocator, pImage);
|
|
|
|
|
|
2015-06-26 20:06:08 -07:00
|
|
|
return anv_image_create(device,
|
|
|
|
|
&(struct anv_image_create_info) {
|
|
|
|
|
.vk_info = pCreateInfo,
|
|
|
|
|
},
|
2015-12-02 03:28:27 -08:00
|
|
|
pAllocator,
|
2015-06-26 20:06:08 -07:00
|
|
|
pImage);
|
2015-05-15 22:04:52 -07:00
|
|
|
}
|
|
|
|
|
|
2015-10-05 20:50:51 -07:00
|
|
|
void
|
2015-12-02 03:28:27 -08:00
|
|
|
anv_DestroyImage(VkDevice _device, VkImage _image,
|
|
|
|
|
const VkAllocationCallbacks *pAllocator)
|
2015-07-10 12:30:58 -07:00
|
|
|
{
|
|
|
|
|
ANV_FROM_HANDLE(anv_device, device, _device);
|
2016-11-10 21:32:32 -08:00
|
|
|
ANV_FROM_HANDLE(anv_image, image, _image);
|
|
|
|
|
|
|
|
|
|
if (!image)
|
|
|
|
|
return;
|
2015-07-10 12:30:58 -07:00
|
|
|
|
2017-08-29 01:36:42 -07:00
|
|
|
for (uint32_t p = 0; p < image->n_planes; ++p) {
|
|
|
|
|
if (image->planes[p].bo_is_owned) {
|
2018-05-30 18:55:00 -07:00
|
|
|
assert(image->planes[p].address.bo != NULL);
|
|
|
|
|
anv_bo_cache_release(device, &device->bo_cache,
|
|
|
|
|
image->planes[p].address.bo);
|
2017-08-29 01:36:42 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-10 21:32:32 -08:00
|
|
|
vk_free2(&device->alloc, pAllocator, image);
|
2015-07-10 12:30:58 -07:00
|
|
|
}
|
|
|
|
|
|
2017-07-19 12:14:19 +01:00
|
|
|
static void anv_image_bind_memory_plane(struct anv_device *device,
|
|
|
|
|
struct anv_image *image,
|
|
|
|
|
uint32_t plane,
|
|
|
|
|
struct anv_device_memory *memory,
|
|
|
|
|
uint32_t memory_offset)
|
2016-10-06 15:21:50 -07:00
|
|
|
{
|
2017-08-29 01:36:42 -07:00
|
|
|
assert(!image->planes[plane].bo_is_owned);
|
|
|
|
|
|
2017-07-19 12:14:19 +01:00
|
|
|
if (!memory) {
|
2018-05-30 18:55:00 -07:00
|
|
|
image->planes[plane].address = ANV_NULL_ADDRESS;
|
2017-10-09 08:17:15 +03:00
|
|
|
return;
|
2016-10-06 15:21:50 -07:00
|
|
|
}
|
|
|
|
|
|
2018-05-30 18:55:00 -07:00
|
|
|
image->planes[plane].address = (struct anv_address) {
|
|
|
|
|
.bo = memory->bo,
|
|
|
|
|
.offset = memory_offset,
|
|
|
|
|
};
|
2017-07-18 09:02:53 -07:00
|
|
|
}
|
|
|
|
|
|
2018-11-08 10:37:12 +02:00
|
|
|
/* We are binding AHardwareBuffer. Get a description, resolve the
|
|
|
|
|
* format and prepare anv_image properly.
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
resolve_ahw_image(struct anv_device *device,
|
|
|
|
|
struct anv_image *image,
|
|
|
|
|
struct anv_device_memory *mem)
|
|
|
|
|
{
|
2019-03-18 19:06:05 -07:00
|
|
|
#if defined(ANDROID) && ANDROID_API_LEVEL >= 26
|
2018-11-08 10:37:12 +02:00
|
|
|
assert(mem->ahw);
|
|
|
|
|
AHardwareBuffer_Desc desc;
|
|
|
|
|
AHardwareBuffer_describe(mem->ahw, &desc);
|
|
|
|
|
|
|
|
|
|
/* Check tiling. */
|
|
|
|
|
int i915_tiling = anv_gem_get_tiling(device, mem->bo->gem_handle);
|
|
|
|
|
VkImageTiling vk_tiling;
|
|
|
|
|
isl_tiling_flags_t isl_tiling_flags = 0;
|
|
|
|
|
|
|
|
|
|
switch (i915_tiling) {
|
|
|
|
|
case I915_TILING_NONE:
|
|
|
|
|
vk_tiling = VK_IMAGE_TILING_LINEAR;
|
|
|
|
|
isl_tiling_flags = ISL_TILING_LINEAR_BIT;
|
|
|
|
|
break;
|
|
|
|
|
case I915_TILING_X:
|
|
|
|
|
vk_tiling = VK_IMAGE_TILING_OPTIMAL;
|
|
|
|
|
isl_tiling_flags = ISL_TILING_X_BIT;
|
|
|
|
|
break;
|
|
|
|
|
case I915_TILING_Y:
|
|
|
|
|
vk_tiling = VK_IMAGE_TILING_OPTIMAL;
|
|
|
|
|
isl_tiling_flags = ISL_TILING_Y0_BIT;
|
|
|
|
|
break;
|
|
|
|
|
case -1:
|
|
|
|
|
default:
|
|
|
|
|
unreachable("Invalid tiling flags.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert(vk_tiling == VK_IMAGE_TILING_LINEAR ||
|
|
|
|
|
vk_tiling == VK_IMAGE_TILING_OPTIMAL);
|
|
|
|
|
|
|
|
|
|
/* Check format. */
|
|
|
|
|
VkFormat vk_format = vk_format_from_android(desc.format);
|
|
|
|
|
enum isl_format isl_fmt = anv_get_isl_format(&device->info,
|
|
|
|
|
vk_format,
|
|
|
|
|
VK_IMAGE_ASPECT_COLOR_BIT,
|
|
|
|
|
vk_tiling);
|
|
|
|
|
assert(format != ISL_FORMAT_UNSUPPORTED);
|
|
|
|
|
|
|
|
|
|
/* Handle RGB(X)->RGBA fallback. */
|
|
|
|
|
switch (desc.format) {
|
|
|
|
|
case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
|
|
|
|
|
case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
|
|
|
|
|
if (isl_format_is_rgb(isl_fmt))
|
|
|
|
|
isl_fmt = isl_format_rgb_to_rgba(isl_fmt);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Now we are able to fill anv_image fields properly and create
|
|
|
|
|
* isl_surface for it.
|
|
|
|
|
*/
|
|
|
|
|
image->vk_format = vk_format;
|
|
|
|
|
image->format = anv_get_format(vk_format);
|
|
|
|
|
image->aspects = vk_format_aspects(image->vk_format);
|
|
|
|
|
image->n_planes = image->format->n_planes;
|
|
|
|
|
image->ccs_e_compatible = false;
|
|
|
|
|
|
|
|
|
|
uint32_t stride = desc.stride *
|
|
|
|
|
(isl_format_get_layout(isl_fmt)->bpb / 8);
|
|
|
|
|
|
|
|
|
|
uint32_t b;
|
|
|
|
|
for_each_bit(b, image->aspects) {
|
|
|
|
|
VkResult r = make_surface(device, image, stride, isl_tiling_flags,
|
|
|
|
|
ISL_SURF_USAGE_DISABLE_AUX_BIT, (1 << b));
|
|
|
|
|
assert(r == VK_SUCCESS);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2017-07-18 09:02:53 -07:00
|
|
|
VkResult anv_BindImageMemory(
|
2017-07-19 12:14:19 +01:00
|
|
|
VkDevice _device,
|
|
|
|
|
VkImage _image,
|
|
|
|
|
VkDeviceMemory _memory,
|
2017-07-18 09:02:53 -07:00
|
|
|
VkDeviceSize memoryOffset)
|
|
|
|
|
{
|
2017-07-19 12:14:19 +01:00
|
|
|
ANV_FROM_HANDLE(anv_device, device, _device);
|
|
|
|
|
ANV_FROM_HANDLE(anv_device_memory, mem, _memory);
|
|
|
|
|
ANV_FROM_HANDLE(anv_image, image, _image);
|
|
|
|
|
|
2018-11-08 10:37:12 +02:00
|
|
|
if (mem->ahw)
|
|
|
|
|
resolve_ahw_image(device, image, mem);
|
|
|
|
|
|
2017-07-19 12:14:19 +01:00
|
|
|
uint32_t aspect_bit;
|
|
|
|
|
anv_foreach_image_aspect_bit(aspect_bit, image, image->aspects) {
|
|
|
|
|
uint32_t plane =
|
|
|
|
|
anv_image_aspect_to_plane(image->aspects, 1UL << aspect_bit);
|
|
|
|
|
anv_image_bind_memory_plane(device, image, plane, mem, memoryOffset);
|
|
|
|
|
}
|
2017-07-18 09:02:53 -07:00
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-20 12:18:10 -07:00
|
|
|
VkResult anv_BindImageMemory2(
|
2017-07-19 12:14:19 +01:00
|
|
|
VkDevice _device,
|
2017-07-18 09:02:53 -07:00
|
|
|
uint32_t bindInfoCount,
|
2017-09-20 13:16:26 -07:00
|
|
|
const VkBindImageMemoryInfo* pBindInfos)
|
2017-07-18 09:02:53 -07:00
|
|
|
{
|
2017-07-19 12:14:19 +01:00
|
|
|
ANV_FROM_HANDLE(anv_device, device, _device);
|
|
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < bindInfoCount; i++) {
|
2017-09-20 13:16:26 -07:00
|
|
|
const VkBindImageMemoryInfo *bind_info = &pBindInfos[i];
|
2017-07-19 12:14:19 +01:00
|
|
|
ANV_FROM_HANDLE(anv_device_memory, mem, bind_info->memory);
|
|
|
|
|
ANV_FROM_HANDLE(anv_image, image, bind_info->image);
|
2017-06-19 16:57:00 +01:00
|
|
|
|
2019-03-25 15:02:47 +00:00
|
|
|
/* Resolve will alter the image's aspects, do this first. */
|
|
|
|
|
if (mem && mem->ahw)
|
2018-11-08 10:37:12 +02:00
|
|
|
resolve_ahw_image(device, image, mem);
|
|
|
|
|
|
|
|
|
|
VkImageAspectFlags aspects = image->aspects;
|
2017-06-19 16:57:00 +01:00
|
|
|
vk_foreach_struct_const(s, bind_info->pNext) {
|
|
|
|
|
switch (s->sType) {
|
2017-09-20 13:16:26 -07:00
|
|
|
case VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO: {
|
|
|
|
|
const VkBindImagePlaneMemoryInfo *plane_info =
|
|
|
|
|
(const VkBindImagePlaneMemoryInfo *) s;
|
2017-07-19 12:14:19 +01:00
|
|
|
|
2017-06-19 16:57:00 +01:00
|
|
|
aspects = plane_info->planeAspect;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2019-03-25 15:02:47 +00:00
|
|
|
case VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR: {
|
|
|
|
|
const VkBindImageMemorySwapchainInfoKHR *swapchain_info =
|
|
|
|
|
(const VkBindImageMemorySwapchainInfoKHR *) s;
|
|
|
|
|
struct anv_image *swapchain_image =
|
|
|
|
|
anv_swapchain_get_image(swapchain_info->swapchain,
|
|
|
|
|
swapchain_info->imageIndex);
|
|
|
|
|
assert(swapchain_image);
|
|
|
|
|
assert(image->aspects == swapchain_image->aspects);
|
|
|
|
|
assert(mem == NULL);
|
|
|
|
|
|
|
|
|
|
uint32_t aspect_bit;
|
|
|
|
|
anv_foreach_image_aspect_bit(aspect_bit, image, aspects) {
|
|
|
|
|
uint32_t plane =
|
|
|
|
|
anv_image_aspect_to_plane(image->aspects, 1UL << aspect_bit);
|
|
|
|
|
struct anv_device_memory mem = {
|
|
|
|
|
.bo = swapchain_image->planes[plane].address.bo,
|
|
|
|
|
};
|
|
|
|
|
anv_image_bind_memory_plane(device, image, plane,
|
|
|
|
|
&mem, bind_info->memoryOffset);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2017-06-19 16:57:00 +01:00
|
|
|
default:
|
|
|
|
|
anv_debug_ignored_stype(s->sType);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-25 15:02:47 +00:00
|
|
|
/* VkBindImageMemorySwapchainInfoKHR requires memory to be
|
|
|
|
|
* VK_NULL_HANDLE. In such case, just carry one with the next bind
|
|
|
|
|
* item.
|
|
|
|
|
*/
|
|
|
|
|
if (!mem)
|
|
|
|
|
continue;
|
|
|
|
|
|
2017-06-19 16:57:00 +01:00
|
|
|
uint32_t aspect_bit;
|
|
|
|
|
anv_foreach_image_aspect_bit(aspect_bit, image, aspects) {
|
2017-07-19 12:14:19 +01:00
|
|
|
uint32_t plane =
|
|
|
|
|
anv_image_aspect_to_plane(image->aspects, 1UL << aspect_bit);
|
|
|
|
|
anv_image_bind_memory_plane(device, image, plane,
|
|
|
|
|
mem, bind_info->memoryOffset);
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-03-21 17:16:46 -07:00
|
|
|
|
2016-10-06 15:21:50 -07:00
|
|
|
return VK_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-06 19:35:43 -08:00
|
|
|
void anv_GetImageSubresourceLayout(
|
|
|
|
|
VkDevice device,
|
|
|
|
|
VkImage _image,
|
|
|
|
|
const VkImageSubresource* subresource,
|
|
|
|
|
VkSubresourceLayout* layout)
|
2015-10-13 15:50:02 -07:00
|
|
|
{
|
2017-11-06 19:35:43 -08:00
|
|
|
ANV_FROM_HANDLE(anv_image, image, _image);
|
2018-02-13 14:26:05 -08:00
|
|
|
|
|
|
|
|
const struct anv_surface *surface;
|
2019-01-08 18:04:54 +00:00
|
|
|
if (subresource->aspectMask == VK_IMAGE_ASPECT_PLANE_1_BIT &&
|
2018-02-13 14:26:05 -08:00
|
|
|
image->drm_format_mod != DRM_FORMAT_MOD_INVALID &&
|
|
|
|
|
isl_drm_modifier_has_aux(image->drm_format_mod))
|
|
|
|
|
surface = &image->planes[0].aux_surface;
|
|
|
|
|
else
|
|
|
|
|
surface = get_surface(image, subresource->aspectMask);
|
2017-11-06 19:35:43 -08:00
|
|
|
|
|
|
|
|
assert(__builtin_popcount(subresource->aspectMask) == 1);
|
|
|
|
|
|
2015-10-13 15:50:02 -07:00
|
|
|
layout->offset = surface->offset;
|
2018-09-05 14:02:12 -05:00
|
|
|
layout->rowPitch = surface->isl.row_pitch_B;
|
2015-12-03 08:40:47 -08:00
|
|
|
layout->depthPitch = isl_surf_get_array_pitch(&surface->isl);
|
2016-01-06 19:27:10 -08:00
|
|
|
layout->arrayPitch = isl_surf_get_array_pitch(&surface->isl);
|
2018-07-20 14:24:17 -07:00
|
|
|
|
|
|
|
|
if (subresource->mipLevel > 0 || subresource->arrayLayer > 0) {
|
|
|
|
|
assert(surface->isl.tiling == ISL_TILING_LINEAR);
|
|
|
|
|
|
|
|
|
|
uint32_t offset_B;
|
|
|
|
|
isl_surf_get_image_offset_B_tile_sa(&surface->isl,
|
|
|
|
|
subresource->mipLevel,
|
|
|
|
|
subresource->arrayLayer,
|
|
|
|
|
0 /* logical_z_offset_px */,
|
|
|
|
|
&offset_B, NULL, NULL);
|
|
|
|
|
layout->offset += offset_B;
|
|
|
|
|
layout->size = layout->rowPitch * anv_minify(image->extent.height,
|
|
|
|
|
subresource->mipLevel);
|
|
|
|
|
} else {
|
2018-09-05 14:02:12 -05:00
|
|
|
layout->size = surface->isl.size_B;
|
2018-07-20 14:24:17 -07:00
|
|
|
}
|
2015-10-13 15:50:02 -07:00
|
|
|
}
|
|
|
|
|
|
2017-02-01 11:27:58 -08:00
|
|
|
/**
|
2017-05-18 11:30:47 -07:00
|
|
|
* This function determines the optimal buffer to use for a given
|
|
|
|
|
* VkImageLayout and other pieces of information needed to make that
|
|
|
|
|
* determination. This does not determine the optimal buffer to use
|
|
|
|
|
* during a resolve operation.
|
2017-02-01 11:27:58 -08:00
|
|
|
*
|
|
|
|
|
* @param devinfo The device information of the Intel GPU.
|
|
|
|
|
* @param image The image that may contain a collection of buffers.
|
2017-11-20 09:47:47 -08:00
|
|
|
* @param aspect The aspect of the image to be accessed.
|
2017-02-01 11:27:58 -08:00
|
|
|
* @param layout The current layout of the image aspect(s).
|
|
|
|
|
*
|
|
|
|
|
* @return The primary buffer that should be used for the given layout.
|
|
|
|
|
*/
|
|
|
|
|
enum isl_aux_usage
|
|
|
|
|
anv_layout_to_aux_usage(const struct gen_device_info * const devinfo,
|
|
|
|
|
const struct anv_image * const image,
|
2017-10-05 12:20:40 -07:00
|
|
|
const VkImageAspectFlagBits aspect,
|
2017-02-01 11:27:58 -08:00
|
|
|
const VkImageLayout layout)
|
|
|
|
|
{
|
|
|
|
|
/* Validate the inputs. */
|
|
|
|
|
|
|
|
|
|
/* The devinfo is needed as the optimal buffer varies across generations. */
|
|
|
|
|
assert(devinfo != NULL);
|
|
|
|
|
|
|
|
|
|
/* The layout of a NULL image is not properly defined. */
|
|
|
|
|
assert(image != NULL);
|
|
|
|
|
|
2017-10-05 12:20:40 -07:00
|
|
|
/* The aspect must be exactly one of the image aspects. */
|
2018-08-21 09:46:46 -07:00
|
|
|
assert(util_bitcount(aspect) == 1 && (aspect & image->aspects));
|
2017-02-01 11:27:58 -08:00
|
|
|
|
|
|
|
|
/* Determine the optimal buffer. */
|
|
|
|
|
|
2017-07-19 12:14:19 +01:00
|
|
|
uint32_t plane = anv_image_aspect_to_plane(image->aspects, aspect);
|
|
|
|
|
|
2017-02-01 11:27:58 -08:00
|
|
|
/* If there is no auxiliary surface allocated, we must use the one and only
|
|
|
|
|
* main buffer.
|
|
|
|
|
*/
|
2018-09-05 14:02:12 -05:00
|
|
|
if (image->planes[plane].aux_surface.isl.size_B == 0)
|
2017-02-01 11:27:58 -08:00
|
|
|
return ISL_AUX_USAGE_NONE;
|
|
|
|
|
|
|
|
|
|
/* All images that use an auxiliary surface are required to be tiled. */
|
|
|
|
|
assert(image->tiling == VK_IMAGE_TILING_OPTIMAL);
|
|
|
|
|
|
2017-10-05 12:20:40 -07:00
|
|
|
/* Stencil has no aux */
|
2017-07-19 12:14:19 +01:00
|
|
|
assert(aspect != VK_IMAGE_ASPECT_STENCIL_BIT);
|
2017-02-01 11:27:58 -08:00
|
|
|
|
|
|
|
|
switch (layout) {
|
|
|
|
|
|
|
|
|
|
/* Invalid Layouts */
|
2017-05-18 11:30:47 -07:00
|
|
|
case VK_IMAGE_LAYOUT_RANGE_SIZE:
|
|
|
|
|
case VK_IMAGE_LAYOUT_MAX_ENUM:
|
|
|
|
|
unreachable("Invalid image layout.");
|
2017-02-01 11:27:58 -08:00
|
|
|
|
2017-05-18 11:30:47 -07:00
|
|
|
/* Undefined layouts
|
|
|
|
|
*
|
|
|
|
|
* The pre-initialized layout is equivalent to the undefined layout for
|
|
|
|
|
* optimally-tiled images. We can only do color compression (CCS or HiZ)
|
|
|
|
|
* on tiled images.
|
2017-02-01 11:27:58 -08:00
|
|
|
*/
|
|
|
|
|
case VK_IMAGE_LAYOUT_UNDEFINED:
|
|
|
|
|
case VK_IMAGE_LAYOUT_PREINITIALIZED:
|
2017-05-18 11:30:47 -07:00
|
|
|
return ISL_AUX_USAGE_NONE;
|
2017-02-01 11:27:58 -08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Transfer Layouts
|
|
|
|
|
*/
|
|
|
|
|
case VK_IMAGE_LAYOUT_GENERAL:
|
|
|
|
|
case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
|
|
|
|
|
case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
|
2017-11-20 12:05:20 -08:00
|
|
|
if (aspect == VK_IMAGE_ASPECT_DEPTH_BIT) {
|
|
|
|
|
/* This buffer could be a depth buffer used in a transfer operation.
|
|
|
|
|
* BLORP currently doesn't use HiZ for transfer operations so we must
|
|
|
|
|
* use the main buffer for this layout. TODO: Enable HiZ in BLORP.
|
|
|
|
|
*/
|
|
|
|
|
assert(image->planes[plane].aux_usage == ISL_AUX_USAGE_HIZ);
|
|
|
|
|
return ISL_AUX_USAGE_NONE;
|
|
|
|
|
} else {
|
|
|
|
|
assert(image->aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT_ANV);
|
|
|
|
|
return image->planes[plane].aux_usage;
|
|
|
|
|
}
|
2017-02-01 11:27:58 -08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Sampling Layouts */
|
|
|
|
|
case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
|
2017-09-20 13:16:26 -07:00
|
|
|
case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL:
|
2017-11-02 16:05:45 -07:00
|
|
|
assert((image->aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT_ANV) == 0);
|
2017-02-01 11:27:58 -08:00
|
|
|
/* Fall-through */
|
|
|
|
|
case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
|
2017-11-20 12:05:20 -08:00
|
|
|
if (aspect == VK_IMAGE_ASPECT_DEPTH_BIT) {
|
|
|
|
|
if (anv_can_sample_with_hiz(devinfo, image))
|
|
|
|
|
return ISL_AUX_USAGE_HIZ;
|
|
|
|
|
else
|
|
|
|
|
return ISL_AUX_USAGE_NONE;
|
|
|
|
|
} else {
|
|
|
|
|
return image->planes[plane].aux_usage;
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-01 11:27:58 -08:00
|
|
|
|
2018-02-13 14:26:05 -08:00
|
|
|
case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR: {
|
2017-07-19 12:14:19 +01:00
|
|
|
assert(image->aspects == VK_IMAGE_ASPECT_COLOR_BIT);
|
2017-02-01 11:27:58 -08:00
|
|
|
|
2018-02-13 14:26:05 -08:00
|
|
|
/* When handing the image off to the presentation engine, we need to
|
|
|
|
|
* ensure that things are properly resolved. For images with no
|
|
|
|
|
* modifier, we assume that they follow the old rules and always need
|
|
|
|
|
* a full resolve because the PE doesn't understand any form of
|
|
|
|
|
* compression. For images with modifiers, we use the aux usage from
|
|
|
|
|
* the modifier.
|
2017-02-01 11:27:58 -08:00
|
|
|
*/
|
2018-02-13 14:26:05 -08:00
|
|
|
const struct isl_drm_modifier_info *mod_info =
|
|
|
|
|
isl_drm_modifier_get_info(image->drm_format_mod);
|
|
|
|
|
return mod_info ? mod_info->aux_usage : ISL_AUX_USAGE_NONE;
|
|
|
|
|
}
|
2017-02-01 11:27:58 -08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Rendering Layouts */
|
|
|
|
|
case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
|
2017-11-20 12:05:20 -08:00
|
|
|
assert(aspect & VK_IMAGE_ASPECT_ANY_COLOR_BIT_ANV);
|
|
|
|
|
if (image->planes[plane].aux_usage == ISL_AUX_USAGE_NONE) {
|
|
|
|
|
assert(image->samples == 1);
|
|
|
|
|
return ISL_AUX_USAGE_CCS_D;
|
|
|
|
|
} else {
|
|
|
|
|
assert(image->planes[plane].aux_usage != ISL_AUX_USAGE_CCS_D);
|
|
|
|
|
return image->planes[plane].aux_usage;
|
|
|
|
|
}
|
2017-02-01 11:27:58 -08:00
|
|
|
|
|
|
|
|
case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
|
2017-09-20 13:16:26 -07:00
|
|
|
case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL:
|
2017-10-05 12:20:40 -07:00
|
|
|
assert(aspect == VK_IMAGE_ASPECT_DEPTH_BIT);
|
2017-02-01 11:27:58 -08:00
|
|
|
return ISL_AUX_USAGE_HIZ;
|
2017-06-22 14:39:12 -07:00
|
|
|
|
|
|
|
|
case VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR:
|
|
|
|
|
unreachable("VK_KHR_shared_presentable_image is unsupported");
|
2018-10-02 14:31:42 +01:00
|
|
|
|
2018-12-04 13:19:20 +00:00
|
|
|
case VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT:
|
|
|
|
|
unreachable("VK_EXT_fragment_density_map is unsupported");
|
|
|
|
|
|
2018-10-02 14:31:42 +01:00
|
|
|
case VK_IMAGE_LAYOUT_SHADING_RATE_OPTIMAL_NV:
|
|
|
|
|
unreachable("VK_NV_shading_rate_image is unsupported");
|
2017-02-01 11:27:58 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If the layout isn't recognized in the exhaustive switch above, the
|
|
|
|
|
* VkImageLayout value is not defined in vulkan.h.
|
|
|
|
|
*/
|
|
|
|
|
unreachable("layout is not a VkImageLayout enumeration member.");
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-20 09:48:39 -08:00
|
|
|
/**
|
|
|
|
|
* This function returns the level of unresolved fast-clear support of the
|
|
|
|
|
* given image in the given VkImageLayout.
|
|
|
|
|
*
|
|
|
|
|
* @param devinfo The device information of the Intel GPU.
|
|
|
|
|
* @param image The image that may contain a collection of buffers.
|
|
|
|
|
* @param aspect The aspect of the image to be accessed.
|
|
|
|
|
* @param layout The current layout of the image aspect(s).
|
|
|
|
|
*/
|
|
|
|
|
enum anv_fast_clear_type
|
|
|
|
|
anv_layout_to_fast_clear_type(const struct gen_device_info * const devinfo,
|
|
|
|
|
const struct anv_image * const image,
|
|
|
|
|
const VkImageAspectFlagBits aspect,
|
|
|
|
|
const VkImageLayout layout)
|
|
|
|
|
{
|
|
|
|
|
/* The aspect must be exactly one of the image aspects. */
|
2018-08-21 09:46:46 -07:00
|
|
|
assert(util_bitcount(aspect) == 1 && (aspect & image->aspects));
|
2017-11-20 09:48:39 -08:00
|
|
|
|
|
|
|
|
uint32_t plane = anv_image_aspect_to_plane(image->aspects, aspect);
|
|
|
|
|
|
|
|
|
|
/* If there is no auxiliary surface allocated, there are no fast-clears */
|
2018-09-05 14:02:12 -05:00
|
|
|
if (image->planes[plane].aux_surface.isl.size_B == 0)
|
2017-11-20 09:48:39 -08:00
|
|
|
return ANV_FAST_CLEAR_NONE;
|
|
|
|
|
|
|
|
|
|
/* All images that use an auxiliary surface are required to be tiled. */
|
|
|
|
|
assert(image->tiling == VK_IMAGE_TILING_OPTIMAL);
|
|
|
|
|
|
|
|
|
|
/* Stencil has no aux */
|
|
|
|
|
assert(aspect != VK_IMAGE_ASPECT_STENCIL_BIT);
|
|
|
|
|
|
|
|
|
|
if (aspect == VK_IMAGE_ASPECT_DEPTH_BIT) {
|
|
|
|
|
/* For depth images (with HiZ), the layout supports fast-clears if and
|
|
|
|
|
* only if it supports HiZ. However, we only support fast-clears to the
|
|
|
|
|
* default depth value.
|
|
|
|
|
*/
|
|
|
|
|
enum isl_aux_usage aux_usage =
|
|
|
|
|
anv_layout_to_aux_usage(devinfo, image, aspect, layout);
|
|
|
|
|
return aux_usage == ISL_AUX_USAGE_HIZ ?
|
|
|
|
|
ANV_FAST_CLEAR_DEFAULT_VALUE : ANV_FAST_CLEAR_NONE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert(image->aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT_ANV);
|
|
|
|
|
|
2018-02-23 21:12:50 -08:00
|
|
|
/* We don't support MSAA fast-clears on Ivybridge or Bay Trail because they
|
|
|
|
|
* lack the MI ALU which we need to determine the predicates.
|
|
|
|
|
*/
|
|
|
|
|
if (devinfo->gen == 7 && !devinfo->is_haswell && image->samples > 1)
|
2017-11-20 09:48:39 -08:00
|
|
|
return ANV_FAST_CLEAR_NONE;
|
|
|
|
|
|
|
|
|
|
switch (layout) {
|
|
|
|
|
case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
|
|
|
|
|
return ANV_FAST_CLEAR_ANY;
|
|
|
|
|
|
2018-02-13 14:26:05 -08:00
|
|
|
case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR: {
|
|
|
|
|
assert(image->aspects == VK_IMAGE_ASPECT_COLOR_BIT);
|
|
|
|
|
#ifndef NDEBUG
|
|
|
|
|
/* We do not yet support any modifiers which support clear color so we
|
|
|
|
|
* just always return NONE. One day, this will change.
|
|
|
|
|
*/
|
|
|
|
|
const struct isl_drm_modifier_info *mod_info =
|
|
|
|
|
isl_drm_modifier_get_info(image->drm_format_mod);
|
|
|
|
|
assert(!mod_info || !mod_info->supports_clear_color);
|
|
|
|
|
#endif
|
2017-11-20 09:48:39 -08:00
|
|
|
return ANV_FAST_CLEAR_NONE;
|
2018-02-13 14:26:05 -08:00
|
|
|
}
|
2017-11-20 09:48:39 -08:00
|
|
|
|
|
|
|
|
default:
|
2018-02-23 21:12:50 -08:00
|
|
|
/* If the image has MCS or CCS_E enabled all the time then we can use
|
2017-11-20 09:48:39 -08:00
|
|
|
* fast-clear as long as the clear color is the default value of zero
|
|
|
|
|
* since this is the default value we program into every surface state
|
|
|
|
|
* used for texturing.
|
|
|
|
|
*/
|
2018-02-23 21:12:50 -08:00
|
|
|
if (image->planes[plane].aux_usage == ISL_AUX_USAGE_MCS ||
|
|
|
|
|
image->planes[plane].aux_usage == ISL_AUX_USAGE_CCS_E)
|
2017-11-20 09:48:39 -08:00
|
|
|
return ANV_FAST_CLEAR_DEFAULT_VALUE;
|
|
|
|
|
else
|
|
|
|
|
return ANV_FAST_CLEAR_NONE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-01 11:27:58 -08:00
|
|
|
|
2016-01-22 11:57:01 -08:00
|
|
|
static struct anv_state
|
2016-10-07 22:14:03 -07:00
|
|
|
alloc_surface_state(struct anv_device *device)
|
2016-01-22 11:57:01 -08:00
|
|
|
{
|
2016-10-07 22:14:03 -07:00
|
|
|
return anv_state_pool_alloc(&device->surface_state_pool, 64, 64);
|
2016-01-22 11:57:01 -08:00
|
|
|
}
|
|
|
|
|
|
2016-02-20 11:45:50 -08:00
|
|
|
static enum isl_channel_select
|
2016-01-26 11:10:56 -08:00
|
|
|
remap_swizzle(VkComponentSwizzle swizzle, VkComponentSwizzle component,
|
2016-08-27 21:39:16 -07:00
|
|
|
struct isl_swizzle format_swizzle)
|
2016-01-26 20:16:43 -08:00
|
|
|
{
|
|
|
|
|
if (swizzle == VK_COMPONENT_SWIZZLE_IDENTITY)
|
2016-01-26 11:10:56 -08:00
|
|
|
swizzle = component;
|
|
|
|
|
|
|
|
|
|
switch (swizzle) {
|
2016-05-15 21:31:38 -07:00
|
|
|
case VK_COMPONENT_SWIZZLE_ZERO: return ISL_CHANNEL_SELECT_ZERO;
|
|
|
|
|
case VK_COMPONENT_SWIZZLE_ONE: return ISL_CHANNEL_SELECT_ONE;
|
|
|
|
|
case VK_COMPONENT_SWIZZLE_R: return format_swizzle.r;
|
|
|
|
|
case VK_COMPONENT_SWIZZLE_G: return format_swizzle.g;
|
|
|
|
|
case VK_COMPONENT_SWIZZLE_B: return format_swizzle.b;
|
|
|
|
|
case VK_COMPONENT_SWIZZLE_A: return format_swizzle.a;
|
2016-01-26 11:10:56 -08:00
|
|
|
default:
|
|
|
|
|
unreachable("Invalid swizzle");
|
|
|
|
|
}
|
2016-01-26 20:16:43 -08:00
|
|
|
}
|
|
|
|
|
|
2017-07-11 10:06:36 -07:00
|
|
|
void
|
|
|
|
|
anv_image_fill_surface_state(struct anv_device *device,
|
|
|
|
|
const struct anv_image *image,
|
|
|
|
|
VkImageAspectFlagBits aspect,
|
|
|
|
|
const struct isl_view *view_in,
|
|
|
|
|
isl_surf_usage_flags_t view_usage,
|
|
|
|
|
enum isl_aux_usage aux_usage,
|
|
|
|
|
const union isl_color_value *clear_color,
|
|
|
|
|
enum anv_image_view_state_flags flags,
|
2017-07-11 11:06:49 -07:00
|
|
|
struct anv_surface_state *state_inout,
|
2017-07-11 10:06:36 -07:00
|
|
|
struct brw_image_param *image_param_out)
|
|
|
|
|
{
|
2017-07-19 12:14:19 +01:00
|
|
|
uint32_t plane = anv_image_aspect_to_plane(image->aspects, aspect);
|
|
|
|
|
|
|
|
|
|
const struct anv_surface *surface = &image->planes[plane].surface,
|
|
|
|
|
*aux_surface = &image->planes[plane].aux_surface;
|
2017-07-11 10:06:36 -07:00
|
|
|
|
|
|
|
|
struct isl_view view = *view_in;
|
|
|
|
|
view.usage |= view_usage;
|
|
|
|
|
|
anv/image: Support creating uncompressed views of compressed images
In order to get support everywhere, this gets a bit complicated. On Sky
Lake and later, everything is fine because HALIGN/VALIGN are specified
in surface elements and are required to be at least 4 so any offsetting
we may need to do falls neatly within the heavy restrictions placed on
the X/Y Offset parameter of RENDER_SURFACE_STATE. On Broadwell and
earlier, HALIGN/VALIGN are specified in pixels and are hard-coded to
align to exactly the block size of the compressed texture. This means
that, when reinterpreted as a non-compressed texture, the tile offsets
may be anything and we can't rely on X/Y Offset.
In order to work around this issue, we fall back to linear where we can
trivially offset to whatever element we so choose. However, since
linear texturing performance is terrible, we create a tiled shadow copy
of the image to use for texturing. Whenever the user does a layout
transition from anything to SHADER_READ_ONLY_OPTIMAL, we use blorp to
copy the contents of the texture from the linear copy to the tiled
shadow copy. This assumes that the client will use the image far more
for texturing than as a storage image or render target.
Even though we don't need the shadow copy on Sky Lake, we implement it
this way first to make testing easier. Due to the hardware restriction
that ASTC must not be linear, ASTC does not work yet.
Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
2017-07-11 13:17:06 -07:00
|
|
|
/* For texturing with VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL from a
|
|
|
|
|
* compressed surface with a shadow surface, we use the shadow instead of
|
|
|
|
|
* the primary surface. The shadow surface will be tiled, unlike the main
|
|
|
|
|
* surface, so it should get significantly better performance.
|
|
|
|
|
*/
|
2018-09-05 14:02:12 -05:00
|
|
|
if (image->planes[plane].shadow_surface.isl.size_B > 0 &&
|
anv/image: Support creating uncompressed views of compressed images
In order to get support everywhere, this gets a bit complicated. On Sky
Lake and later, everything is fine because HALIGN/VALIGN are specified
in surface elements and are required to be at least 4 so any offsetting
we may need to do falls neatly within the heavy restrictions placed on
the X/Y Offset parameter of RENDER_SURFACE_STATE. On Broadwell and
earlier, HALIGN/VALIGN are specified in pixels and are hard-coded to
align to exactly the block size of the compressed texture. This means
that, when reinterpreted as a non-compressed texture, the tile offsets
may be anything and we can't rely on X/Y Offset.
In order to work around this issue, we fall back to linear where we can
trivially offset to whatever element we so choose. However, since
linear texturing performance is terrible, we create a tiled shadow copy
of the image to use for texturing. Whenever the user does a layout
transition from anything to SHADER_READ_ONLY_OPTIMAL, we use blorp to
copy the contents of the texture from the linear copy to the tiled
shadow copy. This assumes that the client will use the image far more
for texturing than as a storage image or render target.
Even though we don't need the shadow copy on Sky Lake, we implement it
this way first to make testing easier. Due to the hardware restriction
that ASTC must not be linear, ASTC does not work yet.
Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
2017-07-11 13:17:06 -07:00
|
|
|
isl_format_is_compressed(view.format) &&
|
|
|
|
|
(flags & ANV_IMAGE_VIEW_STATE_TEXTURE_OPTIMAL)) {
|
|
|
|
|
assert(isl_format_is_compressed(surface->isl.format));
|
|
|
|
|
assert(surface->isl.tiling == ISL_TILING_LINEAR);
|
2017-07-19 12:14:19 +01:00
|
|
|
assert(image->planes[plane].shadow_surface.isl.tiling != ISL_TILING_LINEAR);
|
|
|
|
|
surface = &image->planes[plane].shadow_surface;
|
anv/image: Support creating uncompressed views of compressed images
In order to get support everywhere, this gets a bit complicated. On Sky
Lake and later, everything is fine because HALIGN/VALIGN are specified
in surface elements and are required to be at least 4 so any offsetting
we may need to do falls neatly within the heavy restrictions placed on
the X/Y Offset parameter of RENDER_SURFACE_STATE. On Broadwell and
earlier, HALIGN/VALIGN are specified in pixels and are hard-coded to
align to exactly the block size of the compressed texture. This means
that, when reinterpreted as a non-compressed texture, the tile offsets
may be anything and we can't rely on X/Y Offset.
In order to work around this issue, we fall back to linear where we can
trivially offset to whatever element we so choose. However, since
linear texturing performance is terrible, we create a tiled shadow copy
of the image to use for texturing. Whenever the user does a layout
transition from anything to SHADER_READ_ONLY_OPTIMAL, we use blorp to
copy the contents of the texture from the linear copy to the tiled
shadow copy. This assumes that the client will use the image far more
for texturing than as a storage image or render target.
Even though we don't need the shadow copy on Sky Lake, we implement it
this way first to make testing easier. Due to the hardware restriction
that ASTC must not be linear, ASTC does not work yet.
Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
2017-07-11 13:17:06 -07:00
|
|
|
}
|
|
|
|
|
|
2017-07-11 10:06:36 -07:00
|
|
|
if (view_usage == ISL_SURF_USAGE_RENDER_TARGET_BIT)
|
|
|
|
|
view.swizzle = anv_swizzle_for_render(view.swizzle);
|
|
|
|
|
|
2019-05-17 10:04:58 -05:00
|
|
|
/* On Ivy Bridge and Bay Trail we do the swizzle in the shader */
|
|
|
|
|
if (device->info.gen == 7 && !device->info.is_haswell)
|
|
|
|
|
view.swizzle = ISL_SWIZZLE_IDENTITY;
|
|
|
|
|
|
2017-07-11 10:06:36 -07:00
|
|
|
/* If this is a HiZ buffer we can sample from with a programmable clear
|
|
|
|
|
* value (SKL+), define the clear value to the optimal constant.
|
|
|
|
|
*/
|
|
|
|
|
union isl_color_value default_clear_color = { .u32 = { 0, } };
|
|
|
|
|
if (device->info.gen >= 9 && aux_usage == ISL_AUX_USAGE_HIZ)
|
|
|
|
|
default_clear_color.f32[0] = ANV_HZ_FC_VAL;
|
|
|
|
|
if (!clear_color)
|
|
|
|
|
clear_color = &default_clear_color;
|
|
|
|
|
|
2018-05-30 18:55:00 -07:00
|
|
|
const struct anv_address address =
|
|
|
|
|
anv_address_add(image->planes[plane].address, surface->offset);
|
2018-01-18 09:50:48 -08:00
|
|
|
|
2017-07-11 10:06:36 -07:00
|
|
|
if (view_usage == ISL_SURF_USAGE_STORAGE_BIT &&
|
|
|
|
|
!(flags & ANV_IMAGE_VIEW_STATE_STORAGE_WRITE_ONLY) &&
|
|
|
|
|
!isl_has_matching_typed_storage_image_format(&device->info,
|
|
|
|
|
view.format)) {
|
|
|
|
|
/* In this case, we are a writeable storage buffer which needs to be
|
|
|
|
|
* lowered to linear. All tiling and offset calculations will be done in
|
|
|
|
|
* the shader.
|
|
|
|
|
*/
|
|
|
|
|
assert(aux_usage == ISL_AUX_USAGE_NONE);
|
2017-07-11 11:06:49 -07:00
|
|
|
isl_buffer_fill_state(&device->isl_dev, state_inout->state.map,
|
2018-05-30 17:16:52 -07:00
|
|
|
.address = anv_address_physical(address),
|
2018-09-05 14:02:12 -05:00
|
|
|
.size_B = surface->isl.size_B,
|
2017-07-11 10:06:36 -07:00
|
|
|
.format = ISL_FORMAT_RAW,
|
2019-02-28 01:13:33 -08:00
|
|
|
.swizzle = ISL_SWIZZLE_IDENTITY,
|
2018-09-05 14:02:12 -05:00
|
|
|
.stride_B = 1,
|
2018-07-09 14:21:33 -07:00
|
|
|
.mocs = anv_mocs_for_bo(device, address.bo));
|
2017-07-11 11:06:49 -07:00
|
|
|
state_inout->address = address,
|
2018-05-30 17:16:52 -07:00
|
|
|
state_inout->aux_address = ANV_NULL_ADDRESS;
|
|
|
|
|
state_inout->clear_address = ANV_NULL_ADDRESS;
|
2017-07-11 10:06:36 -07:00
|
|
|
} else {
|
|
|
|
|
if (view_usage == ISL_SURF_USAGE_STORAGE_BIT &&
|
|
|
|
|
!(flags & ANV_IMAGE_VIEW_STATE_STORAGE_WRITE_ONLY)) {
|
|
|
|
|
/* Typed surface reads support a very limited subset of the shader
|
|
|
|
|
* image formats. Translate it into the closest format the hardware
|
|
|
|
|
* supports.
|
|
|
|
|
*/
|
|
|
|
|
assert(aux_usage == ISL_AUX_USAGE_NONE);
|
|
|
|
|
view.format = isl_lower_storage_image_format(&device->info,
|
|
|
|
|
view.format);
|
|
|
|
|
}
|
|
|
|
|
|
anv/image: Support creating uncompressed views of compressed images
In order to get support everywhere, this gets a bit complicated. On Sky
Lake and later, everything is fine because HALIGN/VALIGN are specified
in surface elements and are required to be at least 4 so any offsetting
we may need to do falls neatly within the heavy restrictions placed on
the X/Y Offset parameter of RENDER_SURFACE_STATE. On Broadwell and
earlier, HALIGN/VALIGN are specified in pixels and are hard-coded to
align to exactly the block size of the compressed texture. This means
that, when reinterpreted as a non-compressed texture, the tile offsets
may be anything and we can't rely on X/Y Offset.
In order to work around this issue, we fall back to linear where we can
trivially offset to whatever element we so choose. However, since
linear texturing performance is terrible, we create a tiled shadow copy
of the image to use for texturing. Whenever the user does a layout
transition from anything to SHADER_READ_ONLY_OPTIMAL, we use blorp to
copy the contents of the texture from the linear copy to the tiled
shadow copy. This assumes that the client will use the image far more
for texturing than as a storage image or render target.
Even though we don't need the shadow copy on Sky Lake, we implement it
this way first to make testing easier. Due to the hardware restriction
that ASTC must not be linear, ASTC does not work yet.
Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
2017-07-11 13:17:06 -07:00
|
|
|
const struct isl_surf *isl_surf = &surface->isl;
|
|
|
|
|
|
|
|
|
|
struct isl_surf tmp_surf;
|
|
|
|
|
uint32_t offset_B = 0, tile_x_sa = 0, tile_y_sa = 0;
|
|
|
|
|
if (isl_format_is_compressed(surface->isl.format) &&
|
|
|
|
|
!isl_format_is_compressed(view.format)) {
|
|
|
|
|
/* We're creating an uncompressed view of a compressed surface. This
|
|
|
|
|
* is allowed but only for a single level/layer.
|
|
|
|
|
*/
|
|
|
|
|
assert(surface->isl.samples == 1);
|
|
|
|
|
assert(view.levels == 1);
|
|
|
|
|
assert(view.array_len == 1);
|
|
|
|
|
|
|
|
|
|
isl_surf_get_image_surf(&device->isl_dev, isl_surf,
|
|
|
|
|
view.base_level,
|
|
|
|
|
surface->isl.dim == ISL_SURF_DIM_3D ?
|
|
|
|
|
0 : view.base_array_layer,
|
|
|
|
|
surface->isl.dim == ISL_SURF_DIM_3D ?
|
|
|
|
|
view.base_array_layer : 0,
|
|
|
|
|
&tmp_surf,
|
|
|
|
|
&offset_B, &tile_x_sa, &tile_y_sa);
|
|
|
|
|
|
|
|
|
|
/* The newly created image represents the one subimage we're
|
|
|
|
|
* referencing with this view so it only has one array slice and
|
|
|
|
|
* miplevel.
|
|
|
|
|
*/
|
|
|
|
|
view.base_array_layer = 0;
|
|
|
|
|
view.base_level = 0;
|
|
|
|
|
|
|
|
|
|
/* We're making an uncompressed view here. The image dimensions need
|
|
|
|
|
* to be scaled down by the block size.
|
|
|
|
|
*/
|
|
|
|
|
const struct isl_format_layout *fmtl =
|
|
|
|
|
isl_format_get_layout(surface->isl.format);
|
|
|
|
|
tmp_surf.format = view.format;
|
|
|
|
|
tmp_surf.logical_level0_px.width =
|
|
|
|
|
DIV_ROUND_UP(tmp_surf.logical_level0_px.width, fmtl->bw);
|
|
|
|
|
tmp_surf.logical_level0_px.height =
|
|
|
|
|
DIV_ROUND_UP(tmp_surf.logical_level0_px.height, fmtl->bh);
|
|
|
|
|
tmp_surf.phys_level0_sa.width /= fmtl->bw;
|
|
|
|
|
tmp_surf.phys_level0_sa.height /= fmtl->bh;
|
2017-07-11 15:32:30 -07:00
|
|
|
tile_x_sa /= fmtl->bw;
|
|
|
|
|
tile_y_sa /= fmtl->bh;
|
anv/image: Support creating uncompressed views of compressed images
In order to get support everywhere, this gets a bit complicated. On Sky
Lake and later, everything is fine because HALIGN/VALIGN are specified
in surface elements and are required to be at least 4 so any offsetting
we may need to do falls neatly within the heavy restrictions placed on
the X/Y Offset parameter of RENDER_SURFACE_STATE. On Broadwell and
earlier, HALIGN/VALIGN are specified in pixels and are hard-coded to
align to exactly the block size of the compressed texture. This means
that, when reinterpreted as a non-compressed texture, the tile offsets
may be anything and we can't rely on X/Y Offset.
In order to work around this issue, we fall back to linear where we can
trivially offset to whatever element we so choose. However, since
linear texturing performance is terrible, we create a tiled shadow copy
of the image to use for texturing. Whenever the user does a layout
transition from anything to SHADER_READ_ONLY_OPTIMAL, we use blorp to
copy the contents of the texture from the linear copy to the tiled
shadow copy. This assumes that the client will use the image far more
for texturing than as a storage image or render target.
Even though we don't need the shadow copy on Sky Lake, we implement it
this way first to make testing easier. Due to the hardware restriction
that ASTC must not be linear, ASTC does not work yet.
Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
2017-07-11 13:17:06 -07:00
|
|
|
|
|
|
|
|
isl_surf = &tmp_surf;
|
|
|
|
|
|
2017-07-11 15:32:30 -07:00
|
|
|
if (device->info.gen <= 8) {
|
|
|
|
|
assert(surface->isl.tiling == ISL_TILING_LINEAR);
|
|
|
|
|
assert(tile_x_sa == 0);
|
|
|
|
|
assert(tile_y_sa == 0);
|
|
|
|
|
}
|
anv/image: Support creating uncompressed views of compressed images
In order to get support everywhere, this gets a bit complicated. On Sky
Lake and later, everything is fine because HALIGN/VALIGN are specified
in surface elements and are required to be at least 4 so any offsetting
we may need to do falls neatly within the heavy restrictions placed on
the X/Y Offset parameter of RENDER_SURFACE_STATE. On Broadwell and
earlier, HALIGN/VALIGN are specified in pixels and are hard-coded to
align to exactly the block size of the compressed texture. This means
that, when reinterpreted as a non-compressed texture, the tile offsets
may be anything and we can't rely on X/Y Offset.
In order to work around this issue, we fall back to linear where we can
trivially offset to whatever element we so choose. However, since
linear texturing performance is terrible, we create a tiled shadow copy
of the image to use for texturing. Whenever the user does a layout
transition from anything to SHADER_READ_ONLY_OPTIMAL, we use blorp to
copy the contents of the texture from the linear copy to the tiled
shadow copy. This assumes that the client will use the image far more
for texturing than as a storage image or render target.
Even though we don't need the shadow copy on Sky Lake, we implement it
this way first to make testing easier. Due to the hardware restriction
that ASTC must not be linear, ASTC does not work yet.
Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
2017-07-11 13:17:06 -07:00
|
|
|
}
|
|
|
|
|
|
2018-05-30 17:16:52 -07:00
|
|
|
state_inout->address = anv_address_add(address, offset_B);
|
|
|
|
|
|
|
|
|
|
struct anv_address aux_address = ANV_NULL_ADDRESS;
|
|
|
|
|
if (aux_usage != ISL_AUX_USAGE_NONE) {
|
2018-05-30 18:55:00 -07:00
|
|
|
aux_address = anv_address_add(image->planes[plane].address,
|
|
|
|
|
aux_surface->offset);
|
2018-05-30 17:16:52 -07:00
|
|
|
}
|
|
|
|
|
state_inout->aux_address = aux_address;
|
|
|
|
|
|
|
|
|
|
struct anv_address clear_address = ANV_NULL_ADDRESS;
|
|
|
|
|
if (device->info.gen >= 10 && aux_usage != ISL_AUX_USAGE_NONE) {
|
|
|
|
|
if (aux_usage == ISL_AUX_USAGE_HIZ) {
|
|
|
|
|
clear_address = (struct anv_address) {
|
|
|
|
|
.bo = &device->hiz_clear_bo,
|
|
|
|
|
.offset = 0,
|
|
|
|
|
};
|
|
|
|
|
} else {
|
|
|
|
|
clear_address = anv_image_get_clear_color_addr(device, image, aspect);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
state_inout->clear_address = clear_address;
|
|
|
|
|
|
2017-07-11 11:06:49 -07:00
|
|
|
isl_surf_fill_state(&device->isl_dev, state_inout->state.map,
|
anv/image: Support creating uncompressed views of compressed images
In order to get support everywhere, this gets a bit complicated. On Sky
Lake and later, everything is fine because HALIGN/VALIGN are specified
in surface elements and are required to be at least 4 so any offsetting
we may need to do falls neatly within the heavy restrictions placed on
the X/Y Offset parameter of RENDER_SURFACE_STATE. On Broadwell and
earlier, HALIGN/VALIGN are specified in pixels and are hard-coded to
align to exactly the block size of the compressed texture. This means
that, when reinterpreted as a non-compressed texture, the tile offsets
may be anything and we can't rely on X/Y Offset.
In order to work around this issue, we fall back to linear where we can
trivially offset to whatever element we so choose. However, since
linear texturing performance is terrible, we create a tiled shadow copy
of the image to use for texturing. Whenever the user does a layout
transition from anything to SHADER_READ_ONLY_OPTIMAL, we use blorp to
copy the contents of the texture from the linear copy to the tiled
shadow copy. This assumes that the client will use the image far more
for texturing than as a storage image or render target.
Even though we don't need the shadow copy on Sky Lake, we implement it
this way first to make testing easier. Due to the hardware restriction
that ASTC must not be linear, ASTC does not work yet.
Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
2017-07-11 13:17:06 -07:00
|
|
|
.surf = isl_surf,
|
2017-07-11 10:06:36 -07:00
|
|
|
.view = &view,
|
2018-05-30 17:16:52 -07:00
|
|
|
.address = anv_address_physical(state_inout->address),
|
2017-07-11 10:06:36 -07:00
|
|
|
.clear_color = *clear_color,
|
2017-07-19 12:14:19 +01:00
|
|
|
.aux_surf = &aux_surface->isl,
|
2017-07-11 10:06:36 -07:00
|
|
|
.aux_usage = aux_usage,
|
2018-05-30 17:16:52 -07:00
|
|
|
.aux_address = anv_address_physical(aux_address),
|
|
|
|
|
.clear_address = anv_address_physical(clear_address),
|
|
|
|
|
.use_clear_address = !anv_address_is_null(clear_address),
|
2018-07-09 14:21:33 -07:00
|
|
|
.mocs = anv_mocs_for_bo(device,
|
|
|
|
|
state_inout->address.bo),
|
2017-07-11 15:32:30 -07:00
|
|
|
.x_offset_sa = tile_x_sa,
|
|
|
|
|
.y_offset_sa = tile_y_sa);
|
2018-01-18 14:12:08 -08:00
|
|
|
|
|
|
|
|
/* With the exception of gen8, the bottom 12 bits of the MCS base address
|
|
|
|
|
* are used to store other information. This should be ok, however,
|
|
|
|
|
* because the surface buffer addresses are always 4K page aligned.
|
|
|
|
|
*/
|
|
|
|
|
uint32_t *aux_addr_dw = state_inout->state.map +
|
|
|
|
|
device->isl_dev.ss.aux_addr_offset;
|
2018-05-30 17:16:52 -07:00
|
|
|
assert((aux_address.offset & 0xfff) == 0);
|
|
|
|
|
state_inout->aux_address.offset |= *aux_addr_dw & 0xfff;
|
2018-01-18 09:50:48 -08:00
|
|
|
|
|
|
|
|
if (device->info.gen >= 10 && clear_address.bo) {
|
|
|
|
|
uint32_t *clear_addr_dw = state_inout->state.map +
|
|
|
|
|
device->isl_dev.ss.clear_color_state_offset;
|
|
|
|
|
assert((clear_address.offset & 0x3f) == 0);
|
2018-05-30 17:16:52 -07:00
|
|
|
state_inout->clear_address.offset |= *clear_addr_dw & 0x3f;
|
2018-01-18 09:50:48 -08:00
|
|
|
}
|
2017-07-11 10:06:36 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (image_param_out) {
|
|
|
|
|
assert(view_usage == ISL_SURF_USAGE_STORAGE_BIT);
|
|
|
|
|
isl_surf_fill_image_param(&device->isl_dev, image_param_out,
|
|
|
|
|
&surface->isl, &view);
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-10-07 22:14:03 -07:00
|
|
|
|
2017-07-19 12:14:19 +01:00
|
|
|
static VkImageAspectFlags
|
|
|
|
|
remap_aspect_flags(VkImageAspectFlags view_aspects)
|
|
|
|
|
{
|
2017-11-02 16:05:45 -07:00
|
|
|
if (view_aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT_ANV) {
|
2018-08-21 09:46:46 -07:00
|
|
|
if (util_bitcount(view_aspects) == 1)
|
2017-07-19 12:14:19 +01:00
|
|
|
return VK_IMAGE_ASPECT_COLOR_BIT;
|
|
|
|
|
|
|
|
|
|
VkImageAspectFlags color_aspects = 0;
|
2018-08-21 09:46:46 -07:00
|
|
|
for (uint32_t i = 0; i < util_bitcount(view_aspects); i++)
|
2017-09-20 13:16:26 -07:00
|
|
|
color_aspects |= VK_IMAGE_ASPECT_PLANE_0_BIT << i;
|
2017-07-19 12:14:19 +01:00
|
|
|
return color_aspects;
|
|
|
|
|
}
|
|
|
|
|
/* No special remapping needed for depth & stencil aspects. */
|
|
|
|
|
return view_aspects;
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-02 10:21:20 +00:00
|
|
|
static uint32_t
|
|
|
|
|
anv_image_aspect_get_planes(VkImageAspectFlags aspect_mask)
|
|
|
|
|
{
|
|
|
|
|
uint32_t planes = 0;
|
|
|
|
|
|
|
|
|
|
if (aspect_mask & (VK_IMAGE_ASPECT_COLOR_BIT |
|
|
|
|
|
VK_IMAGE_ASPECT_DEPTH_BIT |
|
|
|
|
|
VK_IMAGE_ASPECT_STENCIL_BIT |
|
|
|
|
|
VK_IMAGE_ASPECT_PLANE_0_BIT))
|
|
|
|
|
planes++;
|
|
|
|
|
if (aspect_mask & VK_IMAGE_ASPECT_PLANE_1_BIT)
|
|
|
|
|
planes++;
|
|
|
|
|
if (aspect_mask & VK_IMAGE_ASPECT_PLANE_2_BIT)
|
|
|
|
|
planes++;
|
|
|
|
|
|
|
|
|
|
if ((aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT) != 0 &&
|
|
|
|
|
(aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT) != 0)
|
|
|
|
|
planes++;
|
|
|
|
|
|
|
|
|
|
return planes;
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-07 22:14:03 -07:00
|
|
|
VkResult
|
|
|
|
|
anv_CreateImageView(VkDevice _device,
|
|
|
|
|
const VkImageViewCreateInfo *pCreateInfo,
|
|
|
|
|
const VkAllocationCallbacks *pAllocator,
|
|
|
|
|
VkImageView *pView)
|
2015-08-19 21:36:57 -07:00
|
|
|
{
|
2016-10-07 22:14:03 -07:00
|
|
|
ANV_FROM_HANDLE(anv_device, device, _device);
|
2015-10-06 18:17:09 -07:00
|
|
|
ANV_FROM_HANDLE(anv_image, image, pCreateInfo->image);
|
2016-10-07 22:14:03 -07:00
|
|
|
struct anv_image_view *iview;
|
|
|
|
|
|
2017-07-11 11:07:45 -07:00
|
|
|
iview = vk_zalloc2(&device->alloc, pAllocator, sizeof(*iview), 8,
|
2016-10-07 22:14:03 -07:00
|
|
|
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
|
|
|
|
|
if (iview == NULL)
|
|
|
|
|
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
|
|
|
|
|
|
2015-10-06 19:11:58 -07:00
|
|
|
const VkImageSubresourceRange *range = &pCreateInfo->subresourceRange;
|
2015-10-06 18:17:09 -07:00
|
|
|
|
2015-12-01 12:52:56 -08:00
|
|
|
assert(range->layerCount > 0);
|
2015-10-06 19:11:58 -07:00
|
|
|
assert(range->baseMipLevel < image->levels);
|
2017-07-11 09:07:36 -07:00
|
|
|
|
2018-10-08 14:42:53 +03:00
|
|
|
/* Check if a conversion info was passed. */
|
|
|
|
|
const struct anv_format *conv_format = NULL;
|
|
|
|
|
const struct VkSamplerYcbcrConversionInfo *conv_info =
|
|
|
|
|
vk_find_struct_const(pCreateInfo->pNext, SAMPLER_YCBCR_CONVERSION_INFO);
|
|
|
|
|
|
|
|
|
|
/* If image has an external format, the pNext chain must contain an instance of
|
|
|
|
|
* VKSamplerYcbcrConversionInfo with a conversion object created with the same
|
|
|
|
|
* external format as image."
|
|
|
|
|
*/
|
|
|
|
|
assert(!image->external_format || conv_info);
|
|
|
|
|
|
|
|
|
|
if (conv_info) {
|
|
|
|
|
ANV_FROM_HANDLE(anv_ycbcr_conversion, conversion, conv_info->conversion);
|
|
|
|
|
conv_format = conversion->format;
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-20 13:16:26 -07:00
|
|
|
const VkImageViewUsageCreateInfo *usage_info =
|
|
|
|
|
vk_find_struct_const(pCreateInfo, IMAGE_VIEW_USAGE_CREATE_INFO);
|
2017-07-11 09:07:36 -07:00
|
|
|
VkImageUsageFlags view_usage = usage_info ? usage_info->usage : image->usage;
|
|
|
|
|
/* View usage should be a subset of image usage */
|
|
|
|
|
assert((view_usage & ~image->usage) == 0);
|
|
|
|
|
assert(view_usage & (VK_IMAGE_USAGE_SAMPLED_BIT |
|
|
|
|
|
VK_IMAGE_USAGE_STORAGE_BIT |
|
|
|
|
|
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
|
|
|
|
|
VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT |
|
|
|
|
|
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT));
|
2015-10-06 19:11:58 -07:00
|
|
|
|
|
|
|
|
switch (image->type) {
|
|
|
|
|
default:
|
|
|
|
|
unreachable("bad VkImageType");
|
|
|
|
|
case VK_IMAGE_TYPE_1D:
|
|
|
|
|
case VK_IMAGE_TYPE_2D:
|
2016-03-04 20:41:05 -08:00
|
|
|
assert(range->baseArrayLayer + anv_get_layerCount(image, range) - 1 <= image->array_size);
|
2015-10-06 19:11:58 -07:00
|
|
|
break;
|
|
|
|
|
case VK_IMAGE_TYPE_3D:
|
2016-03-04 20:41:05 -08:00
|
|
|
assert(range->baseArrayLayer + anv_get_layerCount(image, range) - 1
|
2015-10-06 19:11:58 -07:00
|
|
|
<= anv_minify(image->extent.depth, range->baseMipLevel));
|
|
|
|
|
break;
|
|
|
|
|
}
|
2015-10-06 18:17:09 -07:00
|
|
|
|
2017-07-19 12:14:19 +01:00
|
|
|
/* First expand aspects to the image's ones (for example
|
|
|
|
|
* VK_IMAGE_ASPECT_COLOR_BIT will be converted to
|
2017-09-20 13:16:26 -07:00
|
|
|
* VK_IMAGE_ASPECT_PLANE_0_BIT | VK_IMAGE_ASPECT_PLANE_1_BIT |
|
|
|
|
|
* VK_IMAGE_ASPECT_PLANE_2_BIT for an image of format
|
2019-01-08 18:04:54 +00:00
|
|
|
* VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM.
|
2017-07-19 12:14:19 +01:00
|
|
|
*/
|
|
|
|
|
VkImageAspectFlags expanded_aspects =
|
|
|
|
|
anv_image_expand_aspects(image, range->aspectMask);
|
|
|
|
|
|
2016-01-01 13:47:18 -08:00
|
|
|
iview->image = image;
|
|
|
|
|
|
2017-07-19 12:14:19 +01:00
|
|
|
/* Remap the expanded aspects for the image view. For example if only
|
2017-09-20 13:16:26 -07:00
|
|
|
* VK_IMAGE_ASPECT_PLANE_1_BIT was given in range->aspectMask, we will
|
2017-07-19 12:14:19 +01:00
|
|
|
* convert it to VK_IMAGE_ASPECT_COLOR_BIT since from the point of view of
|
|
|
|
|
* the image view, it only has a single plane.
|
|
|
|
|
*/
|
|
|
|
|
iview->aspect_mask = remap_aspect_flags(expanded_aspects);
|
|
|
|
|
iview->n_planes = anv_image_aspect_get_planes(iview->aspect_mask);
|
2016-01-01 14:09:17 -08:00
|
|
|
iview->vk_format = pCreateInfo->format;
|
2016-01-26 11:10:56 -08:00
|
|
|
|
2018-10-08 14:42:53 +03:00
|
|
|
/* "If image has an external format, format must be VK_FORMAT_UNDEFINED." */
|
|
|
|
|
assert(!image->external_format || pCreateInfo->format == VK_FORMAT_UNDEFINED);
|
|
|
|
|
|
|
|
|
|
/* Format is undefined, this can happen when using external formats. Set
|
|
|
|
|
* view format from the passed conversion info.
|
|
|
|
|
*/
|
|
|
|
|
if (iview->vk_format == VK_FORMAT_UNDEFINED && conv_format)
|
|
|
|
|
iview->vk_format = conv_format->vk_format;
|
|
|
|
|
|
2016-01-01 13:47:18 -08:00
|
|
|
iview->extent = (VkExtent3D) {
|
2016-02-20 11:45:50 -08:00
|
|
|
.width = anv_minify(image->extent.width , range->baseMipLevel),
|
|
|
|
|
.height = anv_minify(image->extent.height, range->baseMipLevel),
|
|
|
|
|
.depth = anv_minify(image->extent.depth , range->baseMipLevel),
|
2016-01-01 13:47:18 -08:00
|
|
|
};
|
|
|
|
|
|
2017-07-19 12:14:19 +01:00
|
|
|
/* Now go through the underlying image selected planes (computed in
|
|
|
|
|
* expanded_aspects) and map them to planes in the image view.
|
|
|
|
|
*/
|
|
|
|
|
uint32_t iaspect_bit, vplane = 0;
|
|
|
|
|
anv_foreach_image_aspect_bit(iaspect_bit, image, expanded_aspects) {
|
|
|
|
|
uint32_t iplane =
|
2018-10-30 23:44:05 +00:00
|
|
|
anv_image_aspect_to_plane(image->aspects, 1UL << iaspect_bit);
|
2017-07-19 12:14:19 +01:00
|
|
|
VkImageAspectFlags vplane_aspect =
|
|
|
|
|
anv_plane_to_aspect(iview->aspect_mask, vplane);
|
|
|
|
|
struct anv_format_plane format =
|
2018-10-08 14:42:53 +03:00
|
|
|
anv_get_format_plane(&device->info, iview->vk_format,
|
2017-07-19 12:14:19 +01:00
|
|
|
vplane_aspect, image->tiling);
|
|
|
|
|
|
|
|
|
|
iview->planes[vplane].image_plane = iplane;
|
|
|
|
|
|
|
|
|
|
iview->planes[vplane].isl = (struct isl_view) {
|
|
|
|
|
.format = format.isl_format,
|
|
|
|
|
.base_level = range->baseMipLevel,
|
|
|
|
|
.levels = anv_get_levelCount(image, range),
|
|
|
|
|
.base_array_layer = range->baseArrayLayer,
|
|
|
|
|
.array_len = anv_get_layerCount(image, range),
|
|
|
|
|
.swizzle = {
|
|
|
|
|
.r = remap_swizzle(pCreateInfo->components.r,
|
|
|
|
|
VK_COMPONENT_SWIZZLE_R, format.swizzle),
|
|
|
|
|
.g = remap_swizzle(pCreateInfo->components.g,
|
|
|
|
|
VK_COMPONENT_SWIZZLE_G, format.swizzle),
|
|
|
|
|
.b = remap_swizzle(pCreateInfo->components.b,
|
|
|
|
|
VK_COMPONENT_SWIZZLE_B, format.swizzle),
|
|
|
|
|
.a = remap_swizzle(pCreateInfo->components.a,
|
|
|
|
|
VK_COMPONENT_SWIZZLE_A, format.swizzle),
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (pCreateInfo->viewType == VK_IMAGE_VIEW_TYPE_3D) {
|
|
|
|
|
iview->planes[vplane].isl.base_array_layer = 0;
|
|
|
|
|
iview->planes[vplane].isl.array_len = iview->extent.depth;
|
|
|
|
|
}
|
2016-09-19 15:14:56 -07:00
|
|
|
|
2017-07-19 12:14:19 +01:00
|
|
|
if (pCreateInfo->viewType == VK_IMAGE_VIEW_TYPE_CUBE ||
|
|
|
|
|
pCreateInfo->viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) {
|
|
|
|
|
iview->planes[vplane].isl.usage = ISL_SURF_USAGE_CUBE_BIT;
|
|
|
|
|
} else {
|
|
|
|
|
iview->planes[vplane].isl.usage = 0;
|
|
|
|
|
}
|
2016-02-20 11:45:50 -08:00
|
|
|
|
2017-07-19 12:14:19 +01:00
|
|
|
if (view_usage & VK_IMAGE_USAGE_SAMPLED_BIT ||
|
|
|
|
|
(view_usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT &&
|
|
|
|
|
!(iview->aspect_mask & VK_IMAGE_ASPECT_COLOR_BIT))) {
|
|
|
|
|
iview->planes[vplane].optimal_sampler_surface_state.state = alloc_surface_state(device);
|
|
|
|
|
iview->planes[vplane].general_sampler_surface_state.state = alloc_surface_state(device);
|
|
|
|
|
|
|
|
|
|
enum isl_aux_usage general_aux_usage =
|
|
|
|
|
anv_layout_to_aux_usage(&device->info, image, 1UL << iaspect_bit,
|
|
|
|
|
VK_IMAGE_LAYOUT_GENERAL);
|
|
|
|
|
enum isl_aux_usage optimal_aux_usage =
|
|
|
|
|
anv_layout_to_aux_usage(&device->info, image, 1UL << iaspect_bit,
|
|
|
|
|
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
|
|
|
|
|
|
|
|
|
anv_image_fill_surface_state(device, image, 1ULL << iaspect_bit,
|
|
|
|
|
&iview->planes[vplane].isl,
|
|
|
|
|
ISL_SURF_USAGE_TEXTURE_BIT,
|
|
|
|
|
optimal_aux_usage, NULL,
|
|
|
|
|
ANV_IMAGE_VIEW_STATE_TEXTURE_OPTIMAL,
|
|
|
|
|
&iview->planes[vplane].optimal_sampler_surface_state,
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
anv_image_fill_surface_state(device, image, 1ULL << iaspect_bit,
|
|
|
|
|
&iview->planes[vplane].isl,
|
|
|
|
|
ISL_SURF_USAGE_TEXTURE_BIT,
|
|
|
|
|
general_aux_usage, NULL,
|
|
|
|
|
0,
|
|
|
|
|
&iview->planes[vplane].general_sampler_surface_state,
|
|
|
|
|
NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* NOTE: This one needs to go last since it may stomp isl_view.format */
|
|
|
|
|
if (view_usage & VK_IMAGE_USAGE_STORAGE_BIT) {
|
|
|
|
|
iview->planes[vplane].storage_surface_state.state = alloc_surface_state(device);
|
|
|
|
|
iview->planes[vplane].writeonly_storage_surface_state.state = alloc_surface_state(device);
|
|
|
|
|
|
|
|
|
|
anv_image_fill_surface_state(device, image, 1ULL << iaspect_bit,
|
|
|
|
|
&iview->planes[vplane].isl,
|
|
|
|
|
ISL_SURF_USAGE_STORAGE_BIT,
|
|
|
|
|
ISL_AUX_USAGE_NONE, NULL,
|
|
|
|
|
0,
|
|
|
|
|
&iview->planes[vplane].storage_surface_state,
|
|
|
|
|
&iview->planes[vplane].storage_image_param);
|
|
|
|
|
|
|
|
|
|
anv_image_fill_surface_state(device, image, 1ULL << iaspect_bit,
|
|
|
|
|
&iview->planes[vplane].isl,
|
|
|
|
|
ISL_SURF_USAGE_STORAGE_BIT,
|
|
|
|
|
ISL_AUX_USAGE_NONE, NULL,
|
|
|
|
|
ANV_IMAGE_VIEW_STATE_STORAGE_WRITE_ONLY,
|
|
|
|
|
&iview->planes[vplane].writeonly_storage_surface_state,
|
|
|
|
|
NULL);
|
|
|
|
|
}
|
2016-01-22 11:57:01 -08:00
|
|
|
|
2017-07-19 12:14:19 +01:00
|
|
|
vplane++;
|
2015-08-19 21:36:57 -07:00
|
|
|
}
|
2015-08-20 22:59:19 -07:00
|
|
|
|
2016-10-07 22:14:03 -07:00
|
|
|
*pView = anv_image_view_to_handle(iview);
|
2015-05-08 22:32:37 -07:00
|
|
|
|
2015-08-20 22:59:19 -07:00
|
|
|
return VK_SUCCESS;
|
|
|
|
|
}
|
2015-08-19 21:36:57 -07:00
|
|
|
|
2015-12-02 03:28:27 -08:00
|
|
|
void
|
|
|
|
|
anv_DestroyImageView(VkDevice _device, VkImageView _iview,
|
|
|
|
|
const VkAllocationCallbacks *pAllocator)
|
2015-07-10 12:25:30 -07:00
|
|
|
{
|
2015-12-02 03:28:27 -08:00
|
|
|
ANV_FROM_HANDLE(anv_device, device, _device);
|
|
|
|
|
ANV_FROM_HANDLE(anv_image_view, iview, _iview);
|
|
|
|
|
|
2016-11-10 21:32:32 -08:00
|
|
|
if (!iview)
|
|
|
|
|
return;
|
|
|
|
|
|
2017-07-19 12:14:19 +01:00
|
|
|
for (uint32_t plane = 0; plane < iview->n_planes; plane++) {
|
|
|
|
|
if (iview->planes[plane].optimal_sampler_surface_state.state.alloc_size > 0) {
|
|
|
|
|
anv_state_pool_free(&device->surface_state_pool,
|
|
|
|
|
iview->planes[plane].optimal_sampler_surface_state.state);
|
|
|
|
|
}
|
2015-07-10 12:25:30 -07:00
|
|
|
|
2017-07-19 12:14:19 +01:00
|
|
|
if (iview->planes[plane].general_sampler_surface_state.state.alloc_size > 0) {
|
|
|
|
|
anv_state_pool_free(&device->surface_state_pool,
|
|
|
|
|
iview->planes[plane].general_sampler_surface_state.state);
|
|
|
|
|
}
|
2017-07-11 08:13:13 -07:00
|
|
|
|
2017-07-19 12:14:19 +01:00
|
|
|
if (iview->planes[plane].storage_surface_state.state.alloc_size > 0) {
|
|
|
|
|
anv_state_pool_free(&device->surface_state_pool,
|
|
|
|
|
iview->planes[plane].storage_surface_state.state);
|
|
|
|
|
}
|
2015-12-07 17:17:30 -08:00
|
|
|
|
2017-07-19 12:14:19 +01:00
|
|
|
if (iview->planes[plane].writeonly_storage_surface_state.state.alloc_size > 0) {
|
|
|
|
|
anv_state_pool_free(&device->surface_state_pool,
|
|
|
|
|
iview->planes[plane].writeonly_storage_surface_state.state);
|
|
|
|
|
}
|
2017-02-14 10:34:49 +00:00
|
|
|
}
|
|
|
|
|
|
2016-10-14 13:31:35 +10:00
|
|
|
vk_free2(&device->alloc, pAllocator, iview);
|
2015-07-10 20:18:52 -07:00
|
|
|
}
|
2015-05-22 22:59:12 -07:00
|
|
|
|
2016-03-30 15:20:11 -07:00
|
|
|
|
2016-10-07 22:14:03 -07:00
|
|
|
VkResult
|
|
|
|
|
anv_CreateBufferView(VkDevice _device,
|
|
|
|
|
const VkBufferViewCreateInfo *pCreateInfo,
|
|
|
|
|
const VkAllocationCallbacks *pAllocator,
|
|
|
|
|
VkBufferView *pView)
|
2015-12-12 16:11:23 -08:00
|
|
|
{
|
2016-10-07 22:14:03 -07:00
|
|
|
ANV_FROM_HANDLE(anv_device, device, _device);
|
2015-12-12 16:11:23 -08:00
|
|
|
ANV_FROM_HANDLE(anv_buffer, buffer, pCreateInfo->buffer);
|
2016-10-07 22:14:03 -07:00
|
|
|
struct anv_buffer_view *view;
|
|
|
|
|
|
2016-10-14 13:31:35 +10:00
|
|
|
view = vk_alloc2(&device->alloc, pAllocator, sizeof(*view), 8,
|
2016-10-07 22:14:03 -07:00
|
|
|
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
|
|
|
|
|
if (!view)
|
|
|
|
|
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
|
2015-12-12 16:11:23 -08:00
|
|
|
|
2016-05-13 13:39:20 -07:00
|
|
|
/* TODO: Handle the format swizzle? */
|
2015-12-14 16:51:12 -08:00
|
|
|
|
2016-05-16 10:25:54 -07:00
|
|
|
view->format = anv_get_isl_format(&device->info, pCreateInfo->format,
|
2016-05-13 13:39:20 -07:00
|
|
|
VK_IMAGE_ASPECT_COLOR_BIT,
|
2016-05-15 21:15:59 -07:00
|
|
|
VK_IMAGE_TILING_LINEAR);
|
2016-07-14 21:11:14 -07:00
|
|
|
const uint32_t format_bs = isl_format_get_layout(view->format)->bpb / 8;
|
2017-03-04 10:07:56 -08:00
|
|
|
view->range = anv_buffer_get_range(buffer, pCreateInfo->offset,
|
|
|
|
|
pCreateInfo->range);
|
2016-07-14 21:11:14 -07:00
|
|
|
view->range = align_down_npot_u32(view->range, format_bs);
|
2015-12-14 14:09:35 -08:00
|
|
|
|
2018-05-30 18:05:54 -07:00
|
|
|
view->address = anv_address_add(buffer->address, pCreateInfo->offset);
|
2018-05-30 17:36:49 -07:00
|
|
|
|
2015-12-14 16:51:12 -08:00
|
|
|
if (buffer->usage & VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT) {
|
2016-10-07 22:14:03 -07:00
|
|
|
view->surface_state = alloc_surface_state(device);
|
2015-12-12 16:11:23 -08:00
|
|
|
|
2016-01-26 14:50:52 -08:00
|
|
|
anv_fill_buffer_surface_state(device, view->surface_state,
|
2015-12-14 16:51:12 -08:00
|
|
|
view->format,
|
2018-05-30 17:36:49 -07:00
|
|
|
view->address, view->range, format_bs);
|
2015-12-14 16:51:12 -08:00
|
|
|
} else {
|
|
|
|
|
view->surface_state = (struct anv_state){ 0 };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (buffer->usage & VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT) {
|
2016-10-07 22:14:03 -07:00
|
|
|
view->storage_surface_state = alloc_surface_state(device);
|
2017-02-14 10:34:49 +00:00
|
|
|
view->writeonly_storage_surface_state = alloc_surface_state(device);
|
2015-12-12 16:11:23 -08:00
|
|
|
|
2015-12-14 16:51:12 -08:00
|
|
|
enum isl_format storage_format =
|
2016-04-15 17:08:18 -07:00
|
|
|
isl_has_matching_typed_storage_image_format(&device->info,
|
|
|
|
|
view->format) ?
|
2016-04-15 16:53:31 -07:00
|
|
|
isl_lower_storage_image_format(&device->info, view->format) :
|
2016-01-26 12:23:08 -08:00
|
|
|
ISL_FORMAT_RAW;
|
2015-12-14 16:51:12 -08:00
|
|
|
|
2016-01-26 14:50:52 -08:00
|
|
|
anv_fill_buffer_surface_state(device, view->storage_surface_state,
|
2015-12-14 16:51:12 -08:00
|
|
|
storage_format,
|
2018-05-30 17:36:49 -07:00
|
|
|
view->address, view->range,
|
2016-01-26 12:23:08 -08:00
|
|
|
(storage_format == ISL_FORMAT_RAW ? 1 :
|
2016-07-08 22:11:06 -07:00
|
|
|
isl_format_get_layout(storage_format)->bpb / 8));
|
2016-01-26 12:23:08 -08:00
|
|
|
|
2017-02-14 10:34:49 +00:00
|
|
|
/* Write-only accesses should use the original format. */
|
|
|
|
|
anv_fill_buffer_surface_state(device, view->writeonly_storage_surface_state,
|
|
|
|
|
view->format,
|
2018-05-30 17:36:49 -07:00
|
|
|
view->address, view->range,
|
2017-02-14 10:34:49 +00:00
|
|
|
isl_format_get_layout(view->format)->bpb / 8);
|
|
|
|
|
|
2016-02-24 12:50:31 -08:00
|
|
|
isl_buffer_fill_image_param(&device->isl_dev,
|
|
|
|
|
&view->storage_image_param,
|
|
|
|
|
view->format, view->range);
|
2015-12-14 16:51:12 -08:00
|
|
|
} else {
|
|
|
|
|
view->storage_surface_state = (struct anv_state){ 0 };
|
2017-02-14 10:34:49 +00:00
|
|
|
view->writeonly_storage_surface_state = (struct anv_state){ 0 };
|
2015-12-14 16:51:12 -08:00
|
|
|
}
|
2015-12-12 16:11:23 -08:00
|
|
|
|
|
|
|
|
*pView = anv_buffer_view_to_handle(view);
|
|
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
anv_DestroyBufferView(VkDevice _device, VkBufferView bufferView,
|
|
|
|
|
const VkAllocationCallbacks *pAllocator)
|
|
|
|
|
{
|
|
|
|
|
ANV_FROM_HANDLE(anv_device, device, _device);
|
|
|
|
|
ANV_FROM_HANDLE(anv_buffer_view, view, bufferView);
|
|
|
|
|
|
2016-11-10 21:32:32 -08:00
|
|
|
if (!view)
|
|
|
|
|
return;
|
|
|
|
|
|
2015-12-14 16:51:12 -08:00
|
|
|
if (view->surface_state.alloc_size > 0)
|
|
|
|
|
anv_state_pool_free(&device->surface_state_pool,
|
|
|
|
|
view->surface_state);
|
|
|
|
|
|
|
|
|
|
if (view->storage_surface_state.alloc_size > 0)
|
|
|
|
|
anv_state_pool_free(&device->surface_state_pool,
|
|
|
|
|
view->storage_surface_state);
|
|
|
|
|
|
2017-02-14 10:34:49 +00:00
|
|
|
if (view->writeonly_storage_surface_state.alloc_size > 0)
|
|
|
|
|
anv_state_pool_free(&device->surface_state_pool,
|
|
|
|
|
view->writeonly_storage_surface_state);
|
|
|
|
|
|
2016-10-14 13:31:35 +10:00
|
|
|
vk_free2(&device->alloc, pAllocator, view);
|
2015-12-12 16:11:23 -08:00
|
|
|
}
|
|
|
|
|
|
2016-08-30 17:49:32 -07:00
|
|
|
const struct anv_surface *
|
|
|
|
|
anv_image_get_surface_for_aspect_mask(const struct anv_image *image,
|
|
|
|
|
VkImageAspectFlags aspect_mask)
|
2015-08-28 07:08:58 -07:00
|
|
|
{
|
2017-07-19 12:14:19 +01:00
|
|
|
VkImageAspectFlags sanitized_mask;
|
|
|
|
|
|
2015-10-05 06:48:14 -07:00
|
|
|
switch (aspect_mask) {
|
|
|
|
|
case VK_IMAGE_ASPECT_COLOR_BIT:
|
2016-10-07 22:07:04 -07:00
|
|
|
assert(image->aspects == VK_IMAGE_ASPECT_COLOR_BIT);
|
2017-07-19 12:14:19 +01:00
|
|
|
sanitized_mask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
|
|
|
break;
|
2015-10-05 06:48:14 -07:00
|
|
|
case VK_IMAGE_ASPECT_DEPTH_BIT:
|
2016-05-13 16:47:39 -07:00
|
|
|
assert(image->aspects & VK_IMAGE_ASPECT_DEPTH_BIT);
|
2017-07-19 12:14:19 +01:00
|
|
|
sanitized_mask = VK_IMAGE_ASPECT_DEPTH_BIT;
|
|
|
|
|
break;
|
2015-10-05 06:48:14 -07:00
|
|
|
case VK_IMAGE_ASPECT_STENCIL_BIT:
|
2016-05-13 16:47:39 -07:00
|
|
|
assert(image->aspects & VK_IMAGE_ASPECT_STENCIL_BIT);
|
2017-07-19 12:14:19 +01:00
|
|
|
sanitized_mask = VK_IMAGE_ASPECT_STENCIL_BIT;
|
|
|
|
|
break;
|
2015-10-05 06:48:14 -07:00
|
|
|
case VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT:
|
2016-05-13 16:47:39 -07:00
|
|
|
/* FINISHME: The Vulkan spec (git a511ba2) requires support for
|
|
|
|
|
* combined depth stencil formats. Specifically, it states:
|
|
|
|
|
*
|
|
|
|
|
* At least one of ename:VK_FORMAT_D24_UNORM_S8_UINT or
|
|
|
|
|
* ename:VK_FORMAT_D32_SFLOAT_S8_UINT must be supported.
|
|
|
|
|
*
|
|
|
|
|
* Image views with both depth and stencil aspects are only valid for
|
|
|
|
|
* render target attachments, in which case
|
|
|
|
|
* cmd_buffer_emit_depth_stencil() will pick out both the depth and
|
|
|
|
|
* stencil surfaces from the underlying surface.
|
|
|
|
|
*/
|
|
|
|
|
if (image->aspects & VK_IMAGE_ASPECT_DEPTH_BIT) {
|
2017-07-19 12:14:19 +01:00
|
|
|
sanitized_mask = VK_IMAGE_ASPECT_DEPTH_BIT;
|
2016-05-13 16:47:39 -07:00
|
|
|
} else {
|
|
|
|
|
assert(image->aspects == VK_IMAGE_ASPECT_STENCIL_BIT);
|
2017-07-19 12:14:19 +01:00
|
|
|
sanitized_mask = VK_IMAGE_ASPECT_STENCIL_BIT;
|
2015-10-07 09:03:47 -07:00
|
|
|
}
|
2017-07-19 12:14:19 +01:00
|
|
|
break;
|
2017-09-20 13:16:26 -07:00
|
|
|
case VK_IMAGE_ASPECT_PLANE_0_BIT:
|
2017-11-02 16:05:45 -07:00
|
|
|
assert((image->aspects & ~VK_IMAGE_ASPECT_ANY_COLOR_BIT_ANV) == 0);
|
2017-09-20 13:16:26 -07:00
|
|
|
sanitized_mask = VK_IMAGE_ASPECT_PLANE_0_BIT;
|
2017-07-19 12:14:19 +01:00
|
|
|
break;
|
2017-09-20 13:16:26 -07:00
|
|
|
case VK_IMAGE_ASPECT_PLANE_1_BIT:
|
2017-11-02 16:05:45 -07:00
|
|
|
assert((image->aspects & ~VK_IMAGE_ASPECT_ANY_COLOR_BIT_ANV) == 0);
|
2017-09-20 13:16:26 -07:00
|
|
|
sanitized_mask = VK_IMAGE_ASPECT_PLANE_1_BIT;
|
2017-07-19 12:14:19 +01:00
|
|
|
break;
|
2017-09-20 13:16:26 -07:00
|
|
|
case VK_IMAGE_ASPECT_PLANE_2_BIT:
|
2017-11-02 16:05:45 -07:00
|
|
|
assert((image->aspects & ~VK_IMAGE_ASPECT_ANY_COLOR_BIT_ANV) == 0);
|
2017-09-20 13:16:26 -07:00
|
|
|
sanitized_mask = VK_IMAGE_ASPECT_PLANE_2_BIT;
|
2017-07-19 12:14:19 +01:00
|
|
|
break;
|
|
|
|
|
default:
|
2015-08-28 07:08:58 -07:00
|
|
|
unreachable("image does not have aspect");
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
2017-07-19 12:14:19 +01:00
|
|
|
|
|
|
|
|
uint32_t plane = anv_image_aspect_to_plane(image->aspects, sanitized_mask);
|
|
|
|
|
return &image->planes[plane].surface;
|
2015-08-28 07:08:58 -07:00
|
|
|
}
|