v3d: Use the TFU to do generatemipmap.
authorEric Anholt <eric@anholt.net>
Fri, 2 Nov 2018 18:31:42 +0000 (11:31 -0700)
committerEric Anholt <eric@anholt.net>
Sat, 8 Dec 2018 00:48:23 +0000 (16:48 -0800)
This is a separate, dedicated hardware unit for texture layout conversions
and mipmap generation.

src/gallium/drivers/v3d/v3d_blit.c
src/gallium/drivers/v3d/v3d_context.h
src/gallium/drivers/v3d/v3d_formats.c
src/gallium/drivers/v3d/v3d_resource.c
src/gallium/drivers/v3d/v3d_screen.c
src/gallium/drivers/v3d/v3dx_context.h
src/gallium/drivers/v3d/v3dx_format_table.c

index 1a0406a6ed97802060cf0c91681fea555bad6b2c..f2ded8bbf72db33b49bfa7776a293522ee3fb34a 100644 (file)
@@ -25,6 +25,7 @@
 #include "util/u_surface.h"
 #include "util/u_blitter.h"
 #include "v3d_context.h"
+#include "v3d_tiling.h"
 
 #if 0
 static struct pipe_surface *
@@ -316,6 +317,109 @@ v3d_stencil_blit(struct pipe_context *ctx, const struct pipe_blit_info *info)
         pipe_sampler_view_reference(&src_view, NULL);
 }
 
+/* Disable level 0 write, just write following mipmaps */
+#define V3D_TFU_IOA_DIMTW (1 << 0)
+#define V3D_TFU_IOA_FORMAT_SHIFT 3
+#define V3D_TFU_IOA_FORMAT_LINEARTILE 3
+#define V3D_TFU_IOA_FORMAT_UBLINEAR_1_COLUMN 4
+#define V3D_TFU_IOA_FORMAT_UBLINEAR_2_COLUMN 5
+#define V3D_TFU_IOA_FORMAT_UIF_NO_XOR 6
+#define V3D_TFU_IOA_FORMAT_UIF_XOR 7
+
+#define V3D_TFU_ICFG_NUMMM_SHIFT 5
+#define V3D_TFU_ICFG_TTYPE_SHIFT 9
+
+#define V3D_TFU_ICFG_FORMAT_SHIFT 18
+#define V3D_TFU_ICFG_FORMAT_RASTER 0
+#define V3D_TFU_ICFG_FORMAT_SAND_128 1
+#define V3D_TFU_ICFG_FORMAT_SAND_256 2
+#define V3D_TFU_ICFG_FORMAT_LINEARTILE 11
+#define V3D_TFU_ICFG_FORMAT_UBLINEAR_1_COLUMN 12
+#define V3D_TFU_ICFG_FORMAT_UBLINEAR_2_COLUMN 13
+#define V3D_TFU_ICFG_FORMAT_UIF_NO_XOR 14
+#define V3D_TFU_ICFG_FORMAT_UIF_XOR 15
+
+boolean
+v3d_generate_mipmap(struct pipe_context *pctx,
+                    struct pipe_resource *prsc,
+                    enum pipe_format format,
+                    unsigned int base_level,
+                    unsigned int last_level,
+                    unsigned int first_layer,
+                    unsigned int last_layer)
+{
+        struct v3d_context *v3d = v3d_context(pctx);
+        struct v3d_screen *screen = v3d->screen;
+        struct v3d_resource *rsc = v3d_resource(prsc);
+        struct v3d_resource_slice *base_slice = &rsc->slices[base_level];
+        int width = u_minify(prsc->width0, base_level);
+        int height = u_minify(prsc->height0, base_level);
+        uint32_t tex_format = v3d_get_tex_format(&screen->devinfo,
+                                                 prsc->format);
+
+        if (!v3d_tfu_supports_tex_format(&screen->devinfo, tex_format))
+                return false;
+
+        if (prsc->target != PIPE_TEXTURE_2D)
+                return false;
+        /* Since we don't support array or 3D textures, there should be only
+         * one layer.
+         */
+        int layer = first_layer;
+        assert(first_layer == last_layer);
+
+        /* Can't write to raster. */
+        if (base_slice->tiling == VC5_TILING_RASTER)
+                return false;
+
+        v3d_flush_jobs_reading_resource(v3d, prsc);
+
+        struct drm_v3d_submit_tfu tfu = {
+                .ios = (height << 16) | width,
+                .bo_handles = { rsc->bo->handle },
+                .in_sync = v3d->out_sync,
+                .out_sync = v3d->out_sync,
+        };
+        uint32_t offset = (rsc->bo->offset +
+                           v3d_layer_offset(prsc, base_level, layer));
+        tfu.iia |= offset;
+        tfu.icfg |= ((V3D_TFU_ICFG_FORMAT_LINEARTILE +
+                      (base_slice->tiling - VC5_TILING_LINEARTILE)) <<
+                     V3D_TFU_ICFG_FORMAT_SHIFT);
+
+        tfu.ioa |= offset;
+        tfu.ioa |= V3D_TFU_IOA_DIMTW;
+        tfu.ioa |= ((V3D_TFU_IOA_FORMAT_LINEARTILE +
+                     (base_slice->tiling - VC5_TILING_LINEARTILE)) <<
+                    V3D_TFU_IOA_FORMAT_SHIFT);
+
+        tfu.icfg |= tex_format << V3D_TFU_ICFG_TTYPE_SHIFT;
+        tfu.icfg |= (last_level - base_level) << V3D_TFU_ICFG_NUMMM_SHIFT;
+
+        switch (base_slice->tiling) {
+        case VC5_TILING_UIF_NO_XOR:
+        case VC5_TILING_UIF_XOR:
+                tfu.iis |= (base_slice->padded_height /
+                            (2 * v3d_utile_height(rsc->cpp)));
+                break;
+        case VC5_TILING_RASTER:
+                tfu.iis |= base_slice->stride;
+                break;
+        case VC5_TILING_LINEARTILE:
+        case VC5_TILING_UBLINEAR_1_COLUMN:
+        case VC5_TILING_UBLINEAR_2_COLUMN:
+                break;
+       }
+
+        int ret = v3d_ioctl(screen->fd, DRM_IOCTL_V3D_SUBMIT_TFU, &tfu);
+        if (ret != 0) {
+                fprintf(stderr, "Failed to submit TFU job: %d\n", ret);
+                return false;
+        }
+
+        return true;
+}
+
 /* Optimal hardware path for blitting pixels.
  * Scaling, format conversion, up- and downsampling (resolve) are allowed.
  */
index 4c3779a49908e28d78067e0b4e9641035daf189d..8c55eadfa157bd8c84f881ba2d1c82226b50393d 100644 (file)
@@ -365,7 +365,7 @@ struct v3d_context {
         /** Maximum index buffer valid for the current shader_rec. */
         uint32_t max_index;
 
-        /** Sync object that our RCL will update as its out_sync. */
+        /** Sync object that our RCL or TFU job will update as its out_sync. */
         uint32_t out_sync;
 
         struct u_upload_mgr *uploader;
@@ -526,10 +526,19 @@ void v3d_get_internal_type_bpp_for_output_format(const struct v3d_device_info *d
                                                  uint32_t format,
                                                  uint32_t *type,
                                                  uint32_t *bpp);
+bool v3d_tfu_supports_tex_format(const struct v3d_device_info *devinfo,
+                                 uint32_t tex_format);
 
 void v3d_init_query_functions(struct v3d_context *v3d);
 void v3d_blit(struct pipe_context *pctx, const struct pipe_blit_info *blit_info);
 void v3d_blitter_save(struct v3d_context *v3d);
+boolean v3d_generate_mipmap(struct pipe_context *pctx,
+                            struct pipe_resource *prsc,
+                            enum pipe_format format,
+                            unsigned int base_level,
+                            unsigned int last_level,
+                            unsigned int first_layer,
+                            unsigned int last_layer);
 
 struct v3d_fence *v3d_fence_create(struct v3d_context *v3d);
 
index bdb86935f6588f4f1cd19f606878869923523f0a..5bd8db0dbd419dcadf29a8aa106d40b2a82e0a79 100644 (file)
@@ -142,3 +142,14 @@ v3d_get_internal_type_bpp_for_output_format(const struct v3d_device_info *devinf
                                                                      type, bpp);
         }
 }
+
+bool
+v3d_tfu_supports_tex_format(const struct v3d_device_info *devinfo,
+                            uint32_t tex_format)
+{
+        if (devinfo->ver >= 41) {
+                return v3d41_tfu_supports_tex_format(tex_format);
+        } else {
+                return v3d33_tfu_supports_tex_format(tex_format);
+        }
+}
index 39529c10c4c1eb5ee89e2e8f01b72324b01085ca..6c69cbe03f7451ba49196d3e9b0f20f603b84605 100644 (file)
@@ -985,5 +985,6 @@ v3d_resource_context_init(struct pipe_context *pctx)
         pctx->surface_destroy = v3d_surface_destroy;
         pctx->resource_copy_region = util_resource_copy_region;
         pctx->blit = v3d_blit;
+        pctx->generate_mipmap = v3d_generate_mipmap;
         pctx->flush_resource = v3d_flush_resource;
 }
index 7fab90677ea08407cc51b7e9607666f474e8ddde..49ea489d5efde154f65732502dcd1de3a7bd5f53 100644 (file)
@@ -79,6 +79,20 @@ v3d_screen_destroy(struct pipe_screen *pscreen)
         ralloc_free(pscreen);
 }
 
+static bool
+v3d_has_feature(struct v3d_screen *screen, enum drm_v3d_param feature)
+{
+        struct drm_v3d_get_param p = {
+                .param = feature,
+        };
+        int ret = v3d_ioctl(screen->fd, DRM_IOCTL_V3D_GET_PARAM, &p);
+
+        if (ret != 0)
+                return false;
+
+        return p.value;
+}
+
 static int
 v3d_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
 {
@@ -113,6 +127,9 @@ v3d_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
         case PIPE_CAP_TEXTURE_HALF_FLOAT_LINEAR:
                 return 1;
 
+        case PIPE_CAP_GENERATE_MIPMAP:
+                return v3d_has_feature(screen,DRM_V3D_PARAM_SUPPORTS_TFU);
+
         case PIPE_CAP_INDEP_BLEND_ENABLE:
                 return screen->devinfo.ver >= 40;
 
index ca69294a99f89aa5dd56f3a568d4f80108070d62..722b854b819a832d2e0ad7c52e9b75010fb4e00d 100644 (file)
@@ -48,3 +48,4 @@ const struct v3d_format *v3dX(get_format_desc)(enum pipe_format f);
 void v3dX(get_internal_type_bpp_for_output_format)(uint32_t format,
                                                    uint32_t *type,
                                                    uint32_t *bpp);
+bool v3dX(tfu_supports_tex_format)(uint32_t tex_format);
index 100fd3b0da48d1c868a39332be5d41a3dd03dd43..6f9af3cea4f1e0bb19b54af574995e64c37f3ab4 100644 (file)
@@ -318,3 +318,34 @@ v3dX(get_internal_type_bpp_for_output_format)(uint32_t format,
                 break;
         }
 }
+
+bool
+v3dX(tfu_supports_tex_format)(enum V3DX(Texture_Data_Formats) format)
+{
+        switch (format) {
+        case TEXTURE_DATA_FORMAT_R8:
+        case TEXTURE_DATA_FORMAT_R8_SNORM:
+        case TEXTURE_DATA_FORMAT_RG8:
+        case TEXTURE_DATA_FORMAT_RG8_SNORM:
+        case TEXTURE_DATA_FORMAT_RGBA8:
+        case TEXTURE_DATA_FORMAT_RGBA8_SNORM:
+        case TEXTURE_DATA_FORMAT_RGB565:
+        case TEXTURE_DATA_FORMAT_RGBA4:
+        case TEXTURE_DATA_FORMAT_RGB5_A1:
+        case TEXTURE_DATA_FORMAT_RGB10_A2:
+        case TEXTURE_DATA_FORMAT_R16:
+        case TEXTURE_DATA_FORMAT_R16_SNORM:
+        case TEXTURE_DATA_FORMAT_RG16:
+        case TEXTURE_DATA_FORMAT_RG16_SNORM:
+        case TEXTURE_DATA_FORMAT_RGBA16:
+        case TEXTURE_DATA_FORMAT_RGBA16_SNORM:
+        case TEXTURE_DATA_FORMAT_R16F:
+        case TEXTURE_DATA_FORMAT_RG16F:
+        case TEXTURE_DATA_FORMAT_RGBA16F:
+        case TEXTURE_DATA_FORMAT_R11F_G11F_B10F:
+        case TEXTURE_DATA_FORMAT_R4:
+                return true;
+        default:
+                return false;
+        }
+}