iris: Allocate buffer space for the fast clear color.

Also store clear color in the iris_resource.

Always allocate clear color state buffer.

v2:
 - Make clear_color_offset be 64 bits (Ken).
 - Simplify the logic to decide when to memset the aux buffer (Ken).

Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
This commit is contained in:
Rafael Antognolli
2019-02-15 14:45:05 -08:00
parent 5f5ac19f13
commit 37f2692591
2 changed files with 100 additions and 8 deletions

View File

@@ -200,14 +200,14 @@ void
iris_resource_disable_aux(struct iris_resource *res)
{
iris_bo_unreference(res->aux.bo);
iris_bo_unreference(res->aux.clear_color_bo);
free(res->aux.state);
// XXX: clear color BO
res->aux.usage = ISL_AUX_USAGE_NONE;
res->aux.possible_usages = 1 << ISL_AUX_USAGE_NONE;
res->aux.surf.size_B = 0;
res->aux.bo = NULL;
res->aux.clear_color_bo = NULL;
res->aux.state = NULL;
}
@@ -294,6 +294,11 @@ iris_resource_alloc_aux(struct iris_screen *screen, struct iris_resource *res)
UNUSED bool ok = false;
uint8_t memset_value = 0;
uint32_t alloc_flags = 0;
const struct gen_device_info *devinfo = &screen->devinfo;
const unsigned clear_color_state_size = devinfo->gen >= 10 ?
screen->isl_dev.ss.clear_color_state_size :
screen->isl_dev.ss.clear_value_size;
assert(!res->aux.bo);
@@ -353,32 +358,50 @@ iris_resource_alloc_aux(struct iris_screen *screen, struct iris_resource *res)
if (!res->aux.state)
return false;
uint64_t size = res->aux.surf.size_B;
/* Allocate space in the buffer for storing the clear color. On modern
* platforms (gen > 9), we can read it directly from such buffer.
*
* On gen <= 9, we are going to store the clear color on the buffer
* anyways, and copy it back to the surface state during state emission.
*/
res->aux.clear_color_offset = size;
size += clear_color_state_size;
/* Allocate the auxiliary buffer. ISL has stricter set of alignment rules
* the drm allocator. Therefore, one can pass the ISL dimensions in terms
* of bytes instead of trying to recalculate based on different format
* block sizes.
*/
res->aux.bo = iris_bo_alloc_tiled(screen->bufmgr, "aux buffer",
res->aux.surf.size_B,
res->aux.bo = iris_bo_alloc_tiled(screen->bufmgr, "aux buffer", size,
IRIS_MEMZONE_OTHER, I915_TILING_Y,
res->aux.surf.row_pitch_B, alloc_flags);
if (!res->aux.bo) {
iris_resource_disable_aux(res);
return false;
}
/* Optionally, initialize the auxiliary data to the desired value. */
if (memset_value != 0) {
if (!(alloc_flags & BO_ALLOC_ZEROED)) {
void *map = iris_bo_map(NULL, res->aux.bo, MAP_WRITE | MAP_RAW);
if (!map) {
iris_resource_disable_aux(res);
return false;
}
memset(map, memset_value, res->aux.surf.size_B);
if (memset_value != 0)
memset(map, memset_value, res->aux.surf.size_B);
/* Zero the indirect clear color to match ::fast_clear_color. */
memset((char *)map + res->aux.clear_color_offset, 0,
clear_color_state_size);
iris_bo_unmap(res->aux.bo);
}
res->aux.clear_color_bo = res->aux.bo;
iris_bo_reference(res->aux.clear_color_bo);
if (res->aux.usage == ISL_AUX_USAGE_HIZ) {
for (unsigned level = 0; level < res->surf.levels; ++level) {
uint32_t width = u_minify(res->surf.phys_level0_sa.width, level);
@@ -1371,6 +1394,56 @@ iris_flush_and_dirty_for_history(struct iris_context *ice,
ice->state.dirty |= dirty;
}
bool
iris_resource_set_clear_color(struct iris_context *ice,
struct iris_resource *res,
union isl_color_value color)
{
if (memcmp(&res->aux.clear_color, &color, sizeof(color)) != 0) {
res->aux.clear_color = color;
struct iris_batch *batch = &ice->batches[IRIS_BATCH_RENDER];
/* We can't update the clear color while the hardware is still using
* the previous one for a resolve or sampling from it. Make sure that
* there are no pending commands at this point.
*/
/* TODO: Make these pipe controls gen-specific?
*
* We don't really need them on gen <= 9 where we are reading the
* clear color from the surface state and clear_params, so they
* shouldn't be needed. On gen11, the clear color is read from this
* buffer, but the clear depth is still read from CLEAR_PARAMS, so we
* could probably skip it in the HiZ case as well.
*
* Need to also check that for i965.
*/
iris_emit_pipe_control_flush(batch, PIPE_CONTROL_CS_STALL);
for (int i = 0; i < 4; i++) {
ice->vtbl.store_data_imm32(batch, res->aux.clear_color_bo,
res->aux.clear_color_offset + i * 4,
color.u32[i]);
}
iris_emit_pipe_control_flush(batch,
PIPE_CONTROL_STATE_CACHE_INVALIDATE);
return true;
}
return false;
}
union isl_color_value
iris_resource_get_clear_color(const struct iris_resource *res,
struct iris_bo **clear_color_bo,
uint64_t *clear_color_offset)
{
assert(res->aux.bo);
if (clear_color_bo)
*clear_color_bo = res->aux.clear_color_bo;
if (clear_color_offset)
*clear_color_offset = res->aux.clear_color_offset;
return res->aux.clear_color;
}
static enum pipe_format
iris_resource_get_internal_format(struct pipe_resource *p_res)
{

View File

@@ -86,6 +86,18 @@ struct iris_resource {
/** Offset into 'bo' where the auxiliary surface starts. */
uint32_t offset;
/**
* Fast clear color for this surface. For depth surfaces, the clear
* value is stored as a float32 in the red component.
*/
union isl_color_value clear_color;
/** Buffer object containing the indirect clear color. */
struct iris_bo *clear_color_bo;
/** Offset into bo where the clear color can be found. */
uint64_t clear_color_offset;
/**
* \brief The type of auxiliary compression used by this resource.
*
@@ -207,6 +219,13 @@ struct pipe_resource *iris_resource_get_separate_stencil(struct pipe_resource *)
void iris_get_depth_stencil_resources(struct pipe_resource *res,
struct iris_resource **out_z,
struct iris_resource **out_s);
bool iris_resource_set_clear_color(struct iris_context *ice,
struct iris_resource *res,
union isl_color_value color);
union isl_color_value
iris_resource_get_clear_color(const struct iris_resource *res,
struct iris_bo **clear_color_bo,
uint64_t *clear_color_offset);
void iris_init_screen_resource_functions(struct pipe_screen *pscreen);