[Mesa-dev] [PATCH 19/22] i965: Add a userptr path for TexImage

Chris Wilson chris at chris-wilson.co.uk
Sat Aug 5 09:40:11 UTC 2017


Uncommonly we may be able to blit into the texture where we cannot
perform the tiled memcpy fast path, for example on older generations and
non-LLC architectures (though those restrictions may be lifted in
future). Using the GPU blit, even with a linear source and forced stall,
is still much faster than the mesa fallback paths, make it so.

Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
---
 src/mesa/drivers/dri/i965/intel_tex.h          |   6 +
 src/mesa/drivers/dri/i965/intel_tex_image.c    |  36 +++--
 src/mesa/drivers/dri/i965/intel_tex_subimage.c | 197 +++++++++++++++++++++++--
 3 files changed, 204 insertions(+), 35 deletions(-)

diff --git a/src/mesa/drivers/dri/i965/intel_tex.h b/src/mesa/drivers/dri/i965/intel_tex.h
index 376f075c9e..5e2f9297eb 100644
--- a/src/mesa/drivers/dri/i965/intel_tex.h
+++ b/src/mesa/drivers/dri/i965/intel_tex.h
@@ -63,6 +63,12 @@ intel_texsubimage_tiled_memcpy(struct gl_context *ctx,
                                const GLvoid *pixels,
                                const struct gl_pixelstore_attrib *packing,
                                bool for_glTexImage);
+bool
+intel_texsubimage_pbo(struct gl_context *ctx, GLuint dims,
+                      struct gl_texture_image *texImage,
+                      GLint x, GLint y, GLint z,
+                      GLsizei width, GLsizei height, GLsizei depth,
+                      GLenum format, GLenum type, const GLvoid *pixels);
 
 bool
 intel_gettexsubimage_tiled_memcpy(struct gl_context *ctx,
diff --git a/src/mesa/drivers/dri/i965/intel_tex_image.c b/src/mesa/drivers/dri/i965/intel_tex_image.c
index 334e323d74..7cd8a9b66a 100644
--- a/src/mesa/drivers/dri/i965/intel_tex_image.c
+++ b/src/mesa/drivers/dri/i965/intel_tex_image.c
@@ -137,9 +137,6 @@ intelTexImage(struct gl_context * ctx,
               const struct gl_pixelstore_attrib *unpack)
 {
    struct intel_texture_image *intelImage = intel_texture_image(texImage);
-   bool ok;
-
-   bool tex_busy = intelImage->mt && brw_bo_busy(intelImage->mt->bo);
 
    DBG("%s mesa_format %s target %s format %s type %s level %d %dx%dx%d\n",
        __func__, _mesa_get_format_name(texImage->TexFormat),
@@ -158,22 +155,23 @@ intelTexImage(struct gl_context * ctx,
    if (intelImage->mt->format == MESA_FORMAT_S_UINT8)
       intelImage->mt->r8stencil_needs_update = true;
 
-   ok = _mesa_meta_pbo_TexSubImage(ctx, dims, texImage, 0, 0, 0,
-                                   texImage->Width, texImage->Height,
-                                   texImage->Depth,
-                                   format, type, pixels,
-                                   tex_busy, unpack);
-   if (ok)
-      return;
+   if (!_mesa_is_bufferobj(unpack->BufferObj)) {
+      if (intel_texsubimage_tiled_memcpy(ctx, dims, texImage,
+                                         0, 0, 0, /*x,y,z offsets*/
+                                         texImage->Width,
+                                         texImage->Height,
+                                         texImage->Depth,
+                                         format, type, pixels, unpack,
+                                         false /*allocate_storage*/))
+         return;
+   }
 
-   ok = intel_texsubimage_tiled_memcpy(ctx, dims, texImage,
-                                       0, 0, 0, /*x,y,z offsets*/
-                                       texImage->Width,
-                                       texImage->Height,
-                                       texImage->Depth,
-                                       format, type, pixels, unpack,
-                                       false /*allocate_storage*/);
-   if (ok)
+   if (intel_texsubimage_pbo(ctx, dims, texImage,
+                             0, 0, 0, /*x,y,z offsets*/
+                             texImage->Width,
+                             texImage->Height,
+                             texImage->Depth,
+                             format, type, pixels))
       return;
 
    DBG("%s: upload image %dx%dx%d pixels %p\n",
@@ -735,7 +733,7 @@ intel_gettexsubimage_pbo(struct gl_context *ctx,
                                           intel_buffer_object(pack->BufferObj),
                                           dst_offset,
                                           dst_size,
-                                          false);
+                                          true);
    } else {
       dst_offset = (GLintptr)pixels & 4095;
       if ((dst_offset | dst_stride) % bpp)
diff --git a/src/mesa/drivers/dri/i965/intel_tex_subimage.c b/src/mesa/drivers/dri/i965/intel_tex_subimage.c
index e7486300ab..77db18242c 100644
--- a/src/mesa/drivers/dri/i965/intel_tex_subimage.c
+++ b/src/mesa/drivers/dri/i965/intel_tex_subimage.c
@@ -25,21 +25,25 @@
 
 #include "main/bufferobj.h"
 #include "main/image.h"
+#include "main/glformats.h"
 #include "main/macros.h"
 #include "main/mtypes.h"
 #include "main/glformats.h"
 #include "main/pbo.h"
+#include "main/readpix.h"
 #include "main/texobj.h"
 #include "main/texstore.h"
 #include "main/texcompress.h"
 #include "main/enums.h"
 #include "drivers/common/meta.h"
 
+#include "brw_blorp.h"
 #include "brw_context.h"
 #include "intel_batchbuffer.h"
 #include "intel_tex.h"
 #include "intel_mipmap_tree.h"
 #include "intel_blit.h"
+#include "intel_buffer_objects.h"
 #include "intel_tiled_memcpy.h"
 
 #define FILE_DEBUG_FLAG DEBUG_TEXTURE
@@ -212,6 +216,169 @@ intel_texsubimage_tiled_memcpy(struct gl_context * ctx,
    return true;
 }
 
+bool
+intel_texsubimage_pbo(struct gl_context *ctx, GLuint dims,
+                      struct gl_texture_image *tex,
+                      GLint x, GLint y, GLint z,
+                      GLsizei width, GLsizei height, GLsizei depth,
+                      GLenum format, GLenum type, const GLvoid *pixels)
+{
+   struct brw_context *brw = brw_context(ctx);
+   struct intel_texture_image *image = intel_texture_image(tex);
+   const struct gl_pixelstore_attrib *pack = &ctx->Unpack;
+   bool ok;
+
+   if (ctx->_ImageTransferState)
+      return false;
+
+   if (pack->SwapBytes || pack->LsbFirst) {
+      DBG("%s: bad packing params\n", __func__);
+      return false;
+   }
+
+   if (format == GL_COLOR_INDEX)
+      return false;
+
+   if (_mesa_need_rgb_to_luminance_conversion(format, tex->_BaseFormat))
+      return false;
+
+   struct intel_mipmap_tree *dst = image->mt;
+   if (format == GL_STENCIL_INDEX && dst->stencil_mt)
+      dst = dst->stencil_mt;
+   if (!brw->mesa_format_supports_render[dst->format])
+      return false;
+
+   mesa_format src_format = _mesa_format_from_format_and_type(format, type);
+   if (_mesa_format_is_mesa_array_format(src_format))
+      src_format = _mesa_format_from_array_format(src_format);
+   if (!brw->screen->mesa_format_supports_texture[src_format])
+      return false;
+
+   bool src_flip = false;
+   int src_stride = _mesa_image_row_stride(pack, width, format, type);
+   if (pack->Invert) {
+      src_stride = -src_stride;
+      src_flip = true;
+   }
+
+   int image_height = pack->ImageHeight == 0 ? height : pack->ImageHeight;
+   int full_height = image_height * (depth - 1) + height;
+   int bpp = _mesa_bytes_per_pixel(format, type);
+   pixels += (pack->SkipImages * image_height + pack->SkipRows) * src_stride;
+   pixels += pack->SkipPixels * bpp;
+   int src_size = (full_height - 1) * src_stride + width * bpp;
+
+   struct brw_bo *src_buffer;
+   int src_offset;
+   if (_mesa_is_bufferobj(pack->BufferObj)) {
+      src_offset = (GLintptr)pixels,
+                 src_buffer = intel_bufferobj_buffer(brw,
+                                                     intel_buffer_object(pack->BufferObj),
+                                                     src_offset,
+                                                     src_size,
+                                                     true);
+   } else if (brw_bo_busy(dst->bo)) {
+      src_offset = 0;
+      src_buffer = brw_bo_alloc(brw->bufmgr, "texsubimage", src_size, 0);
+      if (!src_buffer)
+         return false;
+
+      void *map = brw_bo_map(brw, src_buffer, MAP_WRITE);
+      if (!map)
+         goto err_src_buffer;
+
+      memcpy(map, pixels, src_size);
+      brw_bo_unmap(src_buffer);
+   } else {
+      src_offset = (GLintptr)pixels & 4095;
+      src_buffer = brw_bo_alloc_userptr(brw->bufmgr, "texsubimage(userptr)",
+                                        (void *)((GLintptr)pixels & -4096),
+                                        ALIGN(src_size + src_offset, 4096), 0);
+   }
+   if (!src_buffer)
+      return false;
+
+   if (tex->TexObject->Target == GL_TEXTURE_1D_ARRAY) {
+      assert(depth == 1);
+      assert(z == 0);
+      depth = height;
+      height = 1;
+      image_height = 1;
+      z = y;
+      y = 0;
+   }
+
+   struct intel_mipmap_tree *src =
+      intel_miptree_create_for_bo(brw,
+                                  src_buffer,
+                                  src_format,
+                                  src_offset,
+                                  width, full_height, 1,
+                                  src_stride,
+                                  MIPTREE_LAYOUT_TILING_NONE |
+                                  MIPTREE_LAYOUT_DISABLE_AUX |
+                                  MIPTREE_LAYOUT_FOR_TEXTURE);
+   if (!src)
+      goto err_src_buffer;
+
+   int dst_level = tex->Level + tex->TexObject->MinLevel;
+   int dst_slice = tex->Face + tex->TexObject->MinLayer + z;
+
+   /* blorp restrictions; see try_blorp_blit() */
+   mesa_format dst_format = dst->format;
+   switch (format) {
+   case GL_STENCIL_INDEX:
+      if (src_format != dst_format)
+         goto err_src_mt;
+
+      /* fallthrough */
+   case GL_DEPTH_COMPONENT:
+   case GL_DEPTH_STENCIL_EXT:
+      if ((src_format == MESA_FORMAT_Z24_UNORM_X8_UINT) !=
+          (dst_format == MESA_FORMAT_Z24_UNORM_X8_UINT))
+         goto err_src_mt;
+
+      if (_mesa_get_format_base_format(src_format) == GL_DEPTH_STENCIL ||
+          _mesa_get_format_base_format(dst_format) == GL_DEPTH_STENCIL)
+         goto err_src_mt;
+
+      src_format = MESA_FORMAT_NONE;
+      dst_format = MESA_FORMAT_NONE;
+      break;
+
+   default:
+      break;
+   }
+
+   for (z = 0; depth--; z++) {
+      if (!intel_miptree_blit(brw,
+                              src, 0, 0, 0, z * image_height, src_flip,
+                              dst, dst_level, dst_slice + z, x, y, false,
+                              width, height, GL_COPY)) {
+         brw_blorp_blit_miptrees(brw,
+                                 src, 0, 0,
+                                 src_format, SWIZZLE_XYZW,
+                                 dst, dst_level, dst_slice + z, dst_format,
+                                 0, z * image_height, width, z * image_height + height,
+                                 x, y, x + width, y + height,
+                                 GL_NEAREST, false, src_flip,
+                                 false, false);
+      }
+   }
+   if (src_buffer->userptr) {
+      intel_batchbuffer_flush(brw);
+      brw_bo_wait_rendering(src_buffer);
+   }
+
+   ok = true;
+err_src_mt:
+   intel_miptree_release(&src);
+err_src_buffer:
+   if (!_mesa_is_bufferobj(pack->BufferObj))
+      brw_bo_unreference(src_buffer);
+   return ok;
+}
+
 static void
 intelTexSubImage(struct gl_context * ctx,
                  GLuint dims,
@@ -223,9 +390,6 @@ intelTexSubImage(struct gl_context * ctx,
                  const struct gl_pixelstore_attrib *packing)
 {
    struct intel_mipmap_tree *mt = intel_texture_image(texImage)->mt;
-   bool ok;
-
-   bool tex_busy = mt && brw_bo_busy(mt->bo);
 
    if (mt && mt->format == MESA_FORMAT_S_UINT8)
       mt->r8stencil_needs_update = true;
@@ -236,20 +400,21 @@ intelTexSubImage(struct gl_context * ctx,
        _mesa_enum_to_string(format), _mesa_enum_to_string(type),
        texImage->Level, texImage->Width, texImage->Height, texImage->Depth);
 
-   ok = _mesa_meta_pbo_TexSubImage(ctx, dims, texImage,
-                                   xoffset, yoffset, zoffset,
-                                   width, height, depth, format, type,
-                                   pixels, tex_busy, packing);
-   if (ok)
-      return;
+   if (!_mesa_is_bufferobj(packing->BufferObj)) {
+      if (intel_texsubimage_tiled_memcpy(ctx, dims, texImage,
+                                         xoffset, yoffset, zoffset,
+                                         width, height, depth,
+                                         format, type, pixels, packing,
+                                         false /*for_glTexImage*/))
+         return;
+   }
 
-   ok = intel_texsubimage_tiled_memcpy(ctx, dims, texImage,
-                                       xoffset, yoffset, zoffset,
-                                       width, height, depth,
-                                       format, type, pixels, packing,
-                                       false /*for_glTexImage*/);
-   if (ok)
-     return;
+
+   if (intel_texsubimage_pbo(ctx, dims, texImage,
+                             xoffset, yoffset, zoffset,
+                             width, height, depth,
+                             format, type, pixels))
+      return;
 
    _mesa_store_texsubimage(ctx, dims, texImage,
                            xoffset, yoffset, zoffset,
-- 
2.13.3



More information about the mesa-dev mailing list