lima: introduce a struct describing texture descriptor
authorVasily Khoruzhick <anarsoul@gmail.com>
Wed, 7 Aug 2019 02:58:42 +0000 (19:58 -0700)
committerVasily Khoruzhick <anarsoul@gmail.com>
Fri, 9 Aug 2019 02:17:20 +0000 (19:17 -0700)
Use a struct with bitfields to construct texture descriptor
instead of poking bits in array of uint32_t. It improves code
readability and makes it easier to experiment with unknown fields.

Also fix mipmapping while we're at it - Utgard can have up to 13
levels, but 64 bytes is enough only for 10. Calculate descriptor
size dynamically to account extra levels if we need them.

Reviewed-by: Qiang Yu <yuq825@gmail.com>
Signed-off-by: Vasily Khoruzhick <anarsoul@gmail.com>
src/gallium/drivers/lima/lima_draw.c
src/gallium/drivers/lima/lima_texture.c
src/gallium/drivers/lima/lima_texture.h

index 8c1e7ed01bc973cc76a588152419670d483fcd3e..87eeb0e795ba641171d8ba99d64dca392d524c55 100644 (file)
@@ -275,13 +275,16 @@ lima_pack_reload_plbu_cmd(struct lima_context *ctx)
           sizeof(reload_render_state));
 
    struct lima_context_framebuffer *fb = &ctx->framebuffer;
-   uint32_t *td = cpu + lima_reload_tex_desc_offset;
-   memset(td, 0, lima_tex_desc_size);
+   lima_tex_desc *td = cpu + lima_reload_tex_desc_offset;
+   memset(td, 0, lima_min_tex_desc_size);
    lima_texture_desc_set_res(ctx, td, fb->base.cbufs[0]->texture, 0, 0);
-   td[1] = 0x00000480;
-   td[2] |= 0x00093800;
-   td[4] = 0x00000000;
-   td[5] = 0x00000000;
+   td->unknown_1_1 = 0x80;
+   td->texture_2d = 1;
+   td->min_img_filter_nearest = 1;
+   td->mag_img_filter_nearest = 1;
+   td->wrap_s_clamp_to_edge = 1;
+   td->wrap_t_clamp_to_edge = 1;
+   td->unknown_2_2 = 0x1;
 
    uint32_t *ta = cpu + lima_reload_tex_array_offset;
    ta[0] = va + lima_reload_tex_desc_offset;
index d2f317b5e1a741c924257b2e4a7b7ad89add94a8..9fb6313cf5361a534e41ba75f844447ae40e9f9d 100644 (file)
@@ -86,6 +86,8 @@ static const lima_format lima_format_table[] = {
    LIMA_FORMAT(L8A8_UNORM, LIMA_TEXEL_FORMAT_L8A8, false),
 };
 
+static_assert(offsetof(lima_tex_desc, va) == 24, "lima_tex_desc->va offset isn't 24");
+
 bool
 lima_texel_format_supported(enum pipe_format pformat)
 {
@@ -95,8 +97,25 @@ lima_texel_format_supported(enum pipe_format pformat)
    return lima_format_table[pformat].present;
 }
 
+static void
+lima_texture_desc_set_va(lima_tex_desc *desc,
+                         int idx,
+                         uint32_t va)
+{
+   unsigned va_bit_idx = VA_BIT_OFFSET + (VA_BIT_SIZE * idx);
+   unsigned va_idx = va_bit_idx / 32;
+   va_bit_idx %= 32;
+
+   va >>= 6;
+
+   desc->va[va_idx] |= va << va_bit_idx;
+   if (va_bit_idx <= 6)
+      return;
+   desc->va[va_idx + 1] |= va >> (32 - va_bit_idx);
+}
+
 void
-lima_texture_desc_set_res(struct lima_context *ctx, uint32_t *desc,
+lima_texture_desc_set_res(struct lima_context *ctx, lima_tex_desc *desc,
                           struct pipe_resource *prsc,
                           unsigned first_level, unsigned last_level)
 {
@@ -113,18 +132,19 @@ lima_texture_desc_set_res(struct lima_context *ctx, uint32_t *desc,
    assert(prsc->format < ARRAY_SIZE(lima_format_table));
    assert(lima_format_table[prsc->format].present);
 
-   desc[0] |= lima_format_table[prsc->format].lima_format;
-   desc[0] |= lima_format_table[prsc->format].swap_r_b ? (1 << 7) : 0;
-   desc[2] |= (width << 22);
-   desc[3] |= 0x10000 | (height << 3) | (width >> 10);
+   desc->format = lima_format_table[prsc->format].lima_format;
+   desc->swap_r_b = lima_format_table[prsc->format].swap_r_b;
+   desc->width  = width;
+   desc->height = height;
+   desc->unknown_3_1 = 1;
 
    if (lima_res->tiled)
       layout = 3;
    else {
       /* for padded linear texture */
       if (lima_res->levels[first_level].width != width) {
-         desc[0] |= lima_res->levels[first_level].width << 18;
-         desc[2] |= 0x100;
+         desc->stride = lima_res->levels[first_level].width;
+         desc->has_stride = 1;
       }
       layout = 0;
    }
@@ -135,45 +155,32 @@ lima_texture_desc_set_res(struct lima_context *ctx, uint32_t *desc,
 
    /* attach first level */
    uint32_t first_va = base_va + lima_res->levels[first_level].offset;
-   desc[6] |= (first_va << 24) | (layout << 13);
-   desc[7] |= first_va >> 8;
+   desc->va_s.va_0 = first_va >> 6;
+   desc->va_s.layout = layout;
 
    /* Attach remaining levels.
     * Each subsequent mipmap address is specified using the 26 msbs.
     * These addresses are then packed continuously in memory */
-   unsigned current_desc_index = 7;
-   unsigned current_desc_bit_index = 24;
-   for (i = first_level + 1; i <= last_level; i++) {
-      uint32_t address = base_va + lima_res->levels[i].offset;
-      address = (address >> 6);
-      desc[current_desc_index] |= (address << current_desc_bit_index);
-      if (current_desc_bit_index <= 6) {
-         current_desc_bit_index += 26;
-         if (current_desc_bit_index >= 32) {
-            current_desc_bit_index &= 0x1F;
-            current_desc_index++;
-         }
-         continue;
-      }
-      desc[current_desc_index + 1] |= (address >> (32 - current_desc_bit_index));
-      current_desc_bit_index = (current_desc_bit_index + 26) & 0x1F;
-      current_desc_index++;
+   for (i = 1; i <= (last_level - first_level); i++) {
+      uint32_t address = base_va + lima_res->levels[first_level + i].offset;
+      lima_texture_desc_set_va(desc, i, address);
    }
 }
 
 static void
 lima_update_tex_desc(struct lima_context *ctx, struct lima_sampler_state *sampler,
-                     struct lima_sampler_view *texture, void *pdesc)
+                     struct lima_sampler_view *texture, void *pdesc,
+                     unsigned desc_size)
 {
-   uint32_t *desc = pdesc;
+   lima_tex_desc *desc = pdesc;
    unsigned first_level;
    unsigned last_level;
    bool mipmapping;
 
-   memset(desc, 0, lima_tex_desc_size);
+   memset(desc, 0, desc_size);
 
    /* 2D texture */
-   desc[1] |= 0x400;
+   desc->texture_2d = 1;
 
    first_level = texture->base.u.tex.first_level;
    last_level = texture->base.u.tex.last_level;
@@ -182,10 +189,10 @@ lima_update_tex_desc(struct lima_context *ctx, struct lima_sampler_state *sample
 
    switch (sampler->base.min_mip_filter) {
       case PIPE_TEX_MIPFILTER_LINEAR:
-         desc[2] |= 0x0600;
+         desc->min_mipfilter = 3;
       case PIPE_TEX_MIPFILTER_NEAREST:
          mipmapping = true;
-         desc[1] |= ((last_level - first_level) << 24);
+         desc->miplevels = (last_level - first_level);
          break;
       case PIPE_TEX_MIPFILTER_NONE:
       default:
@@ -195,40 +202,39 @@ lima_update_tex_desc(struct lima_context *ctx, struct lima_sampler_state *sample
 
    switch (sampler->base.mag_img_filter) {
    case PIPE_TEX_FILTER_LINEAR:
-      desc[2] &= ~0x1000;
+      desc->mag_img_filter_nearest = 0;
       /* no mipmap, filter_mag = linear */
       if (!mipmapping)
-         desc[1] |= 0x80000000;
+         desc->disable_mipmap = 1;
       break;
    case PIPE_TEX_FILTER_NEAREST:
    default:
-      desc[2] |= 0x1000;
+      desc->mag_img_filter_nearest = 1;
       break;
    }
 
    switch (sampler->base.min_img_filter) {
       break;
    case PIPE_TEX_FILTER_LINEAR:
-      desc[2] &= ~0x0800;
+      desc->min_img_filter_nearest = 0;
       break;
    case PIPE_TEX_FILTER_NEAREST:
    default:
-      desc[2] |= 0x0800;
+      desc->min_img_filter_nearest = 1;
       break;
    }
 
    /* Only clamp, clamp to edge, repeat and mirror repeat are supported */
-   desc[2] &= ~0xe000;
    switch (sampler->base.wrap_s) {
    case PIPE_TEX_WRAP_CLAMP:
-      desc[2] |= 0x4000;
+      desc->wrap_s_clamp = 1;
       break;
    case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
    case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
-      desc[2] |= 0x2000;
+      desc->wrap_s_clamp_to_edge = 1;
       break;
    case PIPE_TEX_WRAP_MIRROR_REPEAT:
-      desc[2] |= 0x8000;
+      desc->wrap_s_mirror_repeat = 1;
       break;
    case PIPE_TEX_WRAP_REPEAT:
    default:
@@ -236,17 +242,16 @@ lima_update_tex_desc(struct lima_context *ctx, struct lima_sampler_state *sample
    }
 
    /* Only clamp, clamp to edge, repeat and mirror repeat are supported */
-   desc[2] &= ~0x070000;
    switch (sampler->base.wrap_t) {
    case PIPE_TEX_WRAP_CLAMP:
-      desc[2] |= 0x020000;
+      desc->wrap_t_clamp = 1;
       break;
    case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
    case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
-      desc[2] |= 0x010000;
+      desc->wrap_t_clamp_to_edge = 1;
       break;
    case PIPE_TEX_WRAP_MIRROR_REPEAT:
-      desc[2] |= 0x040000;
+      desc->wrap_t_mirror_repeat = 1;
       break;
    case PIPE_TEX_WRAP_REPEAT:
    default:
@@ -257,6 +262,24 @@ lima_update_tex_desc(struct lima_context *ctx, struct lima_sampler_state *sample
                              first_level, last_level);
 }
 
+static unsigned
+lima_calc_tex_desc_size(struct lima_sampler_view *texture)
+{
+   unsigned size = offsetof(lima_tex_desc, va);
+   unsigned va_bit_size;
+   unsigned first_level = texture->base.u.tex.first_level;
+   unsigned last_level = texture->base.u.tex.last_level;
+
+   if (last_level - first_level >= LIMA_MAX_MIP_LEVELS)
+      last_level = first_level + LIMA_MAX_MIP_LEVELS - 1;
+
+   va_bit_size = VA_BIT_OFFSET + VA_BIT_SIZE * (last_level - first_level + 1);
+   size += (va_bit_size + 7) >> 3;
+   size = align(size, lima_min_tex_desc_size);
+
+   return size;
+}
+
 void
 lima_update_textures(struct lima_context *ctx)
 {
@@ -268,18 +291,25 @@ lima_update_textures(struct lima_context *ctx)
    if (!lima_tex->num_samplers || !lima_tex->num_textures)
       return;
 
-   unsigned size = lima_tex_list_size + lima_tex->num_samplers * lima_tex_desc_size;
+   unsigned size = lima_tex_list_size;
+   for (int i = 0; i < lima_tex->num_samplers; i++) {
+      struct lima_sampler_view *texture = lima_sampler_view(lima_tex->textures[i]);
+      size += lima_calc_tex_desc_size(texture);
+   }
+
    uint32_t *descs =
       lima_ctx_buff_alloc(ctx, lima_ctx_buff_pp_tex_desc, size, true);
 
+   off_t offset = lima_tex_list_size;
    for (int i = 0; i < lima_tex->num_samplers; i++) {
-      off_t offset = lima_tex_desc_size * i + lima_tex_list_size;
       struct lima_sampler_state *sampler = lima_sampler_state(lima_tex->samplers[i]);
       struct lima_sampler_view *texture = lima_sampler_view(lima_tex->textures[i]);
+      unsigned desc_size = lima_calc_tex_desc_size(texture);
 
       descs[i] = lima_ctx_buff_va(ctx, lima_ctx_buff_pp_tex_desc,
                                   LIMA_CTX_BUFF_SUBMIT_PP) + offset;
-      lima_update_tex_desc(ctx, sampler, texture, (void *)descs + offset);
+      lima_update_tex_desc(ctx, sampler, texture, (void *)descs + offset, desc_size);
+      offset += desc_size;
    }
 
    lima_dump_command_stream_print(
index 14cf466ecd611e507480816fe00e3e720d9516b6..d91c8bb00c8a2f03216c42fa604b7e0b13695592 100644 (file)
 #ifndef H_LIMA_TEXTURE
 #define H_LIMA_TEXTURE
 
-#define lima_tex_desc_size 64
+#define lima_min_tex_desc_size 64
 
-void lima_texture_desc_set_res(struct lima_context *ctx, uint32_t *desc,
+typedef struct __attribute__((__packed__)) {
+   /* Word 0 */
+   uint32_t format : 6;
+   uint32_t flag1: 1;
+   uint32_t swap_r_b: 1;
+   uint32_t unknown_0_1: 10;
+   uint32_t stride: 13;
+   uint32_t unknown_0_2: 1;
+
+   /* Word 1*/
+   uint32_t unknown_1_1: 10;
+   uint32_t texture_2d: 1;
+   uint32_t unknown_1_2: 13;
+   uint32_t miplevels: 4;
+   uint32_t unknown_1_3: 3;
+   uint32_t disable_mipmap: 1;
+
+   /* Word 2-3 */
+   uint32_t unknown_2_1: 8;
+   uint32_t has_stride: 1;
+   uint32_t min_mipfilter: 2; /* 0x3 for linear, 0x0 for neares */
+   uint32_t min_img_filter_nearest: 1;
+   uint32_t mag_img_filter_nearest: 1;
+   uint32_t wrap_s_clamp_to_edge: 1;
+   uint32_t wrap_s_clamp: 1;
+   uint32_t wrap_s_mirror_repeat: 1;
+   uint32_t wrap_t_clamp_to_edge: 1;
+   uint32_t wrap_t_clamp: 1;
+   uint32_t wrap_t_mirror_repeat: 1;
+   uint32_t unknown_2_2: 3;
+   uint32_t width: 13;
+   uint32_t height: 13;
+   uint32_t unknown_3_1: 1;
+   uint32_t unknown_3_2: 15;
+
+   /* Word 4 */
+   uint32_t unknown_4;
+
+   /* Word 5 */
+   uint32_t unknown_5;
+
+   /* Word 6-15 */
+   /* layout is in va[0] bit 13-14 */
+   /* VAs start in va[0] at bit 30, each VA is 26 bits (only MSBs are stored), stored
+    * linearly in memory */
+   union {
+      uint32_t va[0];
+      struct __attribute__((__packed__)) {
+         uint32_t unknown_6_1: 12;
+         uint32_t layout: 2;
+         uint32_t unknown_6_2: 10;
+         uint32_t unknown_6_3: 6;
+#define VA_BIT_OFFSET 30
+#define VA_BIT_SIZE 26
+         uint32_t va_0: VA_BIT_SIZE;
+         uint32_t va_0_1: 8;
+         uint32_t va_1_x[0];
+      } va_s;
+   };
+} lima_tex_desc;
+
+void lima_texture_desc_set_res(struct lima_context *ctx, lima_tex_desc *desc,
                                struct pipe_resource *prsc,
                                unsigned first_level, unsigned last_level);
 void lima_update_textures(struct lima_context *ctx);