示例#1
0
static void
copy_miptrees(struct brw_context *brw,
              struct intel_mipmap_tree *src_mt,
              int src_x, int src_y, int src_z, unsigned src_level,
              struct intel_mipmap_tree *dst_mt,
              int dst_x, int dst_y, int dst_z, unsigned dst_level,
              int src_width, int src_height)
{
   unsigned bw, bh;

   if (brw->gen >= 6) {
      brw_blorp_copy_miptrees(brw,
                              src_mt, src_level, src_z,
                              dst_mt, dst_level, dst_z,
                              src_x, src_y, dst_x, dst_y,
                              src_width, src_height);
      return;
   }

   /* We are now going to try and copy the texture using the blitter.  If
    * that fails, we will fall back mapping the texture and using memcpy.
    * In either case, we need to do a full resolve.
    */
   intel_miptree_all_slices_resolve_hiz(brw, src_mt);
   intel_miptree_all_slices_resolve_depth(brw, src_mt);
   intel_miptree_resolve_color(brw, src_mt, 0);

   intel_miptree_all_slices_resolve_hiz(brw, dst_mt);
   intel_miptree_all_slices_resolve_depth(brw, dst_mt);
   intel_miptree_resolve_color(brw, dst_mt, 0);

   _mesa_get_format_block_size(src_mt->format, &bw, &bh);

   /* It's legal to have a WxH that's smaller than a compressed block. This
    * happens for example when you are using a higher level LOD. For this case,
    * we still want to copy the entire block, or else the decompression will be
    * incorrect.
    */
   if (src_width < bw)
      src_width = ALIGN_NPOT(src_width, bw);

   if (src_height < bh)
      src_height = ALIGN_NPOT(src_height, bh);

   if (copy_image_with_blitter(brw, src_mt, src_level,
                               src_x, src_y, src_z,
                               dst_mt, dst_level,
                               dst_x, dst_y, dst_z,
                               src_width, src_height))
      return;

   /* This is a worst-case scenario software fallback that maps the two
    * textures and does a memcpy between them.
    */
   copy_image_with_memcpy(brw, src_mt, src_level,
                          src_x, src_y, src_z,
                          dst_mt, dst_level,
                          dst_x, dst_y, dst_z,
                          src_width, src_height);
}
/*
 * \brief Resolve buffers before drawing.
 *
 * Resolve the depth buffer's HiZ buffer and resolve the depth buffer of each
 * enabled depth texture.
 *
 * (In the future, this will also perform MSAA resolves).
 */
static void
brw_predraw_resolve_buffers(struct brw_context *brw)
{
   struct gl_context *ctx = &brw->ctx;
   struct intel_renderbuffer *depth_irb;
   struct intel_texture_object *tex_obj;

   /* Resolve the depth buffer's HiZ buffer. */
   depth_irb = intel_get_renderbuffer(ctx->DrawBuffer, BUFFER_DEPTH);
   if (depth_irb)
      intel_renderbuffer_resolve_hiz(brw, depth_irb);

   /* Resolve depth buffer of each enabled depth texture, and color buffer of
    * each fast-clear-enabled color texture.
    */
   for (int i = 0; i < BRW_MAX_TEX_UNIT; i++) {
      if (!ctx->Texture.Unit[i]._ReallyEnabled)
	 continue;
      tex_obj = intel_texture_object(ctx->Texture.Unit[i]._Current);
      if (!tex_obj || !tex_obj->mt)
	 continue;
      intel_miptree_all_slices_resolve_depth(brw, tex_obj->mt);
      intel_miptree_resolve_color(brw, tex_obj->mt);
   }
}
示例#3
0
/**
 * \brief Prepare for entry into glBegin/glEnd block.
 *
 * Resolve buffers before entering a glBegin/glEnd block. This is
 * necessary to prevent recursive calls to FLUSH_VERTICES.
 *
 * This resolves the depth buffer of each enabled depth texture and the HiZ
 * buffer of the attached depth renderbuffer.
 *
 * Details
 * -------
 * When vertices are queued during a glBegin/glEnd block, those vertices must
 * be drawn before any rendering state changes. To ensure this, Mesa calls
 * FLUSH_VERTICES as a prehook to such state changes. Therefore,
 * FLUSH_VERTICES itself cannot change rendering state without falling into a
 * recursive trap.
 *
 * This precludes meta-ops, namely buffer resolves, from occurring while any
 * vertices are queued. To prevent that situation, we resolve some buffers on
 * entering a glBegin/glEnd
 *
 * \see brwCleanupExecEnd()
 */
