nvc0: implement support for maxwell texture headers
authorBen Skeggs <bskeggs@redhat.com>
Mon, 15 Feb 2016 05:37:29 +0000 (15:37 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Tue, 16 Feb 2016 05:57:13 +0000 (15:57 +1000)
Adds support for the new TIC layout that's present on Maxwell GPUs,
heavily based on the code for the existing layout.

This code is required for GM20x support.  While GM10x supports the older
layout still, this commit switches it to use the updated version instead.

Piglit testing shows zero regressions on GM107.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Acked-by: Ilia Mirkin <imirkin@alum.mit.edu>
src/gallium/drivers/nouveau/nvc0/nvc0_screen.c
src/gallium/drivers/nouveau/nvc0/nvc0_screen.h
src/gallium/drivers/nouveau/nvc0/nvc0_tex.c

index 811a58c6cd27dba9416352de4decb505b9136b8d..ec7471c9672c68634550b951283ab79aaf4bfb97 100644 (file)
@@ -993,6 +993,14 @@ nvc0_screen_create(struct nouveau_device *dev)
    PUSH_DATAh(push, screen->txc->offset);
    PUSH_DATA (push, screen->txc->offset);
    PUSH_DATA (push, NVC0_TIC_MAX_ENTRIES - 1);
+   if (screen->eng3d->oclass >= GM107_3D_CLASS) {
+      screen->tic.maxwell = true;
+      if (screen->eng3d->oclass == GM107_3D_CLASS) {
+         screen->tic.maxwell =
+            debug_get_bool_option("NOUVEAU_MAXWELL_TIC", true);
+         IMMED_NVC0(push, SUBC_3D(0x0f10), screen->tic.maxwell);
+      }
+   }
 
    BEGIN_NVC0(push, NVC0_3D(TSC_ADDRESS_HIGH), 3);
    PUSH_DATAh(push, screen->txc->offset + 65536);
index 40c9c7a6f8b053ac0382e109b548baa9b5f1bc7a..f34fabd6bc98a15ded9988f2ffd1b355847927ea 100644 (file)
@@ -83,6 +83,7 @@ struct nvc0_screen {
       void **entries;
       int next;
       uint32_t lock[NVC0_TIC_MAX_ENTRIES / 32];
+      bool maxwell;
    } tic;
 
    struct {
index ae4d53c9d0860ce3e58466a58c03dbe8fca8f8e8..0f46732d11d01c222b851ba4253a04870a6d9a44 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "nvc0/nvc0_context.h"
 #include "nvc0/nvc0_resource.h"
+#include "nvc0/gm107_texture.xml.h"
 #include "nv50/g80_texture.xml.h"
 #include "nv50/g80_defs.xml.h"
 
@@ -59,12 +60,187 @@ nvc0_create_sampler_view(struct pipe_context *pipe,
    return nvc0_create_texture_view(pipe, res, templ, flags, templ->target);
 }
 
-struct pipe_sampler_view *
-nvc0_create_texture_view(struct pipe_context *pipe,
-                         struct pipe_resource *texture,
-                         const struct pipe_sampler_view *templ,
-                         uint32_t flags,
-                         enum pipe_texture_target target)
+static struct pipe_sampler_view *
+gm107_create_texture_view(struct pipe_context *pipe,
+                          struct pipe_resource *texture,
+                          const struct pipe_sampler_view *templ,
+                          uint32_t flags,
+                          enum pipe_texture_target target)
+{
+   const struct util_format_description *desc;
+   const struct nvc0_format *fmt;
+   uint64_t address;
+   uint32_t *tic;
+   uint32_t swz[4];
+   uint32_t width, height;
+   uint32_t depth;
+   struct nv50_tic_entry *view;
+   struct nv50_miptree *mt;
+   bool tex_int;
+
+   view = MALLOC_STRUCT(nv50_tic_entry);
+   if (!view)
+      return NULL;
+   mt = nv50_miptree(texture);
+
+   view->pipe = *templ;
+   view->pipe.reference.count = 1;
+   view->pipe.texture = NULL;
+   view->pipe.context = pipe;
+
+   view->id = -1;
+
+   pipe_resource_reference(&view->pipe.texture, texture);
+
+   tic = &view->tic[0];
+
+   desc = util_format_description(view->pipe.format);
+   tex_int = util_format_is_pure_integer(view->pipe.format);
+
+   fmt = &nvc0_format_table[view->pipe.format];
+   swz[0] = nv50_tic_swizzle(fmt, view->pipe.swizzle_r, tex_int);
+   swz[1] = nv50_tic_swizzle(fmt, view->pipe.swizzle_g, tex_int);
+   swz[2] = nv50_tic_swizzle(fmt, view->pipe.swizzle_b, tex_int);
+   swz[3] = nv50_tic_swizzle(fmt, view->pipe.swizzle_a, tex_int);
+
+   tic[0]  = fmt->tic.format << GM107_TIC2_0_COMPONENTS_SIZES__SHIFT;
+   tic[0] |= fmt->tic.type_r << GM107_TIC2_0_R_DATA_TYPE__SHIFT;
+   tic[0] |= fmt->tic.type_g << GM107_TIC2_0_G_DATA_TYPE__SHIFT;
+   tic[0] |= fmt->tic.type_b << GM107_TIC2_0_B_DATA_TYPE__SHIFT;
+   tic[0] |= fmt->tic.type_a << GM107_TIC2_0_A_DATA_TYPE__SHIFT;
+   tic[0] |= swz[0] << GM107_TIC2_0_X_SOURCE__SHIFT;
+   tic[0] |= swz[1] << GM107_TIC2_0_Y_SOURCE__SHIFT;
+   tic[0] |= swz[2] << GM107_TIC2_0_Z_SOURCE__SHIFT;
+   tic[0] |= swz[3] << GM107_TIC2_0_W_SOURCE__SHIFT;
+
+   address = mt->base.address;
+
+   tic[3]  = GM107_TIC2_3_LOD_ANISO_QUALITY_2;
+   tic[4]  = GM107_TIC2_4_SECTOR_PROMOTION_PROMOTE_TO_2_V;
+   tic[4] |= GM107_TIC2_4_BORDER_SIZE_SAMPLER_COLOR;
+
+   if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB)
+      tic[4] |= GM107_TIC2_4_SRGB_CONVERSION;
+
+   if (!(flags & NV50_TEXVIEW_SCALED_COORDS))
+      tic[5] = GM107_TIC2_5_NORMALIZED_COORDS;
+   else
+      tic[5] = 0;
+
+   /* check for linear storage type */
+   if (unlikely(!nouveau_bo_memtype(nv04_resource(texture)->bo))) {
+      if (texture->target == PIPE_BUFFER) {
+         assert(!(tic[5] & GM107_TIC2_5_NORMALIZED_COORDS));
+         width = view->pipe.u.buf.last_element - view->pipe.u.buf.first_element;
+         address +=
+            view->pipe.u.buf.first_element * desc->block.bits / 8;
+         tic[2]  = GM107_TIC2_2_HEADER_VERSION_ONE_D_BUFFER;
+         tic[3] |= width >> 16;
+         tic[4] |= GM107_TIC2_4_TEXTURE_TYPE_ONE_D_BUFFER;
+         tic[4] |= width & 0xffff;
+      } else {
+         assert(!(mt->level[0].pitch & 0x1f));
+         /* must be 2D texture without mip maps */
+         tic[2]  = GM107_TIC2_2_HEADER_VERSION_PITCH;
+         tic[4] |= GM107_TIC2_4_TEXTURE_TYPE_TWO_D_NO_MIPMAP;
+         tic[3] |= mt->level[0].pitch >> 5;
+         tic[4] |= mt->base.base.width0 - 1;
+         tic[5] |= 0 << GM107_TIC2_5_DEPTH_MINUS_ONE__SHIFT;
+         tic[5] |= mt->base.base.height0 - 1;
+      }
+      tic[1]  = address;
+      tic[2] |= address >> 32;
+      tic[6]  = 0;
+      tic[7]  = 0;
+      return &view->pipe;
+   }
+
+   tic[2]  = GM107_TIC2_2_HEADER_VERSION_BLOCKLINEAR;
+   tic[3] |=
+      ((mt->level[0].tile_mode & 0x0f0) >> 4 << 3) |
+      ((mt->level[0].tile_mode & 0xf00) >> 8 << 6);
+
+   depth = MAX2(mt->base.base.array_size, mt->base.base.depth0);
+
+   if (mt->base.base.array_size > 1) {
+      /* there doesn't seem to be a base layer field in TIC */
+      address += view->pipe.u.tex.first_layer * mt->layer_stride;
+      depth = view->pipe.u.tex.last_layer - view->pipe.u.tex.first_layer + 1;
+   }
+   tic[1]  = address;
+   tic[2] |= address >> 32;
+
+   switch (target) {
+   case PIPE_TEXTURE_1D:
+      tic[4] |= GM107_TIC2_4_TEXTURE_TYPE_ONE_D;
+      break;
+   case PIPE_TEXTURE_2D:
+      tic[4] |= GM107_TIC2_4_TEXTURE_TYPE_TWO_D;
+      break;
+   case PIPE_TEXTURE_RECT:
+      tic[4] |= GM107_TIC2_4_TEXTURE_TYPE_TWO_D;
+      break;
+   case PIPE_TEXTURE_3D:
+      tic[4] |= GM107_TIC2_4_TEXTURE_TYPE_THREE_D;
+      break;
+   case PIPE_TEXTURE_CUBE:
+      depth /= 6;
+      tic[4] |= GM107_TIC2_4_TEXTURE_TYPE_CUBEMAP;
+      break;
+   case PIPE_TEXTURE_1D_ARRAY:
+      tic[4] |= GM107_TIC2_4_TEXTURE_TYPE_ONE_D_ARRAY;
+      break;
+   case PIPE_TEXTURE_2D_ARRAY:
+      tic[4] |= GM107_TIC2_4_TEXTURE_TYPE_TWO_D_ARRAY;
+      break;
+   case PIPE_TEXTURE_CUBE_ARRAY:
+      depth /= 6;
+      tic[4] |= GM107_TIC2_4_TEXTURE_TYPE_CUBE_ARRAY;
+      break;
+   default:
+      unreachable("unexpected/invalid texture target");
+   }
+
+   tic[3] |= (flags & NV50_TEXVIEW_FILTER_MSAA8) ?
+             GM107_TIC2_3_USE_HEADER_OPT_CONTROL :
+             GM107_TIC2_3_LOD_ANISO_QUALITY_HIGH |
+             GM107_TIC2_3_LOD_ISO_QUALITY_HIGH;
+
+   if (flags & NV50_TEXVIEW_ACCESS_RESOLVE) {
+      width = mt->base.base.width0 << mt->ms_x;
+      height = mt->base.base.height0 << mt->ms_y;
+   } else {
+      width = mt->base.base.width0;
+      height = mt->base.base.height0;
+   }
+
+   tic[4] |= width - 1;
+
+   tic[5] |= (height - 1) & 0xffff;
+   tic[5] |= (depth - 1) << GM107_TIC2_5_DEPTH_MINUS_ONE__SHIFT;
+   tic[3] |= mt->base.base.last_level << GM107_TIC2_3_MAX_MIP_LEVEL__SHIFT;
+
+   /* sampling points: (?) */
+   if ((flags & NV50_TEXVIEW_ACCESS_RESOLVE) && mt->ms_x > 1) {
+      tic[6]  = GM107_TIC2_6_ANISO_FINE_SPREAD_MODIFIER_CONST_TWO;
+      tic[6] |= GM107_TIC2_6_MAX_ANISOTROPY_2_TO_1;
+   } else {
+      tic[6]  = GM107_TIC2_6_ANISO_FINE_SPREAD_FUNC_TWO;
+      tic[6] |= GM107_TIC2_6_ANISO_COARSE_SPREAD_FUNC_ONE;
+   }
+
+   tic[7]  = (view->pipe.u.tex.last_level << 4) | view->pipe.u.tex.first_level;
+   tic[7] |= mt->ms_mode << GM107_TIC2_7_MULTI_SAMPLE_COUNT__SHIFT;
+
+   return &view->pipe;
+}
+
+static struct pipe_sampler_view *
+gf100_create_texture_view(struct pipe_context *pipe,
+                          struct pipe_resource *texture,
+                          const struct pipe_sampler_view *templ,
+                          uint32_t flags,
+                          enum pipe_texture_target target)
 {
    const struct util_format_description *desc;
    const struct nvc0_format *fmt;
@@ -221,6 +397,18 @@ nvc0_create_texture_view(struct pipe_context *pipe,
    return &view->pipe;
 }
 
+struct pipe_sampler_view *
+nvc0_create_texture_view(struct pipe_context *pipe,
+                         struct pipe_resource *texture,
+                         const struct pipe_sampler_view *templ,
+                         uint32_t flags,
+                         enum pipe_texture_target target)
+{
+   if (nvc0_context(pipe)->screen->tic.maxwell)
+      return gm107_create_texture_view(pipe, texture, templ, flags, target);
+   return gf100_create_texture_view(pipe, texture, templ, flags, target);
+}
+
 static void
 nvc0_update_tic(struct nvc0_context *nvc0, struct nv50_tic_entry *tic,
                 struct nv04_resource *res)