anv: Add stencil texturing support for gen7

Intel hardware didn't get support for sampling from W-tiled (required
for stencil) images until Broadwell so we can't directly sample from
stencil.  Instead, if we want to support stencil texturing on gen7
hardware, we have to keep a texture-capable shadow copy around and use
BLORP to update when stencil changes.  The one thing this commit does
not implement is self-dependencies with stencil input attachments.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=99493
Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
This commit is contained in:
Jason Ekstrand 2019-06-16 21:21:16 -05:00
parent 4faa3145b1
commit f3ea0cf828
3 changed files with 96 additions and 7 deletions

View File

@ -514,14 +514,12 @@ anv_get_image_format_features(const struct gen_device_info *devinfo,
return 0;
flags |= VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT |
VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
VK_FORMAT_FEATURE_BLIT_SRC_BIT |
VK_FORMAT_FEATURE_BLIT_DST_BIT |
VK_FORMAT_FEATURE_TRANSFER_SRC_BIT |
VK_FORMAT_FEATURE_TRANSFER_DST_BIT;
if (aspects == VK_IMAGE_ASPECT_DEPTH_BIT || devinfo->gen >= 8)
flags |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
if ((aspects & VK_IMAGE_ASPECT_DEPTH_BIT) && devinfo->gen >= 9)
flags |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT_EXT;

View File

@ -336,6 +336,12 @@ make_surface(const struct anv_device *dev,
needs_shadow = true;
}
if (dev->info.gen <= 7 &&
aspect == VK_IMAGE_ASPECT_STENCIL_BIT &&
(image->usage & VK_IMAGE_USAGE_SAMPLED_BIT)) {
needs_shadow = true;
}
ok = isl_surf_init(&dev->isl_dev, &anv_surf->isl,
.dim = vk_to_isl_surf_dim[image->type],
.format = plane_format.isl_format,
@ -359,12 +365,11 @@ make_surface(const struct anv_device *dev,
/* 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.
* don't get garbage performance. If we're on gen7 and the image contains
* stencil, then we need to maintain a shadow because we can't texture from
* W-tiled images.
*/
if (needs_shadow) {
assert(aspect == VK_IMAGE_ASPECT_COLOR_BIT);
assert(tiling_flags == ISL_TILING_LINEAR_BIT);
ok = isl_surf_init(&dev->isl_dev, &image->planes[plane].shadow_surface.isl,
.dim = vk_to_isl_surf_dim[image->type],
.format = plane_format.isl_format,
@ -1275,6 +1280,16 @@ anv_image_fill_surface_state(struct anv_device *device,
surface = &image->planes[plane].shadow_surface;
}
/* For texturing from stencil on gen7, we have to sample from a shadow
* surface because we don't support W-tiling in the sampler.
*/
if (image->planes[plane].shadow_surface.isl.size_B > 0 &&
aspect == VK_IMAGE_ASPECT_STENCIL_BIT) {
assert(device->info.gen == 7);
assert(view_usage & ISL_SURF_USAGE_TEXTURE_BIT);
surface = &image->planes[plane].shadow_surface;
}
if (view_usage == ISL_SURF_USAGE_RENDER_TARGET_BIT)
view.swizzle = anv_swizzle_for_render(view.swizzle);

View File

@ -474,6 +474,13 @@ transition_depth_buffer(struct anv_cmd_buffer *cmd_buffer,
0, 0, 1, hiz_op);
}
static inline bool
vk_image_layout_stencil_write_optimal(VkImageLayout layout)
{
return layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL ||
layout == VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL;
}
/* Transitions a HiZ-enabled depth buffer from one layout to another. Unless
* the initial layout is undefined, the HiZ buffer and depth buffer will
* represent the same data at the end of this operation.
@ -486,6 +493,34 @@ transition_stencil_buffer(struct anv_cmd_buffer *cmd_buffer,
VkImageLayout initial_layout,
VkImageLayout final_layout)
{
#if GEN_GEN == 7
uint32_t plane = anv_image_aspect_to_plane(image->aspects,
VK_IMAGE_ASPECT_STENCIL_BIT);
/* On gen7, we have to store a texturable version of the stencil buffer in
* a shadow whenever VK_IMAGE_USAGE_SAMPLED_BIT is set and copy back and
* forth at strategic points. Stencil writes are only allowed in three
* layouts:
*
* - VK_IMAGE_LAYOUT_GENERAL
* - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
* - VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
* - VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL
*
* For general, we have no nice opportunity to transition so we do the copy
* to the shadow unconditionally at the end of the subpass. For transfer
* destinations, we can update it as part of the transfer op. For the
* other two, we delay the copy until a transition into some other layout.
*/
if (image->planes[plane].shadow_surface.isl.size_B > 0 &&
vk_image_layout_stencil_write_optimal(initial_layout) &&
!vk_image_layout_stencil_write_optimal(final_layout)) {
anv_image_copy_to_shadow(cmd_buffer, image,
VK_IMAGE_ASPECT_STENCIL_BIT,
base_level, level_count,
base_layer, layer_count);
}
#endif /* GEN_GEN == 7 */
}
#define MI_PREDICATE_SRC0 0x2400
@ -4503,6 +4538,47 @@ cmd_buffer_end_subpass(struct anv_cmd_buffer *cmd_buffer)
}
}
#if GEN_GEN == 7
/* On gen7, we have to store a texturable version of the stencil buffer in
* a shadow whenever VK_IMAGE_USAGE_SAMPLED_BIT is set and copy back and
* forth at strategic points. Stencil writes are only allowed in three
* layouts:
*
* - VK_IMAGE_LAYOUT_GENERAL
* - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
* - VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
* - VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL
*
* For general, we have no nice opportunity to transition so we do the copy
* to the shadow unconditionally at the end of the subpass. For transfer
* destinations, we can update it as part of the transfer op. For the
* other two, we delay the copy until a transition into some other layout.
*/
if (subpass->depth_stencil_attachment) {
uint32_t a = subpass->depth_stencil_attachment->attachment;
assert(a != VK_ATTACHMENT_UNUSED);
struct anv_attachment_state *att_state = &cmd_state->attachments[a];
struct anv_image_view *iview = fb->attachments[a];
const struct anv_image *image = iview->image;
if (image->aspects & VK_IMAGE_ASPECT_STENCIL_BIT) {
uint32_t plane = anv_image_aspect_to_plane(image->aspects,
VK_IMAGE_ASPECT_STENCIL_BIT);
if (image->planes[plane].shadow_surface.isl.size_B > 0 &&
att_state->current_layout == VK_IMAGE_LAYOUT_GENERAL) {
assert(image->aspects & VK_IMAGE_ASPECT_STENCIL_BIT);
anv_image_copy_to_shadow(cmd_buffer, image,
VK_IMAGE_ASPECT_STENCIL_BIT,
iview->planes[plane].isl.base_level, 1,
iview->planes[plane].isl.base_array_layer,
fb->layers);
}
}
}
#endif /* GEN_GEN == 7 */
for (uint32_t i = 0; i < subpass->attachment_count; ++i) {
const uint32_t a = subpass->attachments[i].attachment;
if (a == VK_ATTACHMENT_UNUSED)