anv,hasvk: Add and use set_image_clear_color()

We're going to be storing clear colors from the drivers rather than
BLORP. Add a function for this purpose.

For now, the first use replaces init_fast_clear_color(). One change in
behavior is that the clear color initialization is now done without
write-checking on gfx12. This actually matches what anv does to other
writes to the image's fast-clear tracking state. We can fix this later
if and when we address the larger issue.

Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/30824>
This commit is contained in:
Nanley Chery 2024-08-15 18:11:55 -04:00 committed by Marge Bot
parent 27014df366
commit 5fd42500cf
2 changed files with 87 additions and 79 deletions

View file

@ -864,64 +864,6 @@ genX(cmd_buffer_mark_image_written)(struct anv_cmd_buffer *cmd_buffer,
#endif
}
static void
init_fast_clear_color(struct anv_cmd_buffer *cmd_buffer,
const struct anv_image *image,
VkImageAspectFlagBits aspect)
{
assert(cmd_buffer && image);
assert(image->vk.aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT_ANV);
/* Initialize the struct fields that are accessed for fast clears so that
* the HW restrictions on the field values are satisfied.
*
* On generations that do not support indirect clear color natively, we
* can just skip initializing the values, because they will be set by
* BLORP before actually doing the fast clear.
*
* For newer generations, we may not be able to skip initialization.
* Testing shows that writing to CLEAR_COLOR causes corruption if
* the surface is currently being used. So, care must be taken here.
* There are two cases that we consider:
*
* 1. For CCS_E without FCV, we can skip initializing the color-related
* fields, just like on the older platforms. Also, DWORDS 6 and 7
* are marked MBZ (or have a usable field on gfx11), but we can skip
* initializing them because in practice these fields need other
* state to be programmed for their values to matter.
*
* 2. When the FCV optimization is enabled, we must initialize the
* color-related fields. Otherwise, the engine might reference their
* uninitialized contents before we fill them for a manual fast clear
* with BLORP. Although the surface may be in use, no synchronization
* is needed before initialization. The only possible clear color we
* support in this mode is 0.
*/
#if GFX_VER == 12
const uint32_t plane = anv_image_aspect_to_plane(image, aspect);
if (image->planes[plane].aux_usage == ISL_AUX_USAGE_FCV_CCS_E) {
struct anv_device *device = cmd_buffer->device;
assert(!image->planes[plane].can_non_zero_fast_clear);
assert(device->isl_dev.ss.clear_color_state_size == 32);
unsigned num_dwords = 6;
struct anv_address addr =
anv_image_get_clear_color_addr(device, image, aspect);
struct mi_builder b;
mi_builder_init(&b, device->info, &cmd_buffer->batch);
mi_builder_set_mocs(&b, anv_mocs_for_address(device, &addr));
for (unsigned i = 0; i < num_dwords; i++) {
mi_builder_set_write_check(&b, i == (num_dwords - 1));
mi_store(&b, mi_mem32(anv_address_add(addr, i * 4)), mi_imm(0));
}
}
#endif
}
/* Copy the fast-clear value dword(s) between a surface state object and an
* image's fast clear state buffer.
*/
@ -969,6 +911,49 @@ genX(load_image_clear_color)(struct anv_cmd_buffer *cmd_buffer,
#endif
}
static void
set_image_clear_color(struct anv_cmd_buffer *cmd_buffer,
const struct anv_image *image,
const VkImageAspectFlags aspect,
const uint32_t *pixel)
{
UNUSED struct anv_batch *batch = &cmd_buffer->batch;
uint32_t plane = anv_image_aspect_to_plane(image, aspect);
enum isl_format format = image->planes[plane].primary_surface.isl.format;
union isl_color_value clear_color;
isl_color_value_unpack(&clear_color, format, pixel);
struct anv_address addr =
anv_image_get_clear_color_addr(cmd_buffer->device, image, aspect);
assert(!anv_address_is_null(addr));
#if GFX_VER >= 20
assert(cmd_buffer->device->isl_dev.ss.clear_color_state_size == 0);
assert(cmd_buffer->device->isl_dev.ss.clear_value_size == 0);
unreachable("storing clear colors on invalid gfx_ver" );
#elif GFX_VER >= 11
assert(cmd_buffer->device->isl_dev.ss.clear_color_state_size == 32);
uint32_t *dw = anv_batch_emitn(batch, 3 + 6, GENX(MI_STORE_DATA_IMM),
.StoreQword = true, .Address = addr);
dw[3] = clear_color.u32[0];
dw[4] = clear_color.u32[1];
dw[5] = clear_color.u32[2];
dw[6] = clear_color.u32[3];
dw[7] = pixel[0];
dw[8] = pixel[1];
#else
assert(cmd_buffer->device->isl_dev.ss.clear_color_state_size == 0);
assert(cmd_buffer->device->isl_dev.ss.clear_value_size == 16);
uint32_t *dw = anv_batch_emitn(batch, 3 + 4, GENX(MI_STORE_DATA_IMM),
.StoreQword = true, .Address = addr);
dw[3] = clear_color.u32[0];
dw[4] = clear_color.u32[1];
dw[5] = clear_color.u32[2];
dw[6] = clear_color.u32[3];
#endif
}
void
genX(set_fast_clear_state)(struct anv_cmd_buffer *cmd_buffer,
const struct anv_image *image,
@ -1230,11 +1215,15 @@ transition_color_buffer(struct anv_cmd_buffer *cmd_buffer,
}
if (must_init_fast_clear_state) {
if (image->planes[plane].aux_usage == ISL_AUX_USAGE_FCV_CCS_E) {
assert(!image->planes[plane].can_non_zero_fast_clear);
const uint32_t zero_pixel[4] = {};
set_image_clear_color(cmd_buffer, image, aspect, zero_pixel);
}
if (base_level == 0 && base_layer == 0) {
set_image_fast_clear_state(cmd_buffer, image, aspect,
ANV_FAST_CLEAR_NONE);
}
init_fast_clear_color(cmd_buffer, image, aspect);
}
if (must_init_aux_surface) {

View file

@ -758,38 +758,53 @@ genX(cmd_buffer_mark_image_written)(struct anv_cmd_buffer *cmd_buffer,
}
static void
init_fast_clear_color(struct anv_cmd_buffer *cmd_buffer,
set_image_clear_color(struct anv_cmd_buffer *cmd_buffer,
const struct anv_image *image,
VkImageAspectFlagBits aspect)
const VkImageAspectFlags aspect,
const union isl_color_value clear_color)
{
assert(cmd_buffer && image);
assert(image->vk.aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT_ANV);
uint32_t plane = anv_image_aspect_to_plane(image, aspect);
enum isl_format format = image->planes[plane].primary_surface.isl.format;
set_image_fast_clear_state(cmd_buffer, image, aspect,
ANV_FAST_CLEAR_NONE);
/* Initialize the struct fields that are accessed for fast-clears so that
* the HW restrictions on the field values are satisfied.
*/
struct anv_address addr =
anv_image_get_clear_color_addr(cmd_buffer->device, image, aspect);
assert(!anv_address_is_null(addr));
anv_batch_emit(&cmd_buffer->batch, GENX(MI_STORE_DATA_IMM), sdi) {
sdi.Address = addr;
if (GFX_VERx10 >= 75) {
/* Pre-SKL, the dword containing the clear values also contains
* other fields, so we need to initialize those fields to match the
* values that would be in a color attachment.
/* On HSW+, the RENDER_SURFACE_STATE dword containing the clear
* values also contains other fields. The dword constructed here
* will later be copied onto a surface state as-is. So, initialize
* those fields to match the values that we typically expect in a
* surface.
*
* XXX: Handle other values for ShaderChannelSelect and
* ResourceMinLOD.
*/
sdi.ImmediateData = ISL_CHANNEL_SELECT_RED << 25 |
ISL_CHANNEL_SELECT_GREEN << 22 |
ISL_CHANNEL_SELECT_BLUE << 19 |
ISL_CHANNEL_SELECT_ALPHA << 16;
} else if (GFX_VER == 7) {
/* On IVB, the dword containing the clear values also contains
* other fields that must be zero or can be zero.
*/
sdi.ImmediateData = 0;
}
if (isl_format_has_int_channel(format)) {
for (unsigned i = 0; i < 4; i++) {
assert(clear_color.u32[i] == 0 ||
clear_color.u32[i] == 1);
}
sdi.ImmediateData |= (clear_color.u32[0] != 0) << 31;
sdi.ImmediateData |= (clear_color.u32[1] != 0) << 30;
sdi.ImmediateData |= (clear_color.u32[2] != 0) << 29;
sdi.ImmediateData |= (clear_color.u32[3] != 0) << 28;
} else {
for (unsigned i = 0; i < 4; i++) {
assert(clear_color.f32[i] == 0.0f ||
clear_color.f32[i] == 1.0f);
}
sdi.ImmediateData |= (clear_color.f32[0] != 0.0f) << 31;
sdi.ImmediateData |= (clear_color.f32[1] != 0.0f) << 30;
sdi.ImmediateData |= (clear_color.f32[2] != 0.0f) << 29;
sdi.ImmediateData |= (clear_color.f32[3] != 0.0f) << 28;
}
}
}
@ -1010,8 +1025,12 @@ transition_color_buffer(struct anv_cmd_buffer *cmd_buffer,
}
if (must_init_fast_clear_state) {
if (base_level == 0 && base_layer == 0)
init_fast_clear_color(cmd_buffer, image, aspect);
if (base_level == 0 && base_layer == 0) {
const union isl_color_value zero_color = {};
set_image_clear_color(cmd_buffer, image, aspect, zero_color);
set_image_fast_clear_state(cmd_buffer, image, aspect,
ANV_FAST_CLEAR_NONE);
}
}
if (must_init_aux_surface) {