mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-01 22:40:09 +01:00
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:
parent
27014df366
commit
5fd42500cf
2 changed files with 87 additions and 79 deletions
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue