Пример #1
0
static struct pipe_surface *
ilo_create_surface(struct pipe_context *pipe,
                   struct pipe_resource *res,
                   const struct pipe_surface *templ)
{
   const struct ilo_dev_info *dev = ilo_context(pipe)->dev;
   struct ilo_surface_cso *surf;

   surf = MALLOC_STRUCT(ilo_surface_cso);
   assert(surf);

   surf->base = *templ;
   pipe_reference_init(&surf->base.reference, 1);
   surf->base.texture = NULL;
   pipe_resource_reference(&surf->base.texture, res);

   surf->base.context = pipe;
   surf->base.width = u_minify(res->width0, templ->u.tex.level);
   surf->base.height = u_minify(res->height0, templ->u.tex.level);

   surf->is_rt = !util_format_is_depth_or_stencil(templ->format);

   if (surf->is_rt) {
      /* relax this? */
      assert(res->target != PIPE_BUFFER);

      /*
       * classic i965 sets render_cache_rw for constant buffers and sol
       * surfaces but not render buffers.  Why?
       */
      ilo_gpe_init_view_surface_for_texture(dev, ilo_texture(res),
            templ->format, templ->u.tex.level, 1,
            templ->u.tex.first_layer,
            templ->u.tex.last_layer - templ->u.tex.first_layer + 1,
            true, &surf->u.rt);
   }
   else {
      assert(res->target != PIPE_BUFFER);

      ilo_gpe_init_zs_surface(dev, ilo_texture(res),
            templ->format, templ->u.tex.level,
            templ->u.tex.first_layer,
            templ->u.tex.last_layer - templ->u.tex.first_layer + 1,
            &surf->u.zs);
   }

   return &surf->base;
}
Пример #2
0
void
ilo_blitter_rectlist_resolve_hiz(struct ilo_blitter *blitter,
                                 struct pipe_resource *res,
                                 unsigned level, unsigned slice)
{
    struct ilo_texture *tex = ilo_texture(res);
    struct pipe_depth_stencil_alpha_state dsa_state;

    if (!ilo_image_can_enable_aux(&tex->image, level))
        return;

    /*
     * From the Sandy Bridge PRM, volume 2 part 1, page 315:
     *
     *     "(Hierarchical Depth Buffer Resolve) Depth Test Enable must be
     *      disabled. Depth Buffer Write Enable must be enabled. Stencil Test
     *      Enable and Stencil Buffer Write Enable must be disabled."
     */
    memset(&dsa_state, 0, sizeof(dsa_state));
    dsa_state.depth.writemask = true;

    ilo_blitter_set_invariants(blitter);
    ilo_blitter_set_op(blitter, ILO_BLITTER_RECTLIST_RESOLVE_HIZ);

    ilo_blitter_set_dsa(blitter, &dsa_state);
    ilo_blitter_set_fb_from_resource(blitter, res, res->format, level, slice);
    ilo_blitter_set_uses(blitter,
                         ILO_BLITTER_USE_DSA | ILO_BLITTER_USE_FB_DEPTH);

    hiz_emit_rectlist(blitter);
}
Пример #3
0
static void
ilo_resource_destroy(struct pipe_screen *screen,
                     struct pipe_resource *res)
{
   if (res->target == PIPE_BUFFER)
      buf_destroy(ilo_buffer(res));
   else
      tex_destroy(ilo_texture(res));
}
Пример #4
0
static boolean
ilo_resource_get_handle(struct pipe_screen *screen,
                        struct pipe_resource *res,
                        struct winsys_handle *handle)
{
   if (res->target == PIPE_BUFFER)
      return false;
   else
      return tex_get_handle(ilo_texture(res), handle);

}
Пример #5
0
static void
ilo_blitter_set_fb(struct ilo_blitter *blitter,
                   struct pipe_resource *res, unsigned level,
                   const struct ilo_surface_cso *cso)
{
    struct ilo_texture *tex = ilo_texture(res);

    blitter->fb.width = u_minify(tex->image.width0, level);
    blitter->fb.height = u_minify(tex->image.height0, level);

    blitter->fb.num_samples = res->nr_samples;
    if (!blitter->fb.num_samples)
        blitter->fb.num_samples = 1;

    memcpy(&blitter->fb.dst, cso, sizeof(*cso));
}
Пример #6
0
static struct pipe_sampler_view *
ilo_create_sampler_view(struct pipe_context *pipe,
                        struct pipe_resource *res,
                        const struct pipe_sampler_view *templ)
{
   const struct ilo_dev_info *dev = ilo_context(pipe)->dev;
   struct ilo_view_cso *view;

   view = MALLOC_STRUCT(ilo_view_cso);
   assert(view);

   view->base = *templ;
   pipe_reference_init(&view->base.reference, 1);
   view->base.texture = NULL;
   pipe_resource_reference(&view->base.texture, res);
   view->base.context = pipe;

   if (res->target == PIPE_BUFFER) {
      const unsigned elem_size = util_format_get_blocksize(templ->format);
      const unsigned first_elem = templ->u.buf.first_element;
      const unsigned num_elems = templ->u.buf.last_element - first_elem + 1;

      ilo_gpe_init_view_surface_for_buffer(dev, ilo_buffer(res),
            first_elem * elem_size, num_elems * elem_size,
            elem_size, templ->format, false, false, &view->surface);
   }
   else {
      struct ilo_texture *tex = ilo_texture(res);

      /* warn about degraded performance because of a missing binding flag */
      if (tex->layout.tiling == INTEL_TILING_NONE &&
          !(tex->base.bind & PIPE_BIND_SAMPLER_VIEW)) {
         ilo_warn("creating sampler view for a resource "
                  "not created for sampling\n");
      }

      ilo_gpe_init_view_surface_for_texture(dev, tex,
            templ->format,
            templ->u.tex.first_level,
            templ->u.tex.last_level - templ->u.tex.first_level + 1,
            templ->u.tex.first_layer,
            templ->u.tex.last_layer - templ->u.tex.first_layer + 1,
            false, &view->surface);
   }

   return &view->base;
}
Пример #7
0
static void
gen6_draw_wm_depth(struct ilo_render *r,
                   const struct ilo_state_vector *vec,
                   struct ilo_render_draw_session *session)
{
   /* 3DSTATE_DEPTH_BUFFER and 3DSTATE_CLEAR_PARAMS */
   if (DIRTY(FB) || r->batch_bo_changed) {
      const struct ilo_zs_surface *zs;
      uint32_t clear_params;

      if (vec->fb.state.zsbuf) {
         const struct ilo_surface_cso *surface =
            (const struct ilo_surface_cso *) vec->fb.state.zsbuf;
         const struct ilo_texture_slice *slice =
            ilo_texture_get_slice(ilo_texture(surface->base.texture),
                  surface->base.u.tex.level, surface->base.u.tex.first_layer);

         assert(!surface->is_rt);

         zs = &surface->u.zs;
         clear_params = slice->clear_value;
      }
      else {
         zs = &vec->fb.null_zs;
         clear_params = 0;
      }

      if (ilo_dev_gen(r->dev) == ILO_GEN(6)) {
         gen6_wa_pre_non_pipelined(r);
         gen6_wa_pre_depth(r);
      }

      gen6_3DSTATE_DEPTH_BUFFER(r->builder, zs, false);
      gen6_3DSTATE_HIER_DEPTH_BUFFER(r->builder, zs);
      gen6_3DSTATE_STENCIL_BUFFER(r->builder, zs);
      gen6_3DSTATE_CLEAR_PARAMS(r->builder, clear_params);
   }
}
Пример #8
0
static bool
tex_create_separate_stencil(struct ilo_texture *tex)
{
   struct pipe_resource templ = tex->base;
   struct pipe_resource *s8;

   /*
    * Unless PIPE_BIND_DEPTH_STENCIL is set, the resource may have other
    * tilings.  But that should be fine since it will never be bound as the
    * stencil buffer, and our transfer code can handle all tilings.
    */
   templ.format = PIPE_FORMAT_S8_UINT;

   s8 = tex->base.screen->resource_create(tex->base.screen, &templ);
   if (!s8)
      return false;

   tex->separate_s8 = ilo_texture(s8);

   assert(tex->separate_s8->layout.format == PIPE_FORMAT_S8_UINT);

   return true;
}
Пример #9
0
void
ilo_blitter_rectlist_resolve_z(struct ilo_blitter *blitter,
                               struct pipe_resource *res,
                               unsigned level, unsigned slice)
{
    struct ilo_texture *tex = ilo_texture(res);
    struct pipe_depth_stencil_alpha_state dsa_state;
    const struct ilo_texture_slice *s =
        ilo_texture_get_slice(tex, level, slice);

    if (!ilo_image_can_enable_aux(&tex->image, level))
        return;

    /*
     * From the Sandy Bridge PRM, volume 2 part 1, page 314:
     *
     *     "Depth Test Enable must be enabled with the Depth Test Function set
     *      to NEVER. Depth Buffer Write Enable must be enabled. Stencil Test
     *      Enable and Stencil Buffer Write Enable must be disabled."
     */
    memset(&dsa_state, 0, sizeof(dsa_state));
    dsa_state.depth.writemask = true;
    dsa_state.depth.enabled = true;
    dsa_state.depth.func = PIPE_FUNC_NEVER;

    ilo_blitter_set_invariants(blitter);
    ilo_blitter_set_op(blitter, ILO_BLITTER_RECTLIST_RESOLVE_Z);

    ilo_blitter_set_dsa(blitter, &dsa_state);
    ilo_blitter_set_clear_values(blitter, s->clear_value, 0);
    ilo_blitter_set_fb_from_resource(blitter, res, res->format, level, slice);
    ilo_blitter_set_uses(blitter,
                         ILO_BLITTER_USE_DSA | ILO_BLITTER_USE_FB_DEPTH);

    hiz_emit_rectlist(blitter);
}
Пример #10
0
static void
gen7_draw_wm(struct ilo_render *r,
             const struct ilo_state_vector *vec,
             struct ilo_render_draw_session *session)
{
   const union ilo_shader_cso *cso = ilo_shader_get_kernel_cso(vec->fs);
   const uint32_t kernel_offset = ilo_shader_get_kernel_offset(vec->fs);

   /* 3DSTATE_WM */
   if (DIRTY(FS) || (session->rs_delta.dirty & ILO_STATE_RASTER_3DSTATE_WM))
      gen7_3DSTATE_WM(r->builder, &vec->rasterizer->rs, &cso->ps);

   /* 3DSTATE_BINDING_TABLE_POINTERS_PS */
   if (session->binding_table_fs_changed) {
      gen7_3DSTATE_BINDING_TABLE_POINTERS_PS(r->builder,
            r->state.wm.BINDING_TABLE_STATE);
   }

   /* 3DSTATE_SAMPLER_STATE_POINTERS_PS */
   if (session->sampler_fs_changed) {
      gen7_3DSTATE_SAMPLER_STATE_POINTERS_PS(r->builder,
            r->state.wm.SAMPLER_STATE);
   }

   /* 3DSTATE_CONSTANT_PS */
   if (session->pcb_fs_changed) {
      gen7_3DSTATE_CONSTANT_PS(r->builder,
            &r->state.wm.PUSH_CONSTANT_BUFFER,
            &r->state.wm.PUSH_CONSTANT_BUFFER_size,
            1);
   }

   /* 3DSTATE_PS */
   if (DIRTY(FS) || r->instruction_bo_changed) {
      if (r->hw_ctx_changed)
         gen7_wa_pre_3dstate_ps_max_threads(r);

      gen7_3DSTATE_PS(r->builder, &cso->ps, kernel_offset);
   }

