mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-02-22 18:30:31 +01:00
hk: implement vkCmdClear*Image with fast-clears
Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io> Reviewed-by: Mary Guillemard <mary.guillemard@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/35662>
This commit is contained in:
parent
7120f86035
commit
9cdf486f14
2 changed files with 101 additions and 139 deletions
|
|
@ -4,6 +4,10 @@
|
|||
* Copyright 2022-2023 Collabora Ltd. and Red Hat Inc.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#include "util/format/u_formats.h"
|
||||
#include "util/macros.h"
|
||||
#include "util/u_math.h"
|
||||
#include "vulkan/vulkan_core.h"
|
||||
#include "hk_cmd_buffer.h"
|
||||
#include "layout.h"
|
||||
|
||||
|
|
@ -13,141 +17,113 @@
|
|||
#include "hk_image_view.h"
|
||||
#include "hk_physical_device.h"
|
||||
|
||||
#include "vk_format.h"
|
||||
#include "vk_meta.h"
|
||||
#include "libagx_dgc.h"
|
||||
#include "libagx_shaders.h"
|
||||
|
||||
static VkImageViewType
|
||||
render_view_type(VkImageType image_type, unsigned layer_count)
|
||||
void
|
||||
hk_clear_image(struct hk_cmd_buffer *cmd, struct hk_image *image,
|
||||
enum pipe_format view_format, const uint32_t *clear_value,
|
||||
const VkImageSubresourceRange *range, bool whole_3d)
|
||||
{
|
||||
switch (image_type) {
|
||||
case VK_IMAGE_TYPE_1D:
|
||||
return layer_count == 1 ? VK_IMAGE_VIEW_TYPE_1D
|
||||
: VK_IMAGE_VIEW_TYPE_1D_ARRAY;
|
||||
case VK_IMAGE_TYPE_2D:
|
||||
return layer_count == 1 ? VK_IMAGE_VIEW_TYPE_2D
|
||||
: VK_IMAGE_VIEW_TYPE_2D_ARRAY;
|
||||
case VK_IMAGE_TYPE_3D:
|
||||
return VK_IMAGE_VIEW_TYPE_3D;
|
||||
default:
|
||||
unreachable("Invalid image type");
|
||||
const uint32_t level_count =
|
||||
vk_image_subresource_level_count(&image->vk, range);
|
||||
|
||||
bool z = (range->aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT);
|
||||
bool s = (range->aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT);
|
||||
|
||||
unsigned first_plane = (s && !z) ? 1 : 0;
|
||||
unsigned last_plane = s ? 1 : 0;
|
||||
|
||||
if (image->plane_count == 1) {
|
||||
first_plane = 0;
|
||||
last_plane = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clear_image(struct hk_cmd_buffer *cmd, struct hk_image *image,
|
||||
VkImageLayout image_layout, VkFormat format,
|
||||
const VkClearValue *clear_value, uint32_t range_count,
|
||||
const VkImageSubresourceRange *ranges)
|
||||
{
|
||||
struct hk_device *dev = hk_cmd_buffer_device(cmd);
|
||||
ASSERTED VkResult result;
|
||||
|
||||
/* TODO: Use fast clear */
|
||||
bool compressed = image->planes[0].layout.compressed;
|
||||
perf_debug(cmd, "Image clear (%scompressed)", compressed ? "" : "un");
|
||||
|
||||
for (uint32_t r = 0; r < range_count; r++) {
|
||||
const uint32_t level_count =
|
||||
vk_image_subresource_level_count(&image->vk, &ranges[r]);
|
||||
for (unsigned plane = first_plane; plane <= last_plane; ++plane) {
|
||||
struct ail_layout *layout = &image->planes[plane].layout;
|
||||
perf_debug(cmd, "Image clear (%scompressed)",
|
||||
layout->compressed ? "" : "un");
|
||||
|
||||
for (uint32_t l = 0; l < level_count; l++) {
|
||||
const uint32_t level = ranges[r].baseMipLevel + l;
|
||||
const uint32_t level = range->baseMipLevel + l;
|
||||
|
||||
const VkExtent3D level_extent =
|
||||
vk_image_mip_level_extent(&image->vk, level);
|
||||
|
||||
uint32_t base_array_layer, layer_count;
|
||||
if (image->vk.image_type == VK_IMAGE_TYPE_3D) {
|
||||
if (image->vk.image_type == VK_IMAGE_TYPE_3D && whole_3d) {
|
||||
base_array_layer = 0;
|
||||
layer_count = level_extent.depth;
|
||||
} else {
|
||||
base_array_layer = ranges[r].baseArrayLayer;
|
||||
layer_count =
|
||||
vk_image_subresource_layer_count(&image->vk, &ranges[r]);
|
||||
base_array_layer = range->baseArrayLayer;
|
||||
layer_count = vk_image_subresource_layer_count(&image->vk, range);
|
||||
}
|
||||
|
||||
const VkImageViewUsageCreateInfo view_usage_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO,
|
||||
.usage = (ranges[r].aspectMask & VK_IMAGE_ASPECT_COLOR_BIT)
|
||||
? VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
|
||||
: VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
|
||||
};
|
||||
const VkImageViewCreateInfo view_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
||||
.flags = VK_IMAGE_VIEW_CREATE_DRIVER_INTERNAL_BIT_MESA,
|
||||
.pNext = &view_usage_info,
|
||||
.image = hk_image_to_handle(image),
|
||||
.viewType = render_view_type(image->vk.image_type, layer_count),
|
||||
.format = format,
|
||||
.subresourceRange =
|
||||
{
|
||||
.aspectMask = image->vk.aspects,
|
||||
.baseMipLevel = level,
|
||||
.levelCount = 1,
|
||||
.baseArrayLayer = base_array_layer,
|
||||
.layerCount = layer_count,
|
||||
},
|
||||
};
|
||||
enum pipe_format format = view_format ? view_format : layout->format;
|
||||
bool stencil = format == PIPE_FORMAT_S8_UINT;
|
||||
|
||||
/* We use vk_meta_create_image_view here for lifetime managemnt */
|
||||
VkImageView view;
|
||||
result =
|
||||
vk_meta_create_image_view(&cmd->vk, &dev->meta, &view_info, &view);
|
||||
assert(result == VK_SUCCESS);
|
||||
|
||||
VkRenderingInfo render = {
|
||||
.sType = VK_STRUCTURE_TYPE_RENDERING_INFO,
|
||||
.renderArea =
|
||||
{
|
||||
.offset = {0, 0},
|
||||
.extent = {level_extent.width, level_extent.height},
|
||||
},
|
||||
.layerCount = layer_count,
|
||||
};
|
||||
|
||||
VkRenderingAttachmentInfo vk_att = {
|
||||
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
|
||||
.imageView = view,
|
||||
.imageLayout = image_layout,
|
||||
.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
|
||||
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
|
||||
.clearValue = *clear_value,
|
||||
};
|
||||
|
||||
if (ranges[r].aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) {
|
||||
render.colorAttachmentCount = 1;
|
||||
render.pColorAttachments = &vk_att;
|
||||
if (stencil) {
|
||||
format = PIPE_FORMAT_R8_UINT;
|
||||
} else if (format == PIPE_FORMAT_Z16_UNORM) {
|
||||
format = PIPE_FORMAT_R16_UNORM;
|
||||
} else if (format == PIPE_FORMAT_Z32_FLOAT) {
|
||||
format = PIPE_FORMAT_R32_FLOAT;
|
||||
}
|
||||
if (ranges[r].aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT)
|
||||
render.pDepthAttachment = &vk_att;
|
||||
if (ranges[r].aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT)
|
||||
render.pStencilAttachment = &vk_att;
|
||||
|
||||
hk_CmdBeginRendering(hk_cmd_buffer_to_handle(cmd), &render);
|
||||
hk_CmdEndRendering(hk_cmd_buffer_to_handle(cmd));
|
||||
uint32_t c[4];
|
||||
util_format_pack_rgba(format, c, &clear_value[stencil ? 1 : 0], 1);
|
||||
|
||||
unsigned blocksize_B = util_format_get_blocksize(format);
|
||||
assert(util_is_power_of_two_nonzero(blocksize_B) && blocksize_B <= 16);
|
||||
|
||||
/* Splat out to 128-bit */
|
||||
uint8_t *bytes = (uint8_t *)c;
|
||||
for (unsigned i = 1; i < 16; ++i) {
|
||||
bytes[i] = bytes[i % blocksize_B];
|
||||
}
|
||||
|
||||
uint64_t address =
|
||||
image->planes[plane].addr +
|
||||
ail_get_layer_level_B(layout, base_array_layer, level);
|
||||
|
||||
uint32_t size = ail_get_level_size_B(layout, level);
|
||||
|
||||
assert((layout->layer_stride_B % 16) == 0 && "aligned");
|
||||
uint32_t layer_stride_uint4 = layout->layer_stride_B / 16;
|
||||
|
||||
if (ail_is_level_logically_compressed(layout, level)) {
|
||||
assert((layout->compression_layer_stride_B % 16) == 0 && "aligned");
|
||||
uint32_t meta_layer_stride_tl =
|
||||
layout->compression_layer_stride_B / 8;
|
||||
|
||||
uint64_t meta_addr =
|
||||
image->planes[plane].addr + layout->metadata_offset_B +
|
||||
(base_array_layer * layout->compression_layer_stride_B) +
|
||||
layout->level_offsets_compressed_B[level];
|
||||
|
||||
uint32_t word = (uint32_t)ail_tile_mode_solid(format);
|
||||
|
||||
struct agx_grid grid =
|
||||
agx_3d(ail_metadata_width_tl(layout, level),
|
||||
ail_metadata_height_tl(layout, level), layer_count);
|
||||
|
||||
struct ail_tile tilesize = layout->tilesize_el[level];
|
||||
|
||||
libagx_fast_clear(cmd, grid, AGX_BARRIER_ALL, meta_addr, address,
|
||||
grid.count[0], grid.count[1], tilesize.width_el,
|
||||
tilesize.height_el, meta_layer_stride_tl,
|
||||
layer_stride_uint4, util_logbase2(blocksize_B),
|
||||
util_logbase2(layout->sample_count_sa), c[0],
|
||||
c[1], c[2], c[3], word);
|
||||
} else {
|
||||
libagx_fill_uint4(cmd, agx_2d(DIV_ROUND_UP(size, 16), layer_count),
|
||||
AGX_BARRIER_ALL, address, layer_stride_uint4,
|
||||
c[0], c[1], c[2], c[3]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static VkFormat
|
||||
vk_packed_int_format_for_size(unsigned size_B)
|
||||
{
|
||||
switch (size_B) {
|
||||
case 1:
|
||||
return VK_FORMAT_R8_UINT;
|
||||
case 2:
|
||||
return VK_FORMAT_R16_UINT;
|
||||
case 4:
|
||||
return VK_FORMAT_R32_UINT;
|
||||
case 8:
|
||||
return VK_FORMAT_R32G32_UINT;
|
||||
case 16:
|
||||
return VK_FORMAT_R32G32B32A32_UINT;
|
||||
default:
|
||||
unreachable("Invalid image format size");
|
||||
}
|
||||
}
|
||||
|
||||
VKAPI_ATTR void VKAPI_CALL
|
||||
hk_CmdClearColorImage(VkCommandBuffer commandBuffer, VkImage _image,
|
||||
VkImageLayout imageLayout,
|
||||
|
|
@ -157,28 +133,10 @@ hk_CmdClearColorImage(VkCommandBuffer commandBuffer, VkImage _image,
|
|||
VK_FROM_HANDLE(hk_cmd_buffer, cmd, commandBuffer);
|
||||
VK_FROM_HANDLE(hk_image, image, _image);
|
||||
|
||||
VkClearValue clear_value = {
|
||||
.color = *pColor,
|
||||
};
|
||||
|
||||
VkFormat vk_format = image->vk.format;
|
||||
if (vk_format == VK_FORMAT_R64_UINT || vk_format == VK_FORMAT_R64_SINT)
|
||||
vk_format = VK_FORMAT_R32G32_UINT;
|
||||
|
||||
enum pipe_format p_format = hk_format_to_pipe_format(vk_format);
|
||||
assert(p_format != PIPE_FORMAT_NONE);
|
||||
|
||||
if (!ail_pixel_format[p_format].renderable) {
|
||||
memset(&clear_value, 0, sizeof(clear_value));
|
||||
util_format_pack_rgba(p_format, clear_value.color.uint32, pColor->uint32,
|
||||
1);
|
||||
|
||||
unsigned bpp = util_format_get_blocksize(p_format);
|
||||
vk_format = vk_packed_int_format_for_size(bpp);
|
||||
for (uint32_t r = 0; r < rangeCount; r++) {
|
||||
hk_clear_image(cmd, image, PIPE_FORMAT_NONE, pColor->uint32, &pRanges[r],
|
||||
true /* whole 3D */);
|
||||
}
|
||||
|
||||
clear_image(cmd, image, imageLayout, vk_format, &clear_value, rangeCount,
|
||||
pRanges);
|
||||
}
|
||||
|
||||
VKAPI_ATTR void VKAPI_CALL
|
||||
|
|
@ -191,10 +149,9 @@ hk_CmdClearDepthStencilImage(VkCommandBuffer commandBuffer, VkImage _image,
|
|||
VK_FROM_HANDLE(hk_cmd_buffer, cmd, commandBuffer);
|
||||
VK_FROM_HANDLE(hk_image, image, _image);
|
||||
|
||||
const VkClearValue clear_value = {
|
||||
.depthStencil = *pDepthStencil,
|
||||
};
|
||||
|
||||
clear_image(cmd, image, imageLayout, image->vk.format, &clear_value,
|
||||
rangeCount, pRanges);
|
||||
for (uint32_t r = 0; r < rangeCount; r++) {
|
||||
uint32_t colour[4] = {fui(pDepthStencil->depth), pDepthStencil->stencil};
|
||||
hk_clear_image(cmd, image, PIPE_FORMAT_NONE, colour, &pRanges[r],
|
||||
true /* whole 3D */);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -135,3 +135,8 @@ hk_image_aspects_to_plane(const struct hk_image *image,
|
|||
|
||||
struct agx_device;
|
||||
bool hk_can_compress_format(const struct agx_device *dev, VkFormat format);
|
||||
|
||||
struct hk_cmd_buffer;
|
||||
void hk_clear_image(struct hk_cmd_buffer *cmd, struct hk_image *image,
|
||||
enum pipe_format view_format, const uint32_t *clear_value,
|
||||
const VkImageSubresourceRange *range, bool whole_3d);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue