[Mesa-dev] [PATCH 6/9] i965: Add support for tex upload using gpu
Anuj Phogat
anuj.phogat at gmail.com
Tue Jan 3 21:33:47 UTC 2017
On Mon, Jan 2, 2017 at 12:45 AM, Pohjolainen, Topi
<topi.pohjolainen at gmail.com> wrote:
> On Thu, Dec 29, 2016 at 11:55:37AM -0800, Anuj Phogat wrote:
>> On Tue, Dec 20, 2016 at 6:45 AM, Topi Pohjolainen
>> <topi.pohjolainen at gmail.com> wrote:
>> > Signed-off-by: Topi Pohjolainen <topi.pohjolainen at intel.com>
>> > ---
>> > src/mesa/drivers/dri/i965/intel_tex.h | 8 +
>> > src/mesa/drivers/dri/i965/intel_tex_subimage.c | 194 +++++++++++++++++++++++++
>> > 2 files changed, 202 insertions(+)
>> >
>> > diff --git a/src/mesa/drivers/dri/i965/intel_tex.h b/src/mesa/drivers/dri/i965/intel_tex.h
>> > index 376f075..c7d0937 100644
>> > --- a/src/mesa/drivers/dri/i965/intel_tex.h
>> > +++ b/src/mesa/drivers/dri/i965/intel_tex.h
>> > @@ -65,6 +65,14 @@ intel_texsubimage_tiled_memcpy(struct gl_context *ctx,
>> > bool for_glTexImage);
>> >
>> > bool
>> > +intel_texsubimage_gpu_copy(struct brw_context *brw, GLuint dims,
>> > + struct gl_texture_image *tex_image,
>> > + unsigned x, unsigned y, unsigned z,
>> > + unsigned w, unsigned h, unsigned d,
>> > + GLenum format, GLenum type, const void *pixels,
>> > + const struct gl_pixelstore_attrib *packing);
>> > +
>> > +bool
>> > intel_gettexsubimage_tiled_memcpy(struct gl_context *ctx,
>> > struct gl_texture_image *texImage,
>> > GLint xoffset, GLint yofset,
>> > diff --git a/src/mesa/drivers/dri/i965/intel_tex_subimage.c b/src/mesa/drivers/dri/i965/intel_tex_subimage.c
>> > index b7e52bc..f999a93 100644
>> > --- a/src/mesa/drivers/dri/i965/intel_tex_subimage.c
>> > +++ b/src/mesa/drivers/dri/i965/intel_tex_subimage.c
>> > @@ -24,6 +24,7 @@
>> > */
>> >
>> > #include "main/bufferobj.h"
>> > +#include "main/glformats.h"
>> > #include "main/image.h"
>> > #include "main/macros.h"
>> > #include "main/mtypes.h"
>> > @@ -34,8 +35,10 @@
>> > #include "main/enums.h"
>> > #include "drivers/common/meta.h"
>> >
>> > +#include "brw_blorp.h"
>> > #include "brw_context.h"
>> > #include "intel_batchbuffer.h"
>> > +#include "intel_buffer_objects.h"
>> > #include "intel_tex.h"
>> > #include "intel_mipmap_tree.h"
>> > #include "intel_blit.h"
>> > @@ -43,6 +46,197 @@
>> >
>> > #define FILE_DEBUG_FLAG DEBUG_TEXTURE
>> >
>> > +static drm_intel_bo *
>> > +intel_texsubimage_get_src_as_bo(struct brw_context *brw, unsigned dims,
>> > + struct gl_texture_image *tex_image,
>> > + unsigned w, unsigned h, unsigned d,
>> > + GLenum format, GLenum type, const void *pixels,
>> > + const struct gl_pixelstore_attrib *packing)
>> > +{
>> > + /* Account for SKIP_PIXELS, SKIP_ROWS, ALIGNMENT, and SKIP_IMAGES */
>> > + const uint32_t first_pixel = _mesa_image_offset(dims, packing, w, h,
>> > + format, type, 0, 0, 0);
>> > + const uint32_t last_pixel = _mesa_image_offset(dims, packing, w, h,
>> > + format, type,
>> > + d - 1, h - 1, w);
>> > + const uint32_t size = last_pixel - first_pixel;
>> > +
>> > + drm_intel_bo * const bo =
>> > + drm_intel_bo_alloc(brw->bufmgr, "tmp_tex_subimage_src", size, 64);
>> > +
>> > + if (bo == NULL) {
>> > + perf_debug("intel_texsubimage: temp bo creation failed: size = %u\n",
>> > + size);
>> > + return false;
>> > + }
>> > +
>> > + if (drm_intel_bo_subdata(bo, 0, size, pixels + first_pixel)) {
>> > + perf_debug("intel_texsubimage: temp bo upload failed\n");
>> > + drm_intel_bo_unreference(bo);
>> > + return NULL;
>> > + }
>> > +
>> > + return bo;
>> > +}
>> > +
>> > +static uint32_t
>> > +intel_texsubimage_get_src_offset(unsigned dims, unsigned w, unsigned h,
>> > + GLenum format, GLenum type,
>> > + const void *pixels,
>> > + const struct gl_pixelstore_attrib *packing)
>> > +{
>> > + /* Account for SKIP_PIXELS, SKIP_ROWS, ALIGNMENT, and SKIP_IMAGES */
>> > + const uint32_t first_pixel = _mesa_image_offset(dims, packing, w, h,
>> > + format, type, 0, 0, 0);
>> > +
>> > + /* In case of buffer object source 'pixels' represents offset in bytes. */
>> > + return first_pixel + (intptr_t)pixels;
>> > +}
>> > +
>> > +/* Consider all the restrictions and determine the format of the source. */
>> > +static mesa_format
>> > +intel_texsubimage_check_upload(struct brw_context *brw,
>> > + const struct gl_texture_image *tex_image,
>> > + unsigned h, GLenum format, GLenum type,
>> > + const struct gl_pixelstore_attrib *packing)
>> > +{
>> > + /* TODO: Add support for buffer object upload 1D alignment or perhaps use
>> > + * flat 2D source.
>> > + */
>> > + if (tex_image->TexObject->Target == GL_TEXTURE_1D_ARRAY) {
>> > + perf_debug("intel_texsubimage: 1D_ARRAY not supported\n");
>> > + return MESA_FORMAT_NONE;
>> > + }
>> > +
>> > + if (brw->ctx._ImageTransferState)
>> > + return MESA_FORMAT_NONE;
>> > +
>> > + if (packing->SwapBytes || packing->LsbFirst || packing->Invert) {
>> > + perf_debug("intel_texsubimage: unsupported gl_pixelstore_attrib\n");
>> > + return MESA_FORMAT_NONE;
>> > + }
>> > +
>> > + /* TODO: This can be easily supported as blit manually offsets miptree
>> > + * for each slice.
>> > + */
>> > + if (packing->ImageHeight != 0) {
>> > + perf_debug("intel_texsubimage: _attrib::ImageHeight not supported\n");
>> > + return MESA_FORMAT_NONE;
>> > + }
>> > +
>> > + if (packing->RowLength != 0) {
>> > + perf_debug("intel_texsubimage: _attrib::RowLength not supported\n");
>> > + return MESA_FORMAT_NONE;
>> > + }
>> > +
>> > + if (format != GL_RED &&
>> > + format != GL_RG &&
>> > + format != GL_RGB &&
>> > + format != GL_RGBA &&
>> > + format != GL_ALPHA) {
>> > + perf_debug("intel_texsubimage: %s not supported",
>> > + _mesa_enum_to_string(format));
>> > + return MESA_FORMAT_NONE;
>> > + }
>> > +
>> > + const mesa_format src_mesa_format =
>> > + _mesa_tex_format_from_format_and_type(&brw->ctx, format, type);
>> > + if (src_mesa_format == MESA_FORMAT_NONE)
>> > + return MESA_FORMAT_NONE;
>> Above if check is not required if you move the src_mesa_format
>> computation after the below if block.
>
> That makes it simpler, will do.
>
>> > +
>> > + if (!brw->format_supported_as_render_target[tex_image->TexFormat]) {
>> > + perf_debug("intel_texsubimage: can't use %s as render target\n",
>> > + _mesa_get_format_name(tex_image->TexFormat));
>> > + return MESA_FORMAT_NONE;
>> > + }
>> > +
>> > + return src_mesa_format;
>> > +}
>> > +
>> > +bool
>> > +intel_texsubimage_gpu_copy(struct brw_context *brw, GLuint dims,
>> > + struct gl_texture_image *tex_image,
>> > + unsigned x, unsigned y, unsigned z,
>> > + unsigned w, unsigned h, unsigned d,
>> > + GLenum format, GLenum type, const void *pixels,
>> > + const struct gl_pixelstore_attrib *packing)
>> > +{
>> > + const bool is_src_bo = _mesa_is_bufferobj(packing->BufferObj);
>> > + struct intel_texture_image *intel_image = intel_texture_image(tex_image);
>> > +
>> > + /* Make sure there is something to upload. */
>> > + if (pixels == NULL && !is_src_bo)
>> > + return false;
>> > +
>> > + const mesa_format src_mesa_format = intel_texsubimage_check_upload(
>> > + brw, tex_image, h, format, type, packing);
>> > + if (src_mesa_format == MESA_FORMAT_NONE)
>> > + return MESA_FORMAT_NONE;
>> return false ?
>
> Oops, good catch!
>
>> > +
>> > + const uint32_t offset = is_src_bo ?
>> > + intel_texsubimage_get_src_offset(dims, w, h, format, type, pixels,
>> > + packing) : 0;
>> > + const uint32_t stride = _mesa_image_row_stride(packing, w, format, type);
>> > + const unsigned level = tex_image->Level + tex_image->TexObject->MinLevel;
>> > + const unsigned start_layer =
>> > + tex_image->TexObject->MinLayer + tex_image->Face + z;
>> > +
>> > + assert(level <= intel_image->mt->last_level);
>> > + assert(start_layer + d <= intel_image->mt->level[level].depth);
>> > +
>> > + drm_intel_bo * const src_bo = is_src_bo ?
>> > + intel_buffer_object(packing->BufferObj)->buffer :
>> > + intel_texsubimage_get_src_as_bo(brw, dims, tex_image, w, h, d,
>> > + format, type, pixels, packing);
>> > + if (src_bo == NULL)
>> > + return false;
>> > +
>> > + bool result = false;
>> > +
>> > + /* Blit slice-by-slice creating a single-slice miptree for each layer. This
>> > + * way the alignment in the source buffer object does not need to meet the
>> > + * hw requirements.
>> > + */
>> Can you explain this hw alignment requirement? This is for my understanding.
>
> Good question. Even for linear (non-tiled) buffers I noticed by experimenting
> that hardware wants to have individual slices of arrayed textures vertically
> aligned by 4. However, for single slice the starting address doesn't need to
> be aligned, and therefore offsetting to individual slices manually works.
>
It'll be nice to put this information in a comment here. So, nobody will
get confused later which hw alignment requirement you are talking about.
>>
>> > + for (unsigned i = 0; i < d; ++i) {
>> > + /* Wrap the source buffer object with a miptree. */
>> > + struct intel_mipmap_tree *src_mt = intel_miptree_create_for_bo(
>> > + brw, src_bo, src_mesa_format,
>> > + offset + i * h * stride,
>> > + w, h, 1, stride, 0);
>> > + if (!src_mt) {
>> > + perf_debug("intel_texsubimage: miptree creation for src failed\n");
>> > + goto err;
>> > + }
>> > +
>> > + /* In case exact match is needed, copy using equivalent UINT formats
>> > + * preventing hardware from changing presentation for SNORM -1.
>> > + */
>> > + if (src_mt->format == intel_image->mt->format) {
>> > + brw_blorp_copy_miptrees(brw, src_mt, 0, 0,
>> > + intel_image->mt, level, start_layer + i,
>> > + 0, 0, x, y, w, h);
>> > + } else {
>> > + brw_blorp_blit_miptrees(brw, src_mt, 0, 0,
>> > + src_mesa_format, SWIZZLE_XYZW,
>> > + intel_image->mt, level, start_layer + i,
>> > + intel_image->mt->format,
>> > + 0, 0, w, h,
>> > + x, y, x + w, y + h,
>> > + GL_NEAREST, false, false, false, false);
>> > + }
>> > +
>> > + intel_miptree_release(&src_mt);
>> > + }
>> > +
>> > + result = true;
>> > +
>> > +err:
>> > + if (!is_src_bo)
>> > + drm_intel_bo_unreference(src_bo);
>> > +
>> > + return result;
>> > +}
>> > +
>> > /**
>> > * \brief A fast path for glTexImage and glTexSubImage.
>> > *
>> > --
>> > 2.5.5
>> >
>> > _______________________________________________
>> > mesa-dev mailing list
>> > mesa-dev at lists.freedesktop.org
>> > https://lists.freedesktop.org/mailman/listinfo/mesa-dev
With suggested changes paches 6-8 are:
Reviewed-by: Anuj Phogat <anuj.phogat at gmail.com>
More information about the mesa-dev
mailing list