radv: add mipmap support for the clear depth/stencil values

Signed-off-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Reviewed-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
This commit is contained in:
Samuel Pitoiset 2019-06-06 17:30:17 +02:00
parent e36e260c42
commit 218ce34962
2 changed files with 59 additions and 27 deletions

View file

@ -1575,34 +1575,50 @@ radv_update_bound_fast_clear_ds(struct radv_cmd_buffer *cmd_buffer,
static void static void
radv_set_ds_clear_metadata(struct radv_cmd_buffer *cmd_buffer, radv_set_ds_clear_metadata(struct radv_cmd_buffer *cmd_buffer,
struct radv_image *image, struct radv_image *image,
const VkImageSubresourceRange *range,
VkClearDepthStencilValue ds_clear_value, VkClearDepthStencilValue ds_clear_value,
VkImageAspectFlags aspects) VkImageAspectFlags aspects)
{ {
struct radeon_cmdbuf *cs = cmd_buffer->cs; struct radeon_cmdbuf *cs = cmd_buffer->cs;
uint64_t va = radv_buffer_get_va(image->bo); uint64_t va = radv_get_ds_clear_value_va(image, range->baseMipLevel);
unsigned reg_offset = 0, reg_count = 0; uint32_t level_count = radv_get_levelCount(image, range);
va += image->offset + image->clear_value_offset; if (aspects & (VK_IMAGE_ASPECT_DEPTH_BIT |
VK_IMAGE_ASPECT_STENCIL_BIT)) {
/* Use the fastest way when both aspects are used. */
radeon_emit(cs, PKT3(PKT3_WRITE_DATA, 2 + 2 * level_count, cmd_buffer->state.predicating));
radeon_emit(cs, S_370_DST_SEL(V_370_MEM) |
S_370_WR_CONFIRM(1) |
S_370_ENGINE_SEL(V_370_PFP));
radeon_emit(cs, va);
radeon_emit(cs, va >> 32);
if (aspects & VK_IMAGE_ASPECT_STENCIL_BIT) { for (uint32_t l = 0; l < level_count; l++) {
++reg_count; radeon_emit(cs, ds_clear_value.stencil);
radeon_emit(cs, fui(ds_clear_value.depth));
}
} else { } else {
++reg_offset; /* Otherwise we need one WRITE_DATA packet per level. */
va += 4; for (uint32_t l = 0; l < level_count; l++) {
} uint64_t va = radv_get_ds_clear_value_va(image, range->baseMipLevel + l);
if (aspects & VK_IMAGE_ASPECT_DEPTH_BIT) unsigned value;
++reg_count;
radeon_emit(cs, PKT3(PKT3_WRITE_DATA, 2 + reg_count, cmd_buffer->state.predicating)); if (aspects & VK_IMAGE_ASPECT_DEPTH_BIT) {
radeon_emit(cs, S_370_DST_SEL(V_370_MEM) | value = fui(ds_clear_value.depth);
S_370_WR_CONFIRM(1) | va += 4;
S_370_ENGINE_SEL(V_370_PFP)); } else {
radeon_emit(cs, va); value = ds_clear_value.stencil;
radeon_emit(cs, va >> 32); }
if (aspects & VK_IMAGE_ASPECT_STENCIL_BIT)
radeon_emit(cs, ds_clear_value.stencil); radeon_emit(cs, PKT3(PKT3_WRITE_DATA, 3, cmd_buffer->state.predicating));
if (aspects & VK_IMAGE_ASPECT_DEPTH_BIT) radeon_emit(cs, S_370_DST_SEL(V_370_MEM) |
radeon_emit(cs, fui(ds_clear_value.depth)); S_370_WR_CONFIRM(1) |
S_370_ENGINE_SEL(V_370_PFP));
radeon_emit(cs, va);
radeon_emit(cs, va >> 32);
radeon_emit(cs, value);
}
}
} }
/** /**
@ -1665,11 +1681,19 @@ radv_update_ds_clear_metadata(struct radv_cmd_buffer *cmd_buffer,
VkClearDepthStencilValue ds_clear_value, VkClearDepthStencilValue ds_clear_value,
VkImageAspectFlags aspects) VkImageAspectFlags aspects)
{ {
VkImageSubresourceRange range = {
.aspectMask = iview->aspect_mask,
.baseMipLevel = iview->base_mip,
.levelCount = iview->level_count,
.baseArrayLayer = iview->base_layer,
.layerCount = iview->layer_count,
};
struct radv_image *image = iview->image; struct radv_image *image = iview->image;
assert(radv_image_has_htile(image)); assert(radv_image_has_htile(image));
radv_set_ds_clear_metadata(cmd_buffer, image, ds_clear_value, aspects); radv_set_ds_clear_metadata(cmd_buffer, iview->image, &range,
ds_clear_value, aspects);
if (radv_image_is_tc_compat_htile(image) && if (radv_image_is_tc_compat_htile(image) &&
(aspects & VK_IMAGE_ASPECT_DEPTH_BIT)) { (aspects & VK_IMAGE_ASPECT_DEPTH_BIT)) {
@ -1686,15 +1710,14 @@ radv_update_ds_clear_metadata(struct radv_cmd_buffer *cmd_buffer,
*/ */
static void static void
radv_load_ds_clear_metadata(struct radv_cmd_buffer *cmd_buffer, radv_load_ds_clear_metadata(struct radv_cmd_buffer *cmd_buffer,
struct radv_image *image) const struct radv_image_view *iview)
{ {
struct radeon_cmdbuf *cs = cmd_buffer->cs; struct radeon_cmdbuf *cs = cmd_buffer->cs;
const struct radv_image *image = iview->image;
VkImageAspectFlags aspects = vk_format_aspects(image->vk_format); VkImageAspectFlags aspects = vk_format_aspects(image->vk_format);
uint64_t va = radv_buffer_get_va(image->bo); uint64_t va = radv_get_ds_clear_value_va(image, iview->base_mip);
unsigned reg_offset = 0, reg_count = 0; unsigned reg_offset = 0, reg_count = 0;
va += image->offset + image->clear_value_offset;
if (!radv_image_has_htile(image)) if (!radv_image_has_htile(image))
return; return;
@ -1966,7 +1989,7 @@ radv_emit_framebuffer_state(struct radv_cmd_buffer *cmd_buffer)
cmd_buffer->state.dirty |= RADV_CMD_DIRTY_DYNAMIC_DEPTH_BIAS; cmd_buffer->state.dirty |= RADV_CMD_DIRTY_DYNAMIC_DEPTH_BIAS;
cmd_buffer->state.offset_scale = cmd_buffer->state.attachments[idx].ds.offset_scale; cmd_buffer->state.offset_scale = cmd_buffer->state.attachments[idx].ds.offset_scale;
} }
radv_load_ds_clear_metadata(cmd_buffer, image); radv_load_ds_clear_metadata(cmd_buffer, iview);
} else { } else {
if (cmd_buffer->device->physical_device->rad_info.chip_class == GFX9) if (cmd_buffer->device->physical_device->rad_info.chip_class == GFX9)
radeon_set_context_reg_seq(cmd_buffer->cs, R_028038_DB_Z_INFO, 2); radeon_set_context_reg_seq(cmd_buffer->cs, R_028038_DB_Z_INFO, 2);
@ -5081,7 +5104,7 @@ static void radv_initialize_htile(struct radv_cmd_buffer *cmd_buffer,
if (vk_format_is_stencil(image->vk_format)) if (vk_format_is_stencil(image->vk_format))
aspects |= VK_IMAGE_ASPECT_STENCIL_BIT; aspects |= VK_IMAGE_ASPECT_STENCIL_BIT;
radv_set_ds_clear_metadata(cmd_buffer, image, value, aspects); radv_set_ds_clear_metadata(cmd_buffer, image, range, value, aspects);
if (radv_image_is_tc_compat_htile(image)) { if (radv_image_is_tc_compat_htile(image)) {
/* Initialize the TC-compat metada value to 0 because by /* Initialize the TC-compat metada value to 0 because by

View file

@ -1814,6 +1814,15 @@ radv_get_tc_compat_zrange_va(const struct radv_image *image,
return va; return va;
} }
static inline uint64_t
radv_get_ds_clear_value_va(const struct radv_image *image,
uint32_t base_level)
{
uint64_t va = radv_buffer_get_va(image->bo);
va += image->offset + image->clear_value_offset + base_level * 8;
return va;
}
unsigned radv_image_queue_family_mask(const struct radv_image *image, uint32_t family, uint32_t queue_family); unsigned radv_image_queue_family_mask(const struct radv_image *image, uint32_t family, uint32_t queue_family);
static inline uint32_t static inline uint32_t