static void brwPrepareExecBegin(struct gl_context *ctx)
{
   struct brw_context *brw = brw_context(ctx);
   struct intel_context *intel = &brw->intel;
   struct intel_renderbuffer *draw_irb;
   struct intel_texture_object *tex_obj;

   if (!intel->has_hiz) {
      /* The context uses no feature that requires buffer resolves. */
      return;
   }

   /* Resolve each enabled texture. */
   for (int i = 0; i < ctx->Const.MaxTextureImageUnits; i++) {
      if (!ctx->Texture.Unit[i]._ReallyEnabled)
	 continue;
      tex_obj = intel_texture_object(ctx->Texture.Unit[i]._Current);
      if (!tex_obj || !tex_obj->mt)
	 continue;
      intel_miptree_all_slices_resolve_depth(intel, tex_obj->mt);
   }

   /* Resolve the attached depth buffer. */
   draw_irb = intel_get_renderbuffer(ctx->DrawBuffer, BUFFER_DEPTH);
   if (draw_irb) {
      intel_renderbuffer_resolve_hiz(intel, draw_irb);
   }
}
示例#4
0
文件: brw_clear.c 项目: CSRedRat/mesa
/**
 * Implements fast depth clears on gen6+.
 *
 * Fast clears basically work by setting a flag in each of the subspans
 * represented in the HiZ buffer that says "When you need the depth values for
 * this subspan, it's the hardware's current clear value."  Then later rendering
 * can just use the static clear value instead of referencing memory.
 *
 * The tricky part of the implementation is that you have to have the clear
 * value that was used on the depth buffer in place for all further rendering,
 * at least until a resolve to the real depth buffer happens.
 */
static bool
brw_fast_clear_depth(struct gl_context *ctx)
{
   struct intel_context *intel = intel_context(ctx);
   struct gl_framebuffer *fb = ctx->DrawBuffer;
   struct intel_renderbuffer *depth_irb =
      intel_get_renderbuffer(fb, BUFFER_DEPTH);
   struct intel_mipmap_tree *mt = depth_irb->mt;

   if (intel->gen < 6)
      return false;

   if (!mt->hiz_mt)
      return false;

   /* We only handle full buffer clears -- otherwise you'd have to track whether
    * a previous clear had happened at a different clear value and resolve it
    * first.
    */
   if (ctx->Scissor.Enabled && !noop_scissor(ctx, fb)) {
      perf_debug("Failed to fast clear depth due to scissor being enabled.  "
                 "Possible 5%% performance win if avoided.\n");
      return false;
   }

   /* The rendered area has to be 8x4 samples, not resolved pixels, so we look
    * at the miptree slice dimensions instead of renderbuffer size.
    */
   if (mt->level[depth_irb->mt_level].width % 8 != 0 ||
       mt->level[depth_irb->mt_level].height % 4 != 0) {
      perf_debug("Failed to fast clear depth due to width/height %d,%d not "
                 "being aligned to 8,4.  Possible 5%% performance win if "
                 "avoided\n",
                 mt->level[depth_irb->mt_level].width,
                 mt->level[depth_irb->mt_level].height);
      return false;
   }

   uint32_t depth_clear_value;
   switch (mt->format) {
   case MESA_FORMAT_Z32_FLOAT_X24S8:
   case MESA_FORMAT_S8_Z24:
      /* From the Sandy Bridge PRM, volume 2 part 1, page 314:
       *
       *     "[DevSNB+]: Several cases exist where Depth Buffer Clear cannot be
       *      enabled (the legacy method of clearing must be performed):
       *
       *      - If the depth buffer format is D32_FLOAT_S8X24_UINT or
       *        D24_UNORM_S8_UINT.
       */
      return false;

   case MESA_FORMAT_Z32_FLOAT:
      depth_clear_value = float_as_int(ctx->Depth.Clear);
      break;

   case MESA_FORMAT_Z16:
      /* From the Sandy Bridge PRM, volume 2 part 1, page 314:
       *
       *     "[DevSNB+]: Several cases exist where Depth Buffer Clear cannot be
       *      enabled (the legacy method of clearing must be performed):
       *
       *      - DevSNB{W/A}]: When depth buffer format is D16_UNORM and the
       *        width of the map (LOD0) is not multiple of 16, fast clear
       *        optimization must be disabled.
       */
      if (intel->gen == 6 && (mt->level[depth_irb->mt_level].width % 16) != 0)
	 return false;
      /* FALLTHROUGH */

   default:
      depth_clear_value = fb->_DepthMax * ctx->Depth.Clear;
      break;
   }

   /* If we're clearing to a new clear value, then we need to resolve any clear
    * flags out of the HiZ buffer into the real depth buffer.
    */
   if (mt->depth_clear_value != depth_clear_value) {
      intel_miptree_all_slices_resolve_depth(intel, mt);
      mt->depth_clear_value = depth_clear_value;
   }

   /* From the Sandy Bridge PRM, volume 2 part 1, page 313:
    *
    *     "If other rendering operations have preceded this clear, a
    *      PIPE_CONTROL with write cache flush enabled and Z-inhibit disabled
    *      must be issued before the rectangle primitive used for the depth
    *      buffer clear operation.
    */
   intel_batchbuffer_emit_mi_flush(intel);

   intel_hiz_exec(intel, mt, depth_irb->mt_level, depth_irb->mt_layer,
		  GEN6_HIZ_OP_DEPTH_CLEAR);

   if (intel->gen == 6) {
      /* From the Sandy Bridge PRM, volume 2 part 1, page 314:
       *
       *     "DevSNB, DevSNB-B{W/A}]: Depth buffer clear pass must be followed
       *      by a PIPE_CONTROL command with DEPTH_STALL bit set and Then
       *      followed by Depth FLUSH'
      */
      intel_batchbuffer_emit_mi_flush(intel);
   }

   /* Now, the HiZ buffer contains data that needs to be resolved to the depth
    * buffer.
    */
   intel_renderbuffer_set_needs_depth_resolve(depth_irb);

   return true;
}
示例#5
0
static void
intel_copy_image_sub_data(struct gl_context *ctx,
                          struct gl_texture_image *src_image,
                          int src_x, int src_y, int src_z,
                          struct gl_texture_image *dst_image,
                          int dst_x, int dst_y, int dst_z,
                          int src_width, int src_height)
{
   struct brw_context *brw = brw_context(ctx);
   struct intel_texture_image *intel_src_image = intel_texture_image(src_image);
   struct intel_texture_image *intel_dst_image = intel_texture_image(dst_image);

   if (_mesa_meta_CopyImageSubData_uncompressed(ctx,
                                                src_image, src_x, src_y, src_z,
                                                dst_image, dst_x, dst_y, dst_z,
                                                src_width, src_height)) {
      return;
   }

   if (intel_src_image->mt->num_samples > 0 ||
       intel_dst_image->mt->num_samples > 0) {
      _mesa_problem(ctx, "Failed to copy multisampled texture with meta path\n");
      return;
   }

   /* Cube maps actually have different images per face */
   if (src_image->TexObject->Target == GL_TEXTURE_CUBE_MAP)
      src_z = src_image->Face;
   if (dst_image->TexObject->Target == GL_TEXTURE_CUBE_MAP)
      dst_z = dst_image->Face;

   /* We are now going to try and copy the texture using the blitter.  If
    * that fails, we will fall back mapping the texture and using memcpy.
    * In either case, we need to do a full resolve.
    */
   intel_miptree_all_slices_resolve_hiz(brw, intel_src_image->mt);
   intel_miptree_all_slices_resolve_depth(brw, intel_src_image->mt);
   intel_miptree_resolve_color(brw, intel_src_image->mt);

   intel_miptree_all_slices_resolve_hiz(brw, intel_dst_image->mt);
   intel_miptree_all_slices_resolve_depth(brw, intel_dst_image->mt);
   intel_miptree_resolve_color(brw, intel_dst_image->mt);

   unsigned src_level = src_image->Level + src_image->TexObject->MinLevel;
   unsigned dst_level = dst_image->Level + dst_image->TexObject->MinLevel;
   if (copy_image_with_blitter(brw, intel_src_image->mt, src_level,
                               src_x, src_y, src_z,
                               intel_dst_image->mt, dst_level,
                               dst_x, dst_y, dst_z,
                               src_width, src_height))
      return;

   /* This is a worst-case scenario software fallback that maps the two
    * textures and does a memcpy between them.
    */
   copy_image_with_memcpy(brw, intel_src_image->mt, src_level,
                          src_x, src_y, src_z,
                          intel_dst_image->mt, dst_level,
                          dst_x, dst_y, dst_z,
                          src_width, src_height);
}
示例#6
0
文件: brw_clear.c 项目: Unr34ler/mesa
/**
 * Implements fast depth clears on gen6+.
 *
 * Fast clears basically work by setting a flag in each of the subspans
 * represented in the HiZ buffer that says "When you need the depth values for
 * this subspan, it's the hardware's current clear value."  Then later rendering
 * can just use the static clear value instead of referencing memory.
 *
 * The tricky part of the implementation is that you have to have the clear
 * value that was used on the depth buffer in place for all further rendering,
 * at least until a resolve to the real depth buffer happens.
 */
static bool
brw_fast_clear_depth(struct gl_context *ctx)
{
   struct brw_context *brw = brw_context(ctx);
   struct gl_framebuffer *fb = ctx->DrawBuffer;
   struct intel_renderbuffer *depth_irb =
      intel_get_renderbuffer(fb, BUFFER_DEPTH);
   struct intel_mipmap_tree *mt = depth_irb->mt;
   struct gl_renderbuffer_attachment *depth_att = &fb->Attachment[BUFFER_DEPTH];

   if (brw->gen < 6)
      return false;

   if (!intel_renderbuffer_has_hiz(depth_irb))
      return false;

   /* We only handle full buffer clears -- otherwise you'd have to track whether
    * a previous clear had happened at a different clear value and resolve it
    * first.
    */
   if ((ctx->Scissor.EnableFlags & 1) && !noop_scissor(ctx, fb)) {
      perf_debug("Failed to fast clear %dx%d depth because of scissors.  "
                 "Possible 5%% performance win if avoided.\n",
                 mt->logical_width0, mt->logical_height0);
      return false;
   }

   uint32_t depth_clear_value;
   switch (mt->format) {
   case MESA_FORMAT_Z32_FLOAT_S8X24_UINT:
   case MESA_FORMAT_Z24_UNORM_S8_UINT:
      /* From the Sandy Bridge PRM, volume 2 part 1, page 314:
       *
       *     "[DevSNB+]: Several cases exist where Depth Buffer Clear cannot be
       *      enabled (the legacy method of clearing must be performed):
       *
       *      - If the depth buffer format is D32_FLOAT_S8X24_UINT or
       *        D24_UNORM_S8_UINT.
       */
      return false;

   case MESA_FORMAT_Z_FLOAT32:
      depth_clear_value = float_as_int(ctx->Depth.Clear);
      break;

   case MESA_FORMAT_Z_UNORM16:
      /* From the Sandy Bridge PRM, volume 2 part 1, page 314:
       *
       *     "[DevSNB+]: Several cases exist where Depth Buffer Clear cannot be
       *      enabled (the legacy method of clearing must be performed):
       *
       *      - DevSNB{W/A}]: When depth buffer format is D16_UNORM and the
       *        width of the map (LOD0) is not multiple of 16, fast clear
       *        optimization must be disabled.
       */
      if (brw->gen == 6 &&
          (minify(mt->physical_width0,
                  depth_irb->mt_level - mt->first_level) % 16) != 0)
	 return false;
      /* FALLTHROUGH */

   default:
      if (brw->gen >= 8)
         depth_clear_value = float_as_int(ctx->Depth.Clear);
      else
         depth_clear_value = fb->_DepthMax * ctx->Depth.Clear;
      break;
   }

   /* If we're clearing to a new clear value, then we need to resolve any clear
    * flags out of the HiZ buffer into the real depth buffer.
    */
   if (mt->depth_clear_value != depth_clear_value) {
      intel_miptree_all_slices_resolve_depth(brw, mt);
      mt->depth_clear_value = depth_clear_value;
   }

   /* From the Sandy Bridge PRM, volume 2 part 1, page 313:
    *
    *     "If other rendering operations have preceded this clear, a
    *      PIPE_CONTROL with write cache flush enabled and Z-inhibit disabled
    *      must be issued before the rectangle primitive used for the depth
    *      buffer clear operation.
    */
   brw_emit_mi_flush(brw);

   if (fb->MaxNumLayers > 0) {
      for (unsigned layer = 0; layer < depth_irb->layer_count; layer++) {
         intel_hiz_exec(brw, mt, depth_irb->mt_level,
                        depth_irb->mt_layer + layer,
                        GEN6_HIZ_OP_DEPTH_CLEAR);
      }
   } else {
      intel_hiz_exec(brw, mt, depth_irb->mt_level, depth_irb->mt_layer,
                     GEN6_HIZ_OP_DEPTH_CLEAR);
   }

   if (brw->gen == 6) {
      /* From the Sandy Bridge PRM, volume 2 part 1, page 314:
       *
       *     "DevSNB, DevSNB-B{W/A}]: Depth buffer clear pass must be followed
       *      by a PIPE_CONTROL command with DEPTH_STALL bit set and Then
       *      followed by Depth FLUSH'
      */
      brw_emit_mi_flush(brw);
   }

   /* Now, the HiZ buffer contains data that needs to be resolved to the depth
    * buffer.
    */
   intel_renderbuffer_att_set_needs_depth_resolve(depth_att);

   return true;
}