   /* 3DSTATE_SCISSOR_STATE_POINTERS */
   if (session->scissor_changed) {
      gen6_3DSTATE_SCISSOR_STATE_POINTERS(r->builder,
            r->state.SCISSOR_RECT);
   }

   {
      const bool emit_3dstate_ps = (DIRTY(FS) || DIRTY(BLEND));
      const bool emit_3dstate_depth_buffer =
         (DIRTY(FB) || DIRTY(DSA) || r->state_bo_changed);

      if (ilo_dev_gen(r->dev) == ILO_GEN(7)) {
         /* XXX what is the best way to know if this workaround is needed? */
         if (emit_3dstate_ps ||
             session->pcb_fs_changed ||
             session->viewport_changed ||
             session->binding_table_fs_changed ||
             session->sampler_fs_changed ||
             session->cc_changed ||
             session->blend_changed ||
             session->dsa_changed)
            gen7_wa_post_ps_and_later(r);
      }

      if (emit_3dstate_depth_buffer)
         gen7_wa_pre_depth(r);
   }

   /* 3DSTATE_DEPTH_BUFFER and 3DSTATE_CLEAR_PARAMS */
   if (DIRTY(FB) || r->batch_bo_changed) {
      const struct ilo_state_zs *zs;
      uint32_t clear_params;

      if (vec->fb.state.zsbuf) {
         const struct ilo_surface_cso *surface =
            (const struct ilo_surface_cso *) vec->fb.state.zsbuf;
         const struct ilo_texture_slice *slice =
            ilo_texture_get_slice(ilo_texture(surface->base.texture),
                  surface->base.u.tex.level, surface->base.u.tex.first_layer);

         assert(!surface->is_rt);
         zs = &surface->u.zs;
         clear_params = slice->clear_value;
      }
      else {
         zs = &vec->fb.null_zs;
         clear_params = 0;
      }

      gen6_3DSTATE_DEPTH_BUFFER(r->builder, zs);
      gen6_3DSTATE_HIER_DEPTH_BUFFER(r->builder, zs);
      gen6_3DSTATE_STENCIL_BUFFER(r->builder, zs);
      gen7_3DSTATE_CLEAR_PARAMS(r->builder, clear_params);
   }
}
Пример #11
0
void
ilo_blit_resolve_slices_for_hiz(struct ilo_context *ilo,
                                struct pipe_resource *res, unsigned level,
                                unsigned first_slice, unsigned num_slices,
                                unsigned resolve_flags)
{
   struct ilo_texture *tex = ilo_texture(res);
   const unsigned any_reader =
      ILO_TEXTURE_RENDER_READ |
      ILO_TEXTURE_BLT_READ |
      ILO_TEXTURE_CPU_READ;
   const unsigned other_writers =
      ILO_TEXTURE_BLT_WRITE |
      ILO_TEXTURE_CPU_WRITE;
   unsigned i;

   assert(tex->base.target != PIPE_BUFFER &&
          ilo_image_can_enable_aux(&tex->image, level));

   if (resolve_flags & ILO_TEXTURE_RENDER_WRITE) {
      /*
       * When ILO_TEXTURE_RENDER_WRITE is set, there can be no reader.  We
       * need to perform a HiZ Buffer Resolve in case the resource was
       * previously written by another writer, unless this is a clear.
       *
       * When slices have different clear values, we perform a Depth Buffer
       * Resolve on all slices not sharing the clear value of the first slice.
       * After resolving, those slices do not use 3DSTATE_CLEAR_PARAMS and can
       * be made to have the same clear value as the first slice does.  This
       * way,
       *
       *  - 3DSTATE_CLEAR_PARAMS can be set to the clear value of any slice
       *  - we will not resolve unnecessarily next time this function is
       *    called
       *
       * Since slice clear value is the value the slice is cleared to when
       * ILO_TEXTURE_CLEAR is set, the bit needs to be unset.
       */
      assert(!(resolve_flags & (other_writers | any_reader)));

      if (!(resolve_flags & ILO_TEXTURE_CLEAR)) {
         const uint32_t first_clear_value = ilo_texture_get_slice(tex,
               level, first_slice)->clear_value;
         bool set_clear_value = false;

         for (i = 0; i < num_slices; i++) {
            const struct ilo_texture_slice *slice =
               ilo_texture_get_slice(tex, level, first_slice + i);

            if (slice->flags & other_writers) {
               ilo_blitter_rectlist_resolve_hiz(ilo->blitter,
                     res, level, first_slice + i);
            } else if (slice->clear_value != first_clear_value &&
                       (slice->flags & ILO_TEXTURE_RENDER_WRITE)) {
               ilo_blitter_rectlist_resolve_z(ilo->blitter,
                     res, level, first_slice + i);
               set_clear_value = true;
            }
         }

         if (set_clear_value) {
            /* ILO_TEXTURE_CLEAR will be cleared later */
            ilo_texture_set_slice_clear_value(tex, level,
                  first_slice, num_slices, first_clear_value);
         }
      }
   }
   else if ((resolve_flags & any_reader) ||
            ((resolve_flags & other_writers) &&
             !(resolve_flags & ILO_TEXTURE_CLEAR))) {
      /*
       * When there is at least a reader or writer, we need to perform a
       * Depth Buffer Resolve in case the resource was previously written
       * by ILO_TEXTURE_RENDER_WRITE.
       */
      for (i = 0; i < num_slices; i++) {
         const struct ilo_texture_slice *slice =
            ilo_texture_get_slice(tex, level, first_slice + i);

         if (slice->flags & ILO_TEXTURE_RENDER_WRITE) {
            ilo_blitter_rectlist_resolve_z(ilo->blitter,
                  &tex->base, level, first_slice + i);
         }
      }
   }
}
Пример #12
0
static void
gen8_draw_wm(struct ilo_render *r,
             const struct ilo_state_vector *vec,
             struct ilo_render_draw_session *session)
{
   const union ilo_shader_cso *cso = ilo_shader_get_kernel_cso(vec->fs);
   const uint32_t kernel_offset = ilo_shader_get_kernel_offset(vec->fs);

