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 <ch...@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 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev