vc4: Add support for texture cube maps.
authorEric Anholt <eric@anholt.net>
Sun, 28 Sep 2014 01:57:20 +0000 (18:57 -0700)
committerEric Anholt <eric@anholt.net>
Mon, 29 Sep 2014 18:29:28 +0000 (11:29 -0700)
It's not passing some of the piglit tests, because it looks like at small
miplevels some contents from surrounding faces are getting filtered in at
the corners.  It does get 7 new tests passing.

src/gallium/drivers/vc4/vc4_program.c
src/gallium/drivers/vc4/vc4_qir.h
src/gallium/drivers/vc4/vc4_resource.c
src/gallium/drivers/vc4/vc4_resource.h
src/gallium/drivers/vc4/vc4_simulator_validate.c

index a5011039be2be5d441d7bfb06a31cdbe50d96301..4c97ddfd26ff9972215048651220f621877153e1 100644 (file)
@@ -489,6 +489,7 @@ tgsi_to_qir_tex(struct vc4_compile *c,
 
         struct qreg s = src[0 * 4 + 0];
         struct qreg t = src[0 * 4 + 1];
+        struct qreg r = src[0 * 4 + 2];
         uint32_t unit = tgsi_inst->Src[1].Register.Index;
 
         struct qreg proj = c->undef;
@@ -498,6 +499,14 @@ tgsi_to_qir_tex(struct vc4_compile *c,
                 t = qir_FMUL(c, t, proj);
         }
 
+        struct qreg texture_u[] = {
+                add_uniform(c, QUNIFORM_TEXTURE_CONFIG_P0, unit),
+                add_uniform(c, QUNIFORM_TEXTURE_CONFIG_P1, unit),
+                add_uniform(c, QUNIFORM_CONSTANT, 0),
+                add_uniform(c, QUNIFORM_CONSTANT, 0),
+        };
+        uint32_t next_texture_u = 0;
+
         /* There is no native support for GL texture rectangle coordinates, so
          * we have to rescale from ([0, width], [0, height]) to ([0, 1], [0,
          * 1]).
@@ -512,19 +521,26 @@ tgsi_to_qir_tex(struct vc4_compile *c,
                              get_temp_for_uniform(c,
                                                   QUNIFORM_TEXRECT_SCALE_Y,
                                                   unit));
-        }
+        } else if (tgsi_inst->Texture.Texture == TGSI_TEXTURE_CUBE ||
+                   tgsi_inst->Texture.Texture == TGSI_TEXTURE_SHADOWCUBE) {
+                struct qreg ma = qir_FMAXABS(c, qir_FMAXABS(c, s, t), r);
+                struct qreg rcp_ma = qir_RCP(c, ma);
+                s = qir_FMUL(c, s, rcp_ma);
+                t = qir_FMUL(c, t, rcp_ma);
+                r = qir_FMUL(c, r, rcp_ma);
 
-        qir_TEX_T(c, t, add_uniform(c, QUNIFORM_TEXTURE_CONFIG_P0, unit));
+                texture_u[2] = add_uniform(c, QUNIFORM_TEXTURE_CONFIG_P2, unit);
 
-        struct qreg sampler_p1 = add_uniform(c, QUNIFORM_TEXTURE_CONFIG_P1,
-                                             unit);
-        if (tgsi_inst->Instruction.Opcode == TGSI_OPCODE_TXB) {
-                qir_TEX_B(c, src[0 * 4 + 3], sampler_p1);
-                qir_TEX_S(c, s, add_uniform(c, QUNIFORM_CONSTANT, 0));
-        } else {
-                qir_TEX_S(c, s, sampler_p1);
+                qir_TEX_R(c, r, texture_u[next_texture_u++]);
         }
 
+        qir_TEX_T(c, t, texture_u[next_texture_u++]);
+
+        if (tgsi_inst->Instruction.Opcode == TGSI_OPCODE_TXB)
+                qir_TEX_B(c, src[0 * 4 + 3], texture_u[next_texture_u++]);
+
+        qir_TEX_S(c, s, texture_u[next_texture_u++]);
+
         c->num_texture_samples++;
         struct qreg r4 = qir_TEX_RESULT(c);
 
@@ -1890,8 +1906,11 @@ write_texture_p0(struct vc4_context *vc4,
         struct pipe_sampler_view *texture = texstate->textures[unit];
         struct vc4_resource *rsc = vc4_resource(texture->texture);
 
+        bool is_cube = texture->target == PIPE_TEXTURE_CUBE;
+
         cl_reloc(vc4, &vc4->uniforms, rsc->bo,
                  rsc->slices[0].offset | texture->u.tex.last_level |
+                 is_cube << 9 |
                  ((rsc->vc4_format & 7) << 4));
 }
 
@@ -1924,6 +1943,17 @@ write_texture_p1(struct vc4_context *vc4,
                (translate_wrap(sampler->wrap_s) << 0));
 }
 
+static void
+write_texture_p2(struct vc4_context *vc4,
+                 struct vc4_texture_stateobj *texstate,
+                 uint32_t unit)
+{
+        struct pipe_sampler_view *texture = texstate->textures[unit];
+        struct vc4_resource *rsc = vc4_resource(texture->texture);
+
+        cl_u32(&vc4->uniforms, (1 << 30) | rsc->cube_map_stride);
+}
+
 static uint32_t
 get_texrect_scale(struct vc4_texture_stateobj *texstate,
                   enum quniform_contents contents,
@@ -1983,6 +2013,10 @@ vc4_write_uniforms(struct vc4_context *vc4, struct vc4_compiled_shader *shader,
                         write_texture_p1(vc4, texstate, uinfo->data[i]);
                         break;
 
+                case QUNIFORM_TEXTURE_CONFIG_P2:
+                        write_texture_p2(vc4, texstate, uinfo->data[i]);
+                        break;
+
                 case QUNIFORM_TEXRECT_SCALE_X:
                 case QUNIFORM_TEXRECT_SCALE_Y:
                         cl_u32(&vc4->uniforms,
index f771c425415549ef2c19f4a968802492d047a644..0d490ff9ef585b240d64161227734280b5a1e19f 100644 (file)
@@ -201,6 +201,9 @@ enum quniform_contents {
          */
         QUNIFORM_TEXTURE_CONFIG_P1,
 
+        /** A reference to a texture config parameter 2 cubemap stride uniform */
+        QUNIFORM_TEXTURE_CONFIG_P2,
+
         QUNIFORM_TEXRECT_SCALE_X,
         QUNIFORM_TEXRECT_SCALE_Y,
 
index 3fb0b99b7d5d96e54ab2df96d3af68ce1741a3ca..239443e7a7d47e24e40aec6686b4195de1f3ff53 100644 (file)
@@ -45,7 +45,8 @@ vc4_resource_transfer_unmap(struct pipe_context *pctx,
 
         if (trans->map) {
                 if (ptrans->usage & PIPE_TRANSFER_WRITE) {
-                        vc4_store_tiled_image(rsc->bo->map + slice->offset,
+                        vc4_store_tiled_image(rsc->bo->map + slice->offset +
+                                              ptrans->box.z * rsc->cube_map_stride,
                                               slice->stride,
                                               trans->map, ptrans->stride,
                                               slice->tiling, rsc->cpp,
@@ -137,7 +138,8 @@ vc4_resource_transfer_map(struct pipe_context *pctx,
                 trans->map = malloc(ptrans->stride * ptrans->box.height);
                 if (usage & PIPE_TRANSFER_READ) {
                         vc4_load_tiled_image(trans->map, ptrans->stride,
-                                             buf + slice->offset,
+                                             buf + slice->offset +
+                                             box->z * rsc->cube_map_stride,
                                              slice->stride,
                                              slice->tiling, rsc->cpp,
                                              &ptrans->box);
@@ -152,7 +154,7 @@ vc4_resource_transfer_map(struct pipe_context *pctx,
                 return buf + slice->offset +
                         box->y / util_format_get_blockheight(format) * ptrans->stride +
                         box->x / util_format_get_blockwidth(format) * rsc->cpp +
-                        box->z * slice->size;
+                        box->z * rsc->cube_map_stride;
         }
 
 
@@ -196,7 +198,6 @@ vc4_setup_slices(struct vc4_resource *rsc)
         struct pipe_resource *prsc = &rsc->base.b;
         uint32_t width = prsc->width0;
         uint32_t height = prsc->height0;
-        uint32_t depth = prsc->depth0;
         uint32_t offset = 0;
         uint32_t utile_w = vc4_utile_width(rsc->cpp);
         uint32_t utile_h = vc4_utile_height(rsc->cpp);
@@ -228,10 +229,7 @@ vc4_setup_slices(struct vc4_resource *rsc)
                 slice->stride = level_width * rsc->cpp;
                 slice->size = level_height * slice->stride;
 
-                /* Note, since we have cubes but no 3D, depth is invariant
-                 * with miplevel.
-                 */
-                offset += slice->size * depth;
+                offset += slice->size;
         }
 
         /* The texture base pointer that has to point to level 0 doesn't have
@@ -244,6 +242,14 @@ vc4_setup_slices(struct vc4_resource *rsc)
                 for (int i = 0; i <= prsc->last_level; i++)
                         rsc->slices[i].offset += page_align_offset;
         }
+
+        /* Cube map faces appear as whole miptrees at a page-aligned offset
+         * from the first face's miptree.
+         */
+        if (prsc->target == PIPE_TEXTURE_CUBE) {
+                rsc->cube_map_stride = align(rsc->slices[0].offset +
+                                             rsc->slices[0].size, 4096);
+        }
 }
 
 static struct vc4_resource *
@@ -306,7 +312,8 @@ vc4_resource_create(struct pipe_screen *pscreen,
 
         rsc->bo = vc4_bo_alloc(vc4_screen(pscreen),
                                rsc->slices[0].offset +
-                               rsc->slices[0].size * prsc->depth0,
+                               rsc->slices[0].size +
+                               rsc->cube_map_stride * (prsc->array_size - 1),
                                "resource");
         if (!rsc->bo)
                 goto fail;
index 78869295774f71abd6f15f1b4f7ef751fa2411cf..01f481d15c4a42c37bc33243b9874465ec8f5314 100644 (file)
@@ -56,6 +56,7 @@ struct vc4_resource {
         struct u_resource base;
         struct vc4_bo *bo;
         struct vc4_resource_slice slices[VC4_MAX_MIP_LEVELS];
+        uint32_t cube_map_stride;
         int cpp;
         bool tiled;
         /** One of VC4_TEXTURE_TYPE_* */
index 1b63bf334f27f3991fa4f1648d6f2b012326da68..99f01b238bdbbbbc4b044c729cbde6284046db5c 100644 (file)
@@ -751,6 +751,10 @@ reloc_tex(struct exec_info *exec,
        struct drm_gem_cma_object *tex;
        uint32_t p0 = *(uint32_t *)(uniform_data_u + sample->p_offset[0]);
        uint32_t p1 = *(uint32_t *)(uniform_data_u + sample->p_offset[1]);
+       uint32_t p2 = (sample->p_offset[2] != ~0 ?
+                      *(uint32_t *)(uniform_data_u + sample->p_offset[2]) : 0);
+       uint32_t p3 = (sample->p_offset[3] != ~0 ?
+                      *(uint32_t *)(uniform_data_u + sample->p_offset[3]) : 0);
        uint32_t *validated_p0 = exec->uniforms_v + sample->p_offset[0];
        uint32_t offset = p0 & ~0xfff;
        uint32_t miplevels = (p0 & 15);
@@ -758,6 +762,7 @@ reloc_tex(struct exec_info *exec,
        uint32_t height = (p1 >> 20) & 2047;
        uint32_t cpp, tiling_format, utile_w, utile_h;
        uint32_t i;
+       uint32_t cube_map_stride = 0;
        enum vc4_texture_data_type type;
 
        if (width == 0)
@@ -766,8 +771,20 @@ reloc_tex(struct exec_info *exec,
                height = 2048;
 
        if (p0 & (1 << 9)) {
-               DRM_ERROR("Cube maps unsupported\n");
-               return false;
+               if ((p2 & (3 << 30)) == (1 << 30))
+                       cube_map_stride = p2 & 0x3ffff000;
+               if ((p3 & (3 << 30)) == (1 << 30)) {
+                       if (cube_map_stride) {
+                               DRM_ERROR("Cube map stride set twice\n");
+                               return -EINVAL;
+                       }
+
+                       cube_map_stride = p3 & 0x3ffff000;
+               }
+               if (!cube_map_stride) {
+                       DRM_ERROR("Cube map stride not set\n");
+                       return -EINVAL;
+               }
        }
 
        type = ((p0 >> 4) & 15) | ((p1 >> 31) << 4);
@@ -816,8 +833,8 @@ reloc_tex(struct exec_info *exec,
        if (!vc4_use_bo(exec, texture_handle_index, VC4_MODE_RENDER, &tex))
                return false;
 
-       if (!check_tex_size(exec, tex, offset, tiling_format,
-                           width, height, cpp)) {
+       if (!check_tex_size(exec, tex, offset + cube_map_stride * 5,
+                           tiling_format, width, height, cpp)) {
                return false;
        }