radv: optimize CmdClear{Color,DepthStencil}Image() for layered textures

If all layers are bound we can perform a fast color or depth clear
instead of iterating over all layers. This has the advantage
to avoid trashing the framebuffer for nothing if you we end up by
doing a fast clear when calling radv_clear_image_layer(), and
clearing all layers in one shot is obviously faster.

Signed-off-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Reviewed-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
This commit is contained in:
Samuel Pitoiset 2018-11-23 17:04:15 +01:00
parent 7484bc894b
commit 4b9df824f7
1 changed files with 86 additions and 4 deletions

View File

@ -1776,6 +1776,75 @@ radv_clear_image_layer(struct radv_cmd_buffer *cmd_buffer,
radv_DestroyFramebuffer(device_h, fb,
&cmd_buffer->pool->alloc);
}
/**
* Return TRUE if a fast color or depth clear has been performed.
*/
static bool
radv_fast_clear_range(struct radv_cmd_buffer *cmd_buffer,
struct radv_image *image,
VkFormat format,
VkImageLayout image_layout,
const VkImageSubresourceRange *range,
const VkClearValue *clear_val)
{
struct radv_image_view iview;
radv_image_view_init(&iview, cmd_buffer->device,
&(VkImageViewCreateInfo) {
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
.image = radv_image_to_handle(image),
.viewType = radv_meta_get_view_type(image),
.format = image->vk_format,
.subresourceRange = {
.aspectMask = range->aspectMask,
.baseMipLevel = range->baseMipLevel,
.levelCount = range->levelCount,
.baseArrayLayer = range->baseArrayLayer,
.layerCount = range->layerCount,
},
});
VkClearRect clear_rect = {
.rect = {
.offset = { 0, 0 },
.extent = {
radv_minify(image->info.width, range->baseMipLevel),
radv_minify(image->info.height, range->baseMipLevel),
},
},
.baseArrayLayer = range->baseArrayLayer,
.layerCount = range->layerCount,
};
VkClearAttachment clear_att = {
.aspectMask = range->aspectMask,
.colorAttachment = 0,
.clearValue = *clear_val,
};
if (vk_format_is_color(format)) {
if (radv_can_fast_clear_color(cmd_buffer, &iview,
image_layout, &clear_rect,
clear_att.clearValue.color, 0)) {
radv_fast_clear_color(cmd_buffer, &iview, &clear_att,
clear_att.colorAttachment,
NULL, NULL);
return true;
}
} else {
if (radv_can_fast_clear_depth(cmd_buffer, &iview, image_layout,
range->aspectMask, &clear_rect,
clear_att.clearValue.depthStencil)) {
radv_fast_clear_depth(cmd_buffer, &iview, &clear_att,
NULL, NULL);
return true;
}
}
return false;
}
static void
radv_cmd_clear_image(struct radv_cmd_buffer *cmd_buffer,
struct radv_image *image,
@ -1803,18 +1872,31 @@ radv_cmd_clear_image(struct radv_cmd_buffer *cmd_buffer,
internal_clear_value.color.uint32[0] = (r << 4) | (g & 0xf);
}
if (format == VK_FORMAT_R32G32B32_UINT ||
format == VK_FORMAT_R32G32B32_SINT ||
format == VK_FORMAT_R32G32B32_SFLOAT)
cs = true;
for (uint32_t r = 0; r < range_count; r++) {
const VkImageSubresourceRange *range = &ranges[r];
/* Try to perform a fast clear first, otherwise fallback to
* the legacy path.
*/
if (!cs &&
radv_fast_clear_range(cmd_buffer, image, format,
image_layout, range,
&internal_clear_value)) {
continue;
}
for (uint32_t l = 0; l < radv_get_levelCount(image, range); ++l) {
const uint32_t layer_count = image->type == VK_IMAGE_TYPE_3D ?
radv_minify(image->info.depth, range->baseMipLevel + l) :
radv_get_layerCount(image, range);
for (uint32_t s = 0; s < layer_count; ++s) {
if (cs ||
(format == VK_FORMAT_R32G32B32_UINT ||
format == VK_FORMAT_R32G32B32_SINT ||
format == VK_FORMAT_R32G32B32_SFLOAT)) {
if (cs) {
struct radv_meta_blit2d_surf surf;
surf.format = format;
surf.image = image;