diff options
Diffstat (limited to 'src/gallium/drivers')
-rw-r--r-- | src/gallium/drivers/iris/iris_resource.c | 125 |
1 files changed, 85 insertions, 40 deletions
diff --git a/src/gallium/drivers/iris/iris_resource.c b/src/gallium/drivers/iris/iris_resource.c index ac113e3e181..931a5f304cb 100644 --- a/src/gallium/drivers/iris/iris_resource.c +++ b/src/gallium/drivers/iris/iris_resource.c @@ -334,22 +334,31 @@ create_aux_state_map(struct iris_resource *res, enum isl_aux_state initial) return per_level_arr; } +static unsigned +iris_get_aux_clear_color_state_size(struct iris_screen *screen) +{ + const struct gen_device_info *devinfo = &screen->devinfo; + return + (devinfo->gen >= 10 ? screen->isl_dev.ss.clear_color_state_size : + (devinfo->gen >= 9 ? screen->isl_dev.ss.clear_value_size : 0)); +} + /** - * Allocate the initial aux surface for a resource based on aux.usage + * Configure aux for the resource, but don't allocate it. For images which + * might be shared with modifiers, we must allocate the image and aux data in + * a single bo. */ static bool -iris_resource_alloc_aux(struct iris_screen *screen, struct iris_resource *res) +iris_resource_configure_aux(struct iris_screen *screen, + struct iris_resource *res, uint64_t *aux_size_B, + uint32_t *alloc_flags) { struct isl_device *isl_dev = &screen->isl_dev; enum isl_aux_state initial_state; 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 : - (devinfo->gen >= 9 ? screen->isl_dev.ss.clear_value_size : 0); + *aux_size_B = 0; + *alloc_flags = 0; assert(!res->aux.bo); switch (res->aux.usage) { @@ -359,7 +368,6 @@ iris_resource_alloc_aux(struct iris_screen *screen, struct iris_resource *res) break; case ISL_AUX_USAGE_HIZ: initial_state = ISL_AUX_STATE_AUX_INVALID; - memset_value = 0; ok = isl_surf_get_hiz_surf(isl_dev, &res->surf, &res->aux.surf); break; case ISL_AUX_USAGE_MCS: @@ -373,7 +381,6 @@ iris_resource_alloc_aux(struct iris_screen *screen, struct iris_resource *res) * 1's, so we simply memset it to 0xff. */ initial_state = ISL_AUX_STATE_CLEAR; - memset_value = 0xFF; ok = isl_surf_get_mcs_surf(isl_dev, &res->surf, &res->aux.surf); break; case ISL_AUX_USAGE_CCS_D: @@ -392,7 +399,7 @@ iris_resource_alloc_aux(struct iris_screen *screen, struct iris_resource *res) * undefined bits in the aux buffer. */ initial_state = ISL_AUX_STATE_PASS_THROUGH; - alloc_flags |= BO_ALLOC_ZEROED; + *alloc_flags |= BO_ALLOC_ZEROED; ok = isl_surf_get_ccs_surf(isl_dev, &res->surf, &res->aux.surf, 0); break; } @@ -405,10 +412,12 @@ iris_resource_alloc_aux(struct iris_screen *screen, struct iris_resource *res) if (res->aux.surf.size_B == 0) return true; - /* Create the aux_state for the auxiliary buffer. */ - res->aux.state = create_aux_state_map(res, initial_state); - if (!res->aux.state) - return false; + if (!res->aux.state) { + /* Create the aux_state for the auxiliary buffer. */ + res->aux.state = create_aux_state_map(res, initial_state); + if (!res->aux.state) + return false; + } uint64_t size = res->aux.surf.size_B; @@ -419,20 +428,32 @@ iris_resource_alloc_aux(struct iris_screen *screen, struct iris_resource *res) * anyways, and copy it back to the surface state during state emission. */ res->aux.clear_color_offset = size; - size += clear_color_state_size; + size += iris_get_aux_clear_color_state_size(screen); + *aux_size_B = 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", size, 4096, - IRIS_MEMZONE_OTHER, I915_TILING_Y, - res->aux.surf.row_pitch_B, alloc_flags); - if (!res->aux.bo) { - return false; + 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); + uint32_t height = u_minify(res->surf.phys_level0_sa.height, level); + + /* Disable HiZ for LOD > 0 unless the width/height are 8x4 aligned. + * For LOD == 0, we can grow the dimensions to make it work. + */ + if (level == 0 || ((width & 7) == 0 && (height & 3) == 0)) + res->aux.has_hiz |= 1 << level; + } } + return true; +} + +/** + * Initialize the aux buffer contents. + */ +static bool +iris_resource_init_aux_buf(struct iris_resource *res, uint32_t alloc_flags, + unsigned clear_color_state_size) +{ if (!(alloc_flags & BO_ALLOC_ZEROED)) { void *map = iris_bo_map(NULL, res->aux.bo, MAP_WRITE | MAP_RAW); @@ -441,8 +462,11 @@ iris_resource_alloc_aux(struct iris_screen *screen, struct iris_resource *res) return false; } - if (memset_value != 0) - memset(map, memset_value, res->aux.surf.size_B); + if (iris_resource_get_aux_state(res, 0, 0) != ISL_AUX_STATE_AUX_INVALID) { + uint8_t memset_value = res->aux.usage == ISL_AUX_USAGE_MCS ? 0xFF : 0; + memset((char*)map + res->aux.offset, 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, @@ -456,19 +480,40 @@ iris_resource_alloc_aux(struct iris_screen *screen, struct iris_resource *res) 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); - uint32_t height = u_minify(res->surf.phys_level0_sa.height, level); + return true; +} - /* Disable HiZ for LOD > 0 unless the width/height are 8x4 aligned. - * For LOD == 0, we can grow the dimensions to make it work. - */ - if (level == 0 || ((width & 7) == 0 && (height & 3) == 0)) - res->aux.has_hiz |= 1 << level; - } +/** + * Allocate the initial aux surface for a resource based on aux.usage + */ +static bool +iris_resource_alloc_separate_aux(struct iris_screen *screen, + struct iris_resource *res) +{ + uint32_t alloc_flags; + uint64_t size; + if (!iris_resource_configure_aux(screen, res, &size, &alloc_flags)) + return false; + + if (size == 0) + return true; + + /* 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", size, 4096, + IRIS_MEMZONE_OTHER, I915_TILING_Y, + res->aux.surf.row_pitch_B, alloc_flags); + if (!res->aux.bo) { + return false; } + if (!iris_resource_init_aux_buf(res, alloc_flags, + iris_get_aux_clear_color_state_size(screen))) + return false; + return true; } @@ -674,7 +719,7 @@ iris_resource_create_with_modifiers(struct pipe_screen *pscreen, if (!res->bo) goto fail; - if (!iris_resource_alloc_aux(screen, res)) + if (!iris_resource_alloc_separate_aux(screen, res)) iris_resource_disable_aux(res); return &res->base; @@ -801,7 +846,7 @@ iris_resource_from_handle(struct pipe_screen *pscreen, isl_tiling_to_i915_tiling(res->surf.tiling)); // XXX: create_ccs_buf_for_image? - if (!iris_resource_alloc_aux(screen, res)) + if (!iris_resource_alloc_separate_aux(screen, res)) goto fail; } |