vulkan/meta: Support writing stencil as iterative discard

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24326>
This commit is contained in:
Faith Ekstrand 2023-01-30 20:12:03 -06:00 committed by Marge Bot
parent c184b54ef9
commit d813fe50a4
2 changed files with 144 additions and 86 deletions

View file

@ -52,6 +52,7 @@ struct vk_meta_device {
uint32_t max_bind_map_buffer_size_B;
bool use_layered_rendering;
bool use_stencil_export;
VkResult (*cmd_bind_map_buffer)(struct vk_command_buffer *cmd,
struct vk_meta_device *meta,

View file

@ -33,6 +33,7 @@
struct vk_meta_blit_key {
enum vk_meta_object_key_type key_type;
enum glsl_sampler_dim dim;
bool stencil_as_discard;
VkFormat dst_format;
VkImageAspectFlags aspects;
};
@ -69,7 +70,8 @@ aspect_to_tex_binding(VkImageAspectFlagBits aspect)
struct vk_meta_blit_push_data {
float x_off, y_off, x_scale, y_scale;
float z_off, z_scale;
int32_t arr_delta, _pad;
int32_t arr_delta;
uint32_t stencil_bit;
};
static inline void
@ -277,12 +279,20 @@ build_blit_shader(const struct vk_meta_blit_key *key)
nir_ssa_def *val = build_txl(b, texture, sampler, src_coord);
val = nir_trim_vector(b, val, out_comps);
const struct glsl_type *out_type = glsl_vector_type(base_type, out_comps);
nir_variable *out = nir_variable_create(b->shader, nir_var_shader_out,
out_type, out_name);
out->data.location = out_location;
if (key->stencil_as_discard) {
assert(key->aspects == VK_IMAGE_ASPECT_STENCIL_BIT);
nir_ssa_def *stencil_bit = nir_channel(b, z_xform, 3);
nir_discard_if(b, nir_ieq(b, nir_iand(b, val, stencil_bit),
nir_imm_int(b, 0)));
} else {
const struct glsl_type *out_type =
glsl_vector_type(base_type, out_comps);
nir_variable *out = nir_variable_create(b->shader, nir_var_shader_out,
out_type, out_name);
out->data.location = out_location;
nir_store_var(b, out, val, BITFIELD_MASK(out_comps));
nir_store_var(b, out, val, BITFIELD_MASK(out_comps));
}
}
return b->shader;
@ -394,6 +404,10 @@ get_blit_pipeline(struct vk_device *device,
VkPipelineDepthStencilStateCreateInfo ds_info = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
};
VkDynamicState dyn_tmp;
VkPipelineDynamicStateCreateInfo dyn_info = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
};
struct vk_meta_rendering_info render = {
.samples = 1,
};
@ -413,7 +427,13 @@ get_blit_pipeline(struct vk_device *device,
ds_info.front.passOp = VK_STENCIL_OP_REPLACE;
ds_info.front.compareMask = ~0u;
ds_info.front.writeMask = ~0u;
ds_info.front.reference = ~0;
ds_info.back = ds_info.front;
if (key->stencil_as_discard) {
dyn_tmp = VK_DYNAMIC_STATE_STENCIL_WRITE_MASK;
dyn_info.dynamicStateCount = 1;
dyn_info.pDynamicStates = &dyn_tmp;
}
render.stencil_attachment_format = key->dst_format;
}
@ -422,6 +442,7 @@ get_blit_pipeline(struct vk_device *device,
.stageCount = 1,
.pStages = &fs_info,
.pDepthStencilState = &ds_info,
.pDynamicState = &dyn_info,
.layout = layout,
};
@ -506,80 +527,6 @@ do_blit(struct vk_command_buffer *cmd,
return;
}
key->aspects = dst_subres.aspectMask;
VkImageView dst_view;
const VkImageViewUsageCreateInfo dst_view_usage = {
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO,
.usage = (key->aspects & VK_IMAGE_ASPECT_COLOR_BIT) ?
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT :
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
};
const VkImageViewCreateInfo dst_view_info = {
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
.pNext = &dst_view_usage,
.image = vk_image_to_handle(dst_image),
.viewType = vk_image_sampled_view_type(dst_image),
.format = dst_format,
.subresourceRange = {
.aspectMask = dst_subres.aspectMask,
.baseMipLevel = dst_subres.mipLevel,
.levelCount = 1,
.baseArrayLayer = dst_subres.baseArrayLayer,
.layerCount = dst_subres.layerCount,
},
};
result = vk_meta_create_image_view(cmd, meta, &dst_view_info,
&dst_view);
if (unlikely(result != VK_SUCCESS)) {
vk_command_buffer_set_error(cmd, result);
return;
}
const VkRenderingAttachmentInfo vk_att = {
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
.imageView = dst_view,
.imageLayout = dst_image_layout,
.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
};
VkRenderingInfo vk_render = {
.sType = VK_STRUCTURE_TYPE_RENDERING_INFO,
.renderArea = {
.offset = {
dst_rect->x0,
dst_rect->y0
},
.extent = {
dst_rect->x1 - dst_rect->x0,
dst_rect->y1 - dst_rect->y0
},
},
.layerCount = dst_rect->layer + dst_layer_count,
};
if (key->aspects & VK_IMAGE_ASPECT_COLOR_BIT) {
vk_render.colorAttachmentCount = 1;
vk_render.pColorAttachments = &vk_att;
}
if (key->aspects & VK_IMAGE_ASPECT_DEPTH_BIT)
vk_render.pDepthAttachment = &vk_att;
if (key->aspects & VK_IMAGE_ASPECT_STENCIL_BIT)
vk_render.pStencilAttachment = &vk_att;
disp->CmdBeginRendering(vk_command_buffer_to_handle(cmd), &vk_render);
VkPipeline pipeline;
result = get_blit_pipeline(device, meta, key,
pipeline_layout, &pipeline);
if (unlikely(result != VK_SUCCESS)) {
vk_command_buffer_set_error(cmd, result);
return;
}
disp->CmdBindPipeline(vk_command_buffer_to_handle(cmd),
VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
uint32_t desc_count = 0;
VkDescriptorImageInfo image_infos[3];
VkWriteDescriptorSet desc_writes[3];
@ -645,14 +592,124 @@ do_blit(struct vk_command_buffer *cmd,
pipeline_layout, 0,
desc_count, desc_writes);
disp->CmdPushConstants(vk_command_buffer_to_handle(cmd),
pipeline_layout,
VK_SHADER_STAGE_FRAGMENT_BIT,
0, sizeof(*push), push);
assert(dst_subres.aspectMask == src_subres.aspectMask);
VkImageAspectFlags aspects_left = dst_subres.aspectMask;
meta->cmd_draw_volume(cmd, meta, dst_rect, dst_layer_count);
while (aspects_left) {
key->aspects = aspects_left;
disp->CmdEndRendering(vk_command_buffer_to_handle(cmd));
/* If we need to write stencil via iterative discard, it has to be
* written by itself because otherwise the discards would also throw
* away color or depth data.
*/
if ((key->aspects & VK_IMAGE_ASPECT_STENCIL_BIT) &&
key->aspects != VK_IMAGE_ASPECT_STENCIL_BIT &&
!meta->use_stencil_export)
key->aspects &= ~VK_IMAGE_ASPECT_STENCIL_BIT;
key->stencil_as_discard = key->aspects == VK_IMAGE_ASPECT_STENCIL_BIT &&
!meta->use_stencil_export;
VkImageView dst_view;
const VkImageViewUsageCreateInfo dst_view_usage = {
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO,
.usage = (key->aspects & VK_IMAGE_ASPECT_COLOR_BIT) ?
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT :
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
};
const VkImageViewCreateInfo dst_view_info = {
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
.pNext = &dst_view_usage,
.image = vk_image_to_handle(dst_image),
.viewType = vk_image_sampled_view_type(dst_image),
.format = dst_format,
.subresourceRange = {
.aspectMask = dst_subres.aspectMask,
.baseMipLevel = dst_subres.mipLevel,
.levelCount = 1,
.baseArrayLayer = dst_subres.baseArrayLayer,
.layerCount = dst_subres.layerCount,
},
};
result = vk_meta_create_image_view(cmd, meta, &dst_view_info,
&dst_view);
if (unlikely(result != VK_SUCCESS)) {
vk_command_buffer_set_error(cmd, result);
return;
}
const VkRenderingAttachmentInfo vk_att = {
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
.imageView = dst_view,
.imageLayout = dst_image_layout,
.loadOp = key->stencil_as_discard ? VK_ATTACHMENT_LOAD_OP_CLEAR :
VK_ATTACHMENT_LOAD_OP_DONT_CARE,
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
};
VkRenderingInfo vk_render = {
.sType = VK_STRUCTURE_TYPE_RENDERING_INFO,
.renderArea = {
.offset = {
dst_rect->x0,
dst_rect->y0
},
.extent = {
dst_rect->x1 - dst_rect->x0,
dst_rect->y1 - dst_rect->y0
},
},
.layerCount = dst_rect->layer + dst_layer_count,
};
if (key->aspects & VK_IMAGE_ASPECT_COLOR_BIT) {
vk_render.colorAttachmentCount = 1;
vk_render.pColorAttachments = &vk_att;
}
if (key->aspects & VK_IMAGE_ASPECT_DEPTH_BIT)
vk_render.pDepthAttachment = &vk_att;
if (key->aspects & VK_IMAGE_ASPECT_STENCIL_BIT)
vk_render.pStencilAttachment = &vk_att;
disp->CmdBeginRendering(vk_command_buffer_to_handle(cmd), &vk_render);
VkPipeline pipeline;
result = get_blit_pipeline(device, meta, key,
pipeline_layout, &pipeline);
if (unlikely(result != VK_SUCCESS)) {
vk_command_buffer_set_error(cmd, result);
return;
}
disp->CmdBindPipeline(vk_command_buffer_to_handle(cmd),
VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
if (key->stencil_as_discard) {
for (uint32_t i = 0; i < 8; i++) {
push->stencil_bit = BITFIELD_BIT(i);
disp->CmdPushConstants(vk_command_buffer_to_handle(cmd),
pipeline_layout,
VK_SHADER_STAGE_FRAGMENT_BIT,
0, sizeof(*push), push);
disp->CmdSetStencilWriteMask(vk_command_buffer_to_handle(cmd),
VK_STENCIL_FACE_FRONT_AND_BACK,
push->stencil_bit);
meta->cmd_draw_volume(cmd, meta, dst_rect, dst_layer_count);
}
} else {
disp->CmdPushConstants(vk_command_buffer_to_handle(cmd),
pipeline_layout,
VK_SHADER_STAGE_FRAGMENT_BIT,
0, sizeof(*push), push);
meta->cmd_draw_volume(cmd, meta, dst_rect, dst_layer_count);
}
disp->CmdEndRendering(vk_command_buffer_to_handle(cmd));
aspects_left &= ~key->aspects;
}
}
void