iris: Use SATURATE
[mesa.git] / src / gallium / drivers / iris / iris_resource.c
index df1bf0f745126258d13245a927976e3d269ffe42..3d2805f3548843323f0a74e70befc7ae7a2821fd 100644 (file)
@@ -85,7 +85,8 @@ modifier_is_supported(const struct gen_device_info *devinfo,
 
       enum isl_format linear_format = isl_format_srgb_to_linear(rt_format);
 
-      if (!isl_format_supports_ccs_e(devinfo, linear_format))
+      if (linear_format == ISL_FORMAT_UNSUPPORTED ||
+          !isl_format_supports_ccs_e(devinfo, linear_format))
          return false;
 
       return devinfo->gen >= 9 && devinfo->gen <= 11;
@@ -213,6 +214,32 @@ pipe_bind_to_isl_usage(unsigned bindings)
    return usage;
 }
 
+enum isl_format
+iris_image_view_get_format(struct iris_context *ice,
+                           const struct pipe_image_view *img)
+{
+   struct iris_screen *screen = (struct iris_screen *)ice->ctx.screen;
+   const struct gen_device_info *devinfo = &screen->devinfo;
+
+   isl_surf_usage_flags_t usage = ISL_SURF_USAGE_STORAGE_BIT;
+   enum isl_format isl_fmt =
+      iris_format_for_usage(devinfo, img->format, usage).fmt;
+
+   if (img->shader_access & PIPE_IMAGE_ACCESS_READ) {
+      /* On Gen8, try to use typed surfaces reads (which support a
+       * limited number of formats), and if not possible, fall back
+       * to untyped reads.
+       */
+      if (devinfo->gen == 8 &&
+          !isl_has_matching_typed_storage_image_format(devinfo, isl_fmt))
+         return ISL_FORMAT_RAW;
+      else
+         return isl_lower_storage_image_format(devinfo, isl_fmt);
+   }
+
+   return isl_fmt;
+}
+
 struct pipe_resource *
 iris_resource_get_separate_stencil(struct pipe_resource *p_res)
 {
@@ -313,6 +340,8 @@ iris_resource_destroy(struct pipe_screen *screen,
    iris_resource_disable_aux(res);
 
    iris_bo_unreference(res->bo);
+   iris_pscreen_unref(res->base.screen);
+
    free(res);
 }
 
@@ -325,7 +354,7 @@ iris_alloc_resource(struct pipe_screen *pscreen,
       return NULL;
 
    res->base = *templ;
-   res->base.screen = pscreen;
+   res->base.screen = iris_pscreen_ref(pscreen);
    pipe_reference_init(&res->base.reference, 1);
 
    res->aux.possible_usages = 1 << ISL_AUX_USAGE_NONE;
@@ -479,8 +508,20 @@ iris_resource_configure_aux(struct iris_screen *screen,
       res->aux.possible_usages |=
          1 << (has_ccs ? ISL_AUX_USAGE_MCS_CCS : ISL_AUX_USAGE_MCS);
    } else if (has_hiz) {
-      res->aux.possible_usages |=
-         1 << (has_ccs ? ISL_AUX_USAGE_HIZ_CCS : ISL_AUX_USAGE_HIZ);
+      if (!has_ccs) {
+         res->aux.possible_usages |= 1 << ISL_AUX_USAGE_HIZ;
+      } else if (res->surf.samples == 1 &&
+                 (res->surf.usage & ISL_SURF_USAGE_TEXTURE_BIT)) {
+         /* If this resource is single-sampled and will be used as a texture,
+          * put the HiZ surface in write-through mode so that we can sample
+          * from it.
+          */
+         res->aux.possible_usages |= 1 << ISL_AUX_USAGE_HIZ_CCS_WT;
+      } else {
+         res->aux.possible_usages |= 1 << ISL_AUX_USAGE_HIZ_CCS;
+      }
+   } else if (has_ccs && isl_surf_usage_is_stencil(res->surf.usage)) {
+      res->aux.possible_usages |= 1 << ISL_AUX_USAGE_STC_CCS;
    } else if (has_ccs) {
       if (want_ccs_e_for_format(devinfo, res->surf.format))
          res->aux.possible_usages |= 1 << ISL_AUX_USAGE_CCS_E;
@@ -499,11 +540,8 @@ iris_resource_configure_aux(struct iris_screen *screen,
    if (!devinfo->has_sample_with_hiz || res->surf.samples > 1)
       res->aux.sampler_usages &= ~(1 << ISL_AUX_USAGE_HIZ);
 
-   /* We don't always support sampling with HIZ_CCS. But when we do, treat it
-    * as CCS_E.*/
+   /* ISL_AUX_USAGE_HIZ_CCS doesn't support sampling at all */
    res->aux.sampler_usages &= ~(1 << ISL_AUX_USAGE_HIZ_CCS);
-   if (isl_surf_supports_hiz_ccs_wt(devinfo, &res->surf, res->aux.usage))
-      res->aux.sampler_usages |= 1 << ISL_AUX_USAGE_CCS_E;
 
    enum isl_aux_state initial_state;
    *aux_size_B = 0;
@@ -516,6 +554,7 @@ iris_resource_configure_aux(struct iris_screen *screen,
       return !res->mod_info || res->mod_info->aux_usage == ISL_AUX_USAGE_NONE;
    case ISL_AUX_USAGE_HIZ:
    case ISL_AUX_USAGE_HIZ_CCS:
+   case ISL_AUX_USAGE_HIZ_CCS_WT:
       initial_state = ISL_AUX_STATE_AUX_INVALID;
       break;
    case ISL_AUX_USAGE_MCS:
@@ -533,6 +572,7 @@ iris_resource_configure_aux(struct iris_screen *screen,
       break;
    case ISL_AUX_USAGE_CCS_D:
    case ISL_AUX_USAGE_CCS_E:
+   case ISL_AUX_USAGE_STC_CCS:
       /* When CCS_E is used, we need to ensure that the CCS starts off in
        * a valid state.  From the Sky Lake PRM, "MCS Buffer for Render
        * Target(s)":
@@ -546,13 +586,17 @@ iris_resource_configure_aux(struct iris_screen *screen,
        * For CCS_D, do the same thing.  On Gen9+, this avoids having any
        * undefined bits in the aux buffer.
        */
-      if (imported)
+      if (imported) {
+         assert(res->aux.usage != ISL_AUX_USAGE_STC_CCS);
          initial_state =
             isl_drm_modifier_get_default_aux_state(res->mod_info->modifier);
-      else
+      } else {
          initial_state = ISL_AUX_STATE_PASS_THROUGH;
+      }
       *alloc_flags |= BO_ALLOC_ZEROED;
       break;
+   case ISL_AUX_USAGE_MC:
+      unreachable("Unsupported aux mode");
    }
 
    /* Create the aux_state for the auxiliary buffer. */
@@ -626,20 +670,8 @@ iris_resource_init_aux_buf(struct iris_resource *res, uint32_t alloc_flags,
                 res->aux.surf.size_B);
       }
 
-      /* Bspec section titled : MCS/CCS Buffers for Render Target(s) states:
-       *    - If Software wants to enable Color Compression without Fast clear,
-       *      Software needs to initialize MCS with zeros.
-       *    - Lossless compression and CCS initialized to all F (using HW Fast
-       *      Clear or SW direct Clear)
-       *
-       * We think, the first bullet point above is referring to CCS aux
-       * surface. Since we initialize the MCS in the clear state, we also
-       * initialize the CCS in the clear state (via SW direct clear) to keep
-       * the two in sync.
-       */
       memset((char*)map + res->aux.extra_aux.offset,
-             isl_aux_usage_has_mcs(res->aux.usage) ? 0xFF : 0,
-             res->aux.extra_aux.surf.size_B);
+             0, res->aux.extra_aux.surf.size_B);
 
       /* Zero the indirect clear color to match ::fast_clear_color. */
       memset((char *)map + res->aux.clear_color_offset, 0,
@@ -769,6 +801,9 @@ iris_resource_create_for_buffer(struct pipe_screen *pscreen,
       return NULL;
    }
 
+   if (templ->bind & PIPE_BIND_SHARED)
+      iris_bo_make_external(res->bo);
+
    return &res->base;
 }
 
@@ -807,6 +842,8 @@ iris_resource_create_with_modifiers(struct pipe_screen *pscreen,
       if (templ->usage == PIPE_USAGE_STAGING ||
           templ->bind & (PIPE_BIND_LINEAR | PIPE_BIND_CURSOR) )
          tiling_flags = ISL_TILING_LINEAR_BIT;
+      else if (templ->bind & PIPE_BIND_SCANOUT)
+         tiling_flags = ISL_TILING_X_BIT;
    }
 
    isl_surf_usage_flags_t usage = pipe_bind_to_isl_usage(templ->bind);
@@ -890,6 +927,9 @@ iris_resource_create_with_modifiers(struct pipe_screen *pscreen,
       map_aux_addresses(screen, res);
    }
 
+   if (templ->bind & PIPE_BIND_SHARED)
+      iris_bo_make_external(res->bo);
+
    return &res->base;
 
 fail:
@@ -941,7 +981,7 @@ iris_resource_from_user_memory(struct pipe_screen *pscreen,
                                     user_memory, templ->width0,
                                     IRIS_MEMZONE_OTHER);
    if (!res->bo) {
-      free(res);
+      iris_resource_destroy(pscreen, &res->base);
       return NULL;
    }
 
@@ -984,7 +1024,7 @@ iris_resource_from_handle(struct pipe_screen *pscreen,
       unreachable("invalid winsys handle type");
    }
    if (!res->bo)
-      return NULL;
+      goto fail;
 
    res->offset = whandle->offset;
 
@@ -994,6 +1034,7 @@ iris_resource_from_handle(struct pipe_screen *pscreen,
    }
    assert(mod_inf);
 
+   res->external_format = whandle->format;
    res->mod_info = mod_inf;
 
    isl_surf_usage_flags_t isl_usage = pipe_bind_to_isl_usage(templ->bind);
@@ -1005,7 +1046,8 @@ iris_resource_from_handle(struct pipe_screen *pscreen,
    if (templ->target == PIPE_BUFFER) {
       res->surf.tiling = ISL_TILING_LINEAR;
    } else {
-      if (whandle->modifier == DRM_FORMAT_MOD_INVALID || whandle->plane == 0) {
+      /* Create a surface for each plane specified by the external format. */
+      if (whandle->plane < util_format_get_num_planes(whandle->format)) {
          UNUSED const bool isl_surf_created_successfully =
             isl_surf_init(&screen->isl_dev, &res->surf,
                           .dim = target_to_isl_surf_dim(templ->target),
@@ -1183,6 +1225,8 @@ iris_resource_get_handle(struct pipe_screen *pscreen,
       whandle->stride = res->surf.row_pitch_B;
       bo = res->bo;
    }
+
+   whandle->format = res->external_format;
    whandle->modifier =
       res->mod_info ? res->mod_info->modifier
                     : tiling_to_modifier(res->bo->tiling_mode);
@@ -1234,6 +1278,10 @@ iris_invalidate_resource(struct pipe_context *ctx,
    if (resource->target != PIPE_BUFFER)
       return;
 
+   /* If it's already invalidated, don't bother doing anything. */
+   if (res->valid_buffer_range.start > res->valid_buffer_range.end)
+      return;
+
    if (!resource_is_busy(ice, res)) {
       /* The resource is idle, so just mark that it contains no data and
        * keep using the same underlying buffer object.
@@ -1265,7 +1313,7 @@ iris_invalidate_resource(struct pipe_context *ctx,
    /* Rebind the buffer, replacing any state referring to the old BO's
     * address, and marking state dirty so it's reemitted.
     */
-   ice->vtbl.rebind_buffer(ice, res, old_bo->gtt_offset);
+   screen->vtbl.rebind_buffer(ice, res);
 
    util_range_set_empty(&res->valid_buffer_range);
 
@@ -1762,6 +1810,9 @@ iris_transfer_map(struct pipe_context *ctx,
    struct iris_resource *res = (struct iris_resource *)resource;
    struct isl_surf *surf = &res->surf;
 
+   if (iris_resource_unfinished_aux_import(res))
+      iris_resource_finish_aux_import(ctx->screen, res);
+
    if (usage & PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE) {
       /* Replace the backing storage with a fresh buffer for non-async maps */
       if (!(usage & (PIPE_TRANSFER_UNSYNCHRONIZED |
@@ -1782,13 +1833,16 @@ iris_transfer_map(struct pipe_context *ctx,
 
    if (resource->target != PIPE_BUFFER) {
       bool need_hiz_resolve = iris_resource_level_has_hiz(res, level);
+      bool need_stencil_resolve = res->aux.usage == ISL_AUX_USAGE_STC_CCS;
 
       need_color_resolve =
          (res->aux.usage == ISL_AUX_USAGE_CCS_D ||
           res->aux.usage == ISL_AUX_USAGE_CCS_E) &&
          iris_has_color_unresolved(res, level, 1, box->z, box->depth);
 
-      need_resolve = need_color_resolve || need_hiz_resolve;
+      need_resolve = need_color_resolve ||
+                     need_hiz_resolve ||
+                     need_stencil_resolve;
    }
 
    bool map_would_stall = false;