anv: Implement VK_KHR_depth_stencil_resolve
This commit is contained in:
@@ -1130,6 +1130,34 @@ void anv_GetPhysicalDeviceProperties2(
|
|||||||
|
|
||||||
vk_foreach_struct(ext, pProperties->pNext) {
|
vk_foreach_struct(ext, pProperties->pNext) {
|
||||||
switch (ext->sType) {
|
switch (ext->sType) {
|
||||||
|
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES_KHR: {
|
||||||
|
VkPhysicalDeviceDepthStencilResolvePropertiesKHR *props =
|
||||||
|
(VkPhysicalDeviceDepthStencilResolvePropertiesKHR *)ext;
|
||||||
|
|
||||||
|
/* We support all of the depth resolve modes */
|
||||||
|
props->supportedDepthResolveModes =
|
||||||
|
VK_RESOLVE_MODE_SAMPLE_ZERO_BIT_KHR |
|
||||||
|
VK_RESOLVE_MODE_AVERAGE_BIT_KHR |
|
||||||
|
VK_RESOLVE_MODE_MIN_BIT_KHR |
|
||||||
|
VK_RESOLVE_MODE_MAX_BIT_KHR;
|
||||||
|
|
||||||
|
/* Average doesn't make sense for stencil so we don't support that */
|
||||||
|
props->supportedStencilResolveModes =
|
||||||
|
VK_RESOLVE_MODE_SAMPLE_ZERO_BIT_KHR;
|
||||||
|
if (pdevice->info.gen >= 8) {
|
||||||
|
/* The advanced stencil resolve modes currently require stencil
|
||||||
|
* sampling be supported by the hardware.
|
||||||
|
*/
|
||||||
|
props->supportedStencilResolveModes |=
|
||||||
|
VK_RESOLVE_MODE_MIN_BIT_KHR |
|
||||||
|
VK_RESOLVE_MODE_MAX_BIT_KHR;
|
||||||
|
}
|
||||||
|
|
||||||
|
props->independentResolveNone = VK_TRUE;
|
||||||
|
props->independentResolve = VK_TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR: {
|
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR: {
|
||||||
VkPhysicalDeviceDriverPropertiesKHR *driver_props =
|
VkPhysicalDeviceDriverPropertiesKHR *driver_props =
|
||||||
(VkPhysicalDeviceDriverPropertiesKHR *) ext;
|
(VkPhysicalDeviceDriverPropertiesKHR *) ext;
|
||||||
|
@@ -76,6 +76,7 @@ EXTENSIONS = [
|
|||||||
Extension('VK_KHR_bind_memory2', 1, True),
|
Extension('VK_KHR_bind_memory2', 1, True),
|
||||||
Extension('VK_KHR_create_renderpass2', 1, True),
|
Extension('VK_KHR_create_renderpass2', 1, True),
|
||||||
Extension('VK_KHR_dedicated_allocation', 1, True),
|
Extension('VK_KHR_dedicated_allocation', 1, True),
|
||||||
|
Extension('VK_KHR_depth_stencil_resolve', 1, True),
|
||||||
Extension('VK_KHR_descriptor_update_template', 1, True),
|
Extension('VK_KHR_descriptor_update_template', 1, True),
|
||||||
Extension('VK_KHR_device_group', 1, True),
|
Extension('VK_KHR_device_group', 1, True),
|
||||||
Extension('VK_KHR_device_group_creation', 1, True),
|
Extension('VK_KHR_device_group_creation', 1, True),
|
||||||
|
@@ -74,6 +74,10 @@ anv_render_pass_compile(struct anv_render_pass *pass)
|
|||||||
subpass->depth_stencil_attachment->attachment == VK_ATTACHMENT_UNUSED)
|
subpass->depth_stencil_attachment->attachment == VK_ATTACHMENT_UNUSED)
|
||||||
subpass->depth_stencil_attachment = NULL;
|
subpass->depth_stencil_attachment = NULL;
|
||||||
|
|
||||||
|
if (subpass->ds_resolve_attachment &&
|
||||||
|
subpass->ds_resolve_attachment->attachment == VK_ATTACHMENT_UNUSED)
|
||||||
|
subpass->ds_resolve_attachment = NULL;
|
||||||
|
|
||||||
for (uint32_t j = 0; j < subpass->attachment_count; j++) {
|
for (uint32_t j = 0; j < subpass->attachment_count; j++) {
|
||||||
struct anv_subpass_attachment *subpass_att = &subpass->attachments[j];
|
struct anv_subpass_attachment *subpass_att = &subpass->attachments[j];
|
||||||
if (subpass_att->attachment == VK_ATTACHMENT_UNUSED)
|
if (subpass_att->attachment == VK_ATTACHMENT_UNUSED)
|
||||||
@@ -116,6 +120,16 @@ anv_render_pass_compile(struct anv_render_pass *pass)
|
|||||||
color_att->usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
color_att->usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (subpass->ds_resolve_attachment) {
|
||||||
|
struct anv_subpass_attachment *ds_att =
|
||||||
|
subpass->depth_stencil_attachment;
|
||||||
|
UNUSED struct anv_subpass_attachment *resolve_att =
|
||||||
|
subpass->ds_resolve_attachment;
|
||||||
|
|
||||||
|
assert(resolve_att->usage == VK_IMAGE_USAGE_TRANSFER_DST_BIT);
|
||||||
|
ds_att->usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* From the Vulkan 1.0.39 spec:
|
/* From the Vulkan 1.0.39 spec:
|
||||||
@@ -342,10 +356,15 @@ VkResult anv_CreateRenderPass(
|
|||||||
static unsigned
|
static unsigned
|
||||||
num_subpass_attachments2(const VkSubpassDescription2KHR *desc)
|
num_subpass_attachments2(const VkSubpassDescription2KHR *desc)
|
||||||
{
|
{
|
||||||
|
const VkSubpassDescriptionDepthStencilResolveKHR *ds_resolve =
|
||||||
|
vk_find_struct_const(desc->pNext,
|
||||||
|
SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE_KHR);
|
||||||
|
|
||||||
return desc->inputAttachmentCount +
|
return desc->inputAttachmentCount +
|
||||||
desc->colorAttachmentCount +
|
desc->colorAttachmentCount +
|
||||||
(desc->pResolveAttachments ? desc->colorAttachmentCount : 0) +
|
(desc->pResolveAttachments ? desc->colorAttachmentCount : 0) +
|
||||||
(desc->pDepthStencilAttachment != NULL);
|
(desc->pDepthStencilAttachment != NULL) +
|
||||||
|
(ds_resolve && ds_resolve->pDepthStencilResolveAttachment);
|
||||||
}
|
}
|
||||||
|
|
||||||
VkResult anv_CreateRenderPass2KHR(
|
VkResult anv_CreateRenderPass2KHR(
|
||||||
@@ -460,6 +479,22 @@ VkResult anv_CreateRenderPass2KHR(
|
|||||||
.layout = desc->pDepthStencilAttachment->layout,
|
.layout = desc->pDepthStencilAttachment->layout,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const VkSubpassDescriptionDepthStencilResolveKHR *ds_resolve =
|
||||||
|
vk_find_struct_const(desc->pNext,
|
||||||
|
SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE_KHR);
|
||||||
|
|
||||||
|
if (ds_resolve && ds_resolve->pDepthStencilResolveAttachment) {
|
||||||
|
subpass->ds_resolve_attachment = subpass_attachments++;
|
||||||
|
|
||||||
|
*subpass->ds_resolve_attachment = (struct anv_subpass_attachment) {
|
||||||
|
.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT,
|
||||||
|
.attachment = ds_resolve->pDepthStencilResolveAttachment->attachment,
|
||||||
|
.layout = ds_resolve->pDepthStencilResolveAttachment->layout,
|
||||||
|
};
|
||||||
|
subpass->depth_resolve_mode = ds_resolve->depthResolveMode;
|
||||||
|
subpass->stencil_resolve_mode = ds_resolve->stencilResolveMode;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint32_t i = 0; i < pCreateInfo->dependencyCount; i++)
|
for (uint32_t i = 0; i < pCreateInfo->dependencyCount; i++)
|
||||||
|
@@ -3235,6 +3235,9 @@ struct anv_subpass {
|
|||||||
struct anv_subpass_attachment * resolve_attachments;
|
struct anv_subpass_attachment * resolve_attachments;
|
||||||
|
|
||||||
struct anv_subpass_attachment * depth_stencil_attachment;
|
struct anv_subpass_attachment * depth_stencil_attachment;
|
||||||
|
struct anv_subpass_attachment * ds_resolve_attachment;
|
||||||
|
VkResolveModeFlagBitsKHR depth_resolve_mode;
|
||||||
|
VkResolveModeFlagBitsKHR stencil_resolve_mode;
|
||||||
|
|
||||||
uint32_t view_mask;
|
uint32_t view_mask;
|
||||||
|
|
||||||
|
@@ -3886,6 +3886,23 @@ cmd_buffer_begin_subpass(struct anv_cmd_buffer *cmd_buffer,
|
|||||||
cmd_buffer_emit_depth_stencil(cmd_buffer);
|
cmd_buffer_emit_depth_stencil(cmd_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static enum blorp_filter
|
||||||
|
vk_to_blorp_resolve_mode(VkResolveModeFlagBitsKHR vk_mode)
|
||||||
|
{
|
||||||
|
switch (vk_mode) {
|
||||||
|
case VK_RESOLVE_MODE_SAMPLE_ZERO_BIT_KHR:
|
||||||
|
return BLORP_FILTER_SAMPLE_0;
|
||||||
|
case VK_RESOLVE_MODE_AVERAGE_BIT_KHR:
|
||||||
|
return BLORP_FILTER_AVERAGE;
|
||||||
|
case VK_RESOLVE_MODE_MIN_BIT_KHR:
|
||||||
|
return BLORP_FILTER_MIN_SAMPLE;
|
||||||
|
case VK_RESOLVE_MODE_MAX_BIT_KHR:
|
||||||
|
return BLORP_FILTER_MAX_SAMPLE;
|
||||||
|
default:
|
||||||
|
return BLORP_FILTER_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cmd_buffer_end_subpass(struct anv_cmd_buffer *cmd_buffer)
|
cmd_buffer_end_subpass(struct anv_cmd_buffer *cmd_buffer)
|
||||||
{
|
{
|
||||||
@@ -3953,6 +3970,125 @@ cmd_buffer_end_subpass(struct anv_cmd_buffer *cmd_buffer)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (subpass->ds_resolve_attachment) {
|
||||||
|
/* We are about to do some MSAA resolves. We need to flush so that the
|
||||||
|
* result of writes to the MSAA depth attachments show up in the sampler
|
||||||
|
* when we blit to the single-sampled resolve target.
|
||||||
|
*/
|
||||||
|
cmd_buffer->state.pending_pipe_bits |=
|
||||||
|
ANV_PIPE_TEXTURE_CACHE_INVALIDATE_BIT |
|
||||||
|
ANV_PIPE_DEPTH_CACHE_FLUSH_BIT;
|
||||||
|
|
||||||
|
uint32_t src_att = subpass->depth_stencil_attachment->attachment;
|
||||||
|
uint32_t dst_att = subpass->ds_resolve_attachment->attachment;
|
||||||
|
|
||||||
|
assert(src_att < cmd_buffer->state.pass->attachment_count);
|
||||||
|
assert(dst_att < cmd_buffer->state.pass->attachment_count);
|
||||||
|
|
||||||
|
if (cmd_buffer->state.attachments[dst_att].pending_clear_aspects) {
|
||||||
|
/* From the Vulkan 1.0 spec:
|
||||||
|
*
|
||||||
|
* If the first use of an attachment in a render pass is as a
|
||||||
|
* resolve attachment, then the loadOp is effectively ignored
|
||||||
|
* as the resolve is guaranteed to overwrite all pixels in the
|
||||||
|
* render area.
|
||||||
|
*/
|
||||||
|
cmd_buffer->state.attachments[dst_att].pending_clear_aspects = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct anv_image_view *src_iview = fb->attachments[src_att];
|
||||||
|
struct anv_image_view *dst_iview = fb->attachments[dst_att];
|
||||||
|
|
||||||
|
const VkRect2D render_area = cmd_buffer->state.render_area;
|
||||||
|
|
||||||
|
if ((src_iview->image->aspects & VK_IMAGE_ASPECT_DEPTH_BIT) &&
|
||||||
|
subpass->depth_resolve_mode != VK_RESOLVE_MODE_NONE_KHR) {
|
||||||
|
|
||||||
|
struct anv_attachment_state *src_state =
|
||||||
|
&cmd_state->attachments[src_att];
|
||||||
|
struct anv_attachment_state *dst_state =
|
||||||
|
&cmd_state->attachments[dst_att];
|
||||||
|
|
||||||
|
/* MSAA resolves sample from the source attachment. Transition the
|
||||||
|
* depth attachment first to get rid of any HiZ that we may not be
|
||||||
|
* able to handle.
|
||||||
|
*/
|
||||||
|
transition_depth_buffer(cmd_buffer, src_iview->image,
|
||||||
|
src_state->current_layout,
|
||||||
|
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||||
|
src_state->aux_usage =
|
||||||
|
anv_layout_to_aux_usage(&cmd_buffer->device->info, src_iview->image,
|
||||||
|
VK_IMAGE_ASPECT_DEPTH_BIT,
|
||||||
|
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||||
|
src_state->current_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||||
|
|
||||||
|
/* MSAA resolves write to the resolve attachment as if it were any
|
||||||
|
* other transfer op. Transition the resolve attachment accordingly.
|
||||||
|
*/
|
||||||
|
VkImageLayout dst_initial_layout = dst_state->current_layout;
|
||||||
|
|
||||||
|
/* If our render area is the entire size of the image, we're going to
|
||||||
|
* blow it all away so we can claim the initial layout is UNDEFINED
|
||||||
|
* and we'll get a HiZ ambiguate instead of a resolve.
|
||||||
|
*/
|
||||||
|
if (dst_iview->image->type != VK_IMAGE_TYPE_3D &&
|
||||||
|
render_area.offset.x == 0 && render_area.offset.y == 0 &&
|
||||||
|
render_area.extent.width == dst_iview->extent.width &&
|
||||||
|
render_area.extent.height == dst_iview->extent.height)
|
||||||
|
dst_initial_layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
|
|
||||||
|
transition_depth_buffer(cmd_buffer, dst_iview->image,
|
||||||
|
dst_initial_layout,
|
||||||
|
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||||
|
dst_state->aux_usage =
|
||||||
|
anv_layout_to_aux_usage(&cmd_buffer->device->info, dst_iview->image,
|
||||||
|
VK_IMAGE_ASPECT_DEPTH_BIT,
|
||||||
|
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||||
|
dst_state->current_layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||||
|
|
||||||
|
enum blorp_filter filter =
|
||||||
|
vk_to_blorp_resolve_mode(subpass->depth_resolve_mode);
|
||||||
|
|
||||||
|
anv_image_msaa_resolve(cmd_buffer,
|
||||||
|
src_iview->image, src_state->aux_usage,
|
||||||
|
src_iview->planes[0].isl.base_level,
|
||||||
|
src_iview->planes[0].isl.base_array_layer,
|
||||||
|
dst_iview->image, dst_state->aux_usage,
|
||||||
|
dst_iview->planes[0].isl.base_level,
|
||||||
|
dst_iview->planes[0].isl.base_array_layer,
|
||||||
|
VK_IMAGE_ASPECT_DEPTH_BIT,
|
||||||
|
render_area.offset.x, render_area.offset.y,
|
||||||
|
render_area.offset.x, render_area.offset.y,
|
||||||
|
render_area.extent.width,
|
||||||
|
render_area.extent.height,
|
||||||
|
fb->layers, filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((src_iview->image->aspects & VK_IMAGE_ASPECT_STENCIL_BIT) &&
|
||||||
|
subpass->stencil_resolve_mode != VK_RESOLVE_MODE_NONE_KHR) {
|
||||||
|
|
||||||
|
enum isl_aux_usage src_aux_usage = ISL_AUX_USAGE_NONE;
|
||||||
|
enum isl_aux_usage dst_aux_usage = ISL_AUX_USAGE_NONE;
|
||||||
|
|
||||||
|
enum blorp_filter filter =
|
||||||
|
vk_to_blorp_resolve_mode(subpass->stencil_resolve_mode);
|
||||||
|
|
||||||
|
anv_image_msaa_resolve(cmd_buffer,
|
||||||
|
src_iview->image, src_aux_usage,
|
||||||
|
src_iview->planes[0].isl.base_level,
|
||||||
|
src_iview->planes[0].isl.base_array_layer,
|
||||||
|
dst_iview->image, dst_aux_usage,
|
||||||
|
dst_iview->planes[0].isl.base_level,
|
||||||
|
dst_iview->planes[0].isl.base_array_layer,
|
||||||
|
VK_IMAGE_ASPECT_STENCIL_BIT,
|
||||||
|
render_area.offset.x, render_area.offset.y,
|
||||||
|
render_area.offset.x, render_area.offset.y,
|
||||||
|
render_area.extent.width,
|
||||||
|
render_area.extent.height,
|
||||||
|
fb->layers, filter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (uint32_t i = 0; i < subpass->attachment_count; ++i) {
|
for (uint32_t i = 0; i < subpass->attachment_count; ++i) {
|
||||||
const uint32_t a = subpass->attachments[i].attachment;
|
const uint32_t a = subpass->attachments[i].attachment;
|
||||||
if (a == VK_ATTACHMENT_UNUSED)
|
if (a == VK_ATTACHMENT_UNUSED)
|
||||||
|
Reference in New Issue
Block a user