From 37f2692591cb1af12325d16f7fea17cc761ae9d5 Mon Sep 17 00:00:00 2001 From: Rafael Antognolli Date: Fri, 15 Feb 2019 14:45:05 -0800 Subject: [PATCH] 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 --- src/gallium/drivers/iris/iris_resource.c | 89 +++++++++++++++++++++--- src/gallium/drivers/iris/iris_resource.h | 19 +++++ 2 files changed, 100 insertions(+), 8 deletions(-) diff --git a/src/gallium/drivers/iris/iris_resource.c b/src/gallium/drivers/iris/iris_resource.c index 8bb0b3faa71..3e4b7e71c4a 100644 --- a/src/gallium/drivers/iris/iris_resource.c +++ b/src/gallium/drivers/iris/iris_resource.c @@ -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) { diff --git a/src/gallium/drivers/iris/iris_resource.h b/src/gallium/drivers/iris/iris_resource.h index d6bef37d898..3349d3eafc0 100644 --- a/src/gallium/drivers/iris/iris_resource.h +++ b/src/gallium/drivers/iris/iris_resource.h @@ -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); -- 2.30.2