   /* 3DSTATE_WM */
   if (session->rs_delta.dirty & ILO_STATE_RASTER_3DSTATE_WM)
      gen8_3DSTATE_WM(r->builder, &vec->rasterizer->rs);

   if (session->cc_delta.dirty & ILO_STATE_CC_3DSTATE_WM_DEPTH_STENCIL)
      gen8_3DSTATE_WM_DEPTH_STENCIL(r->builder, &vec->blend->cc);

   /* 3DSTATE_WM_HZ_OP and 3DSTATE_WM_CHROMAKEY */
   if (r->hw_ctx_changed) {
      gen8_disable_3DSTATE_WM_HZ_OP(r->builder);
      gen8_3DSTATE_WM_CHROMAKEY(r->builder);
   }

   /* 3DSTATE_BINDING_TABLE_POINTERS_PS */
   if (session->binding_table_fs_changed) {
      gen7_3DSTATE_BINDING_TABLE_POINTERS_PS(r->builder,
            r->state.wm.BINDING_TABLE_STATE);
   }

   /* 3DSTATE_SAMPLER_STATE_POINTERS_PS */
   if (session->sampler_fs_changed) {
      gen7_3DSTATE_SAMPLER_STATE_POINTERS_PS(r->builder,
            r->state.wm.SAMPLER_STATE);
   }

   /* 3DSTATE_CONSTANT_PS */
   if (session->pcb_fs_changed) {
      gen7_3DSTATE_CONSTANT_PS(r->builder,
            &r->state.wm.PUSH_CONSTANT_BUFFER,
            &r->state.wm.PUSH_CONSTANT_BUFFER_size,
            1);
   }

   /* 3DSTATE_PS */
   if (DIRTY(FS) || r->instruction_bo_changed)
      gen8_3DSTATE_PS(r->builder, &cso->ps, kernel_offset);

   /* 3DSTATE_PS_EXTRA */
   if (DIRTY(FS))
      gen8_3DSTATE_PS_EXTRA(r->builder, &cso->ps);

   /* 3DSTATE_PS_BLEND */
   if (session->cc_delta.dirty & ILO_STATE_CC_3DSTATE_PS_BLEND)
      gen8_3DSTATE_PS_BLEND(r->builder, &vec->blend->cc);

   /* 3DSTATE_SCISSOR_STATE_POINTERS */
   if (session->scissor_changed) {
      gen6_3DSTATE_SCISSOR_STATE_POINTERS(r->builder,
            r->state.SCISSOR_RECT);
   }

   /* 3DSTATE_DEPTH_BUFFER and 3DSTATE_CLEAR_PARAMS */
   if (DIRTY(FB) || r->batch_bo_changed) {
      const struct ilo_state_zs *zs;
      uint32_t clear_params;

      if (vec->fb.state.zsbuf) {
         const struct ilo_surface_cso *surface =
            (const struct ilo_surface_cso *) vec->fb.state.zsbuf;
         const struct ilo_texture_slice *slice =
            ilo_texture_get_slice(ilo_texture(surface->base.texture),
                  surface->base.u.tex.level, surface->base.u.tex.first_layer);

         assert(!surface->is_rt);
         zs = &surface->u.zs;
         clear_params = slice->clear_value;
      }
      else {
         zs = &vec->fb.null_zs;
         clear_params = 0;
      }

      gen8_wa_pre_depth(r);

      gen6_3DSTATE_DEPTH_BUFFER(r->builder, zs);
      gen6_3DSTATE_HIER_DEPTH_BUFFER(r->builder, zs);
      gen6_3DSTATE_STENCIL_BUFFER(r->builder, zs);
      gen7_3DSTATE_CLEAR_PARAMS(r->builder, clear_params);
   }
}
static void
gen8_draw_wm(struct ilo_render *r,
             const struct ilo_state_vector *vec,
             struct ilo_render_draw_session *session)
{
   /* 3DSTATE_WM */
   if (DIRTY(FS) || DIRTY(RASTERIZER))
      gen8_3DSTATE_WM(r->builder, vec->fs, vec->rasterizer);

   if (DIRTY(DSA))
      gen8_3DSTATE_WM_DEPTH_STENCIL(r->builder, vec->dsa);

   /* 3DSTATE_WM_HZ_OP and 3DSTATE_WM_CHROMAKEY */
   if (r->hw_ctx_changed) {
      gen8_disable_3DSTATE_WM_HZ_OP(r->builder);
      gen8_3DSTATE_WM_CHROMAKEY(r->builder);
   }

   /* 3DSTATE_BINDING_TABLE_POINTERS_PS */
   if (session->binding_table_fs_changed) {
      gen7_3DSTATE_BINDING_TABLE_POINTERS_PS(r->builder,
            r->state.wm.BINDING_TABLE_STATE);
   }

   /* 3DSTATE_SAMPLER_STATE_POINTERS_PS */
   if (session->sampler_fs_changed) {
      gen7_3DSTATE_SAMPLER_STATE_POINTERS_PS(r->builder,
            r->state.wm.SAMPLER_STATE);
   }

   /* 3DSTATE_CONSTANT_PS */
   if (session->pcb_fs_changed) {
      gen7_3DSTATE_CONSTANT_PS(r->builder,
            &r->state.wm.PUSH_CONSTANT_BUFFER,
            &r->state.wm.PUSH_CONSTANT_BUFFER_size,
            1);
   }

   /* 3DSTATE_PS */
   if (DIRTY(FS) || r->instruction_bo_changed)
      gen8_3DSTATE_PS(r->builder, vec->fs);

   /* 3DSTATE_PS_EXTRA */
   if (DIRTY(FS) || DIRTY(DSA) || DIRTY(BLEND)) {
      const bool cc_may_kill = (vec->dsa->dw_blend_alpha ||
                                vec->blend->alpha_to_coverage);
      gen8_3DSTATE_PS_EXTRA(r->builder, vec->fs, cc_may_kill, false);
   }

   /* 3DSTATE_PS_BLEND */
   if (DIRTY(BLEND) || DIRTY(FB) || DIRTY(DSA))
      gen8_3DSTATE_PS_BLEND(r->builder, vec->blend, &vec->fb, vec->dsa);

   /* 3DSTATE_SCISSOR_STATE_POINTERS */
   if (session->scissor_changed) {
      gen6_3DSTATE_SCISSOR_STATE_POINTERS(r->builder,
            r->state.SCISSOR_RECT);
   }

   /* 3DSTATE_DEPTH_BUFFER and 3DSTATE_CLEAR_PARAMS */
   if (DIRTY(FB) || r->batch_bo_changed) {
      const struct ilo_zs_surface *zs;
      uint32_t clear_params;

      if (vec->fb.state.zsbuf) {
         const struct ilo_surface_cso *surface =
            (const struct ilo_surface_cso *) vec->fb.state.zsbuf;
         const struct ilo_texture_slice *slice =
            ilo_texture_get_slice(ilo_texture(surface->base.texture),
                  surface->base.u.tex.level, surface->base.u.tex.first_layer);

         assert(!surface->is_rt);
         zs = &surface->u.zs;
         clear_params = slice->clear_value;
      }
      else {
         zs = &vec->fb.null_zs;
         clear_params = 0;
      }

      gen8_wa_pre_depth(r);

      gen6_3DSTATE_DEPTH_BUFFER(r->builder, zs, false);
      gen6_3DSTATE_HIER_DEPTH_BUFFER(r->builder, zs);
      gen6_3DSTATE_STENCIL_BUFFER(r->builder, zs);
      gen7_3DSTATE_CLEAR_PARAMS(r->builder, clear_params);
   }
}
Пример #14
0
bool
ilo_blitter_rectlist_clear_zs(struct ilo_blitter *blitter,
                              struct pipe_surface *zs,
                              unsigned clear_flags,
                              double depth, unsigned stencil)
{
    struct ilo_texture *tex = ilo_texture(zs->texture);
    struct pipe_depth_stencil_alpha_state dsa_state;
    uint32_t uses, clear_value;

    if (!ilo_image_can_enable_aux(&tex->image, zs->u.tex.level))
        return false;

    if (!hiz_can_clear_zs(blitter, tex))
        return false;

    if (ilo_dev_gen(blitter->ilo->dev) >= ILO_GEN(8))
        clear_value = fui(depth);
    else
        clear_value = util_pack_z(tex->image.format, depth);

    ilo_blit_resolve_surface(blitter->ilo, zs,
                             ILO_TEXTURE_RENDER_WRITE | ILO_TEXTURE_CLEAR);
    ilo_texture_set_slice_clear_value(tex, zs->u.tex.level,
                                      zs->u.tex.first_layer,
                                      zs->u.tex.last_layer - zs->u.tex.first_layer + 1,
                                      clear_value);

    /*
     * From the Sandy Bridge PRM, volume 2 part 1, page 313-314:
     *
     *     "- Depth Test Enable must be disabled and Depth Buffer Write Enable
     *        must be enabled (if depth is being cleared).
     *
     *      - Stencil buffer clear can be performed at the same time by
     *        enabling Stencil Buffer Write Enable.  Stencil Test Enable must
     *        be enabled and Stencil Pass Depth Pass Op set to REPLACE, and the
     *        clear value that is placed in the stencil buffer is the Stencil
     *        Reference Value from COLOR_CALC_STATE.
     *
     *      - Note also that stencil buffer clear can be performed without
     *        depth buffer clear. For stencil only clear, Depth Test Enable and
     *        Depth Buffer Write Enable must be disabled.
     *
     *      - [DevSNB] errata: For stencil buffer only clear, the previous
     *        depth clear value must be delivered during the clear."
     */
    memset(&dsa_state, 0, sizeof(dsa_state));

    if (clear_flags & PIPE_CLEAR_DEPTH)
        dsa_state.depth.writemask = true;

    if (clear_flags & PIPE_CLEAR_STENCIL) {
        dsa_state.stencil[0].enabled = true;
        dsa_state.stencil[0].func = PIPE_FUNC_ALWAYS;
        dsa_state.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
        dsa_state.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
        dsa_state.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;

        /*
         * From the Ivy Bridge PRM, volume 2 part 1, page 277:
         *
         *     "Additionally the following must be set to the correct values.
         *
         *      - DEPTH_STENCIL_STATE::Stencil Write Mask must be 0xFF
         *      - DEPTH_STENCIL_STATE::Stencil Test Mask must be 0xFF
         *      - DEPTH_STENCIL_STATE::Back Face Stencil Write Mask must be 0xFF
         *      - DEPTH_STENCIL_STATE::Back Face Stencil Test Mask must be 0xFF"
         */
        dsa_state.stencil[0].valuemask = 0xff;
        dsa_state.stencil[0].writemask = 0xff;
        dsa_state.stencil[1].valuemask = 0xff;
        dsa_state.stencil[1].writemask = 0xff;
    }

    ilo_blitter_set_invariants(blitter);
    ilo_blitter_set_op(blitter, ILO_BLITTER_RECTLIST_CLEAR_ZS);

    ilo_blitter_set_dsa(blitter, &dsa_state);
    ilo_blitter_set_clear_values(blitter, clear_value, (ubyte) stencil);
    ilo_blitter_set_fb_from_surface(blitter, zs);

    uses = ILO_BLITTER_USE_DSA;
    if (clear_flags & PIPE_CLEAR_DEPTH)
        uses |= ILO_BLITTER_USE_VIEWPORT | ILO_BLITTER_USE_FB_DEPTH;
    if (clear_flags & PIPE_CLEAR_STENCIL)
        uses |= ILO_BLITTER_USE_CC | ILO_BLITTER_USE_FB_STENCIL;
    ilo_blitter_set_uses(blitter, uses);

    hiz_emit_rectlist(blitter);

    return true;
}