From 730267eb23b418637c78662a77de0a93af91be35 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Sat, 27 Sep 2014 18:57:20 -0700 Subject: vc4: Add support for texture cube maps. 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 | 52 ++++++++++++++++++++---- src/gallium/drivers/vc4/vc4_qir.h | 3 ++ src/gallium/drivers/vc4/vc4_resource.c | 25 ++++++++---- src/gallium/drivers/vc4/vc4_resource.h | 1 + src/gallium/drivers/vc4/vc4_simulator_validate.c | 25 ++++++++++-- 5 files changed, 84 insertions(+), 22 deletions(-) diff --git a/src/gallium/drivers/vc4/vc4_program.c b/src/gallium/drivers/vc4/vc4_program.c index a5011039be2..4c97ddfd26f 100644 --- a/src/gallium/drivers/vc4/vc4_program.c +++ b/src/gallium/drivers/vc4/vc4_program.c @@ -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, diff --git a/src/gallium/drivers/vc4/vc4_qir.h b/src/gallium/drivers/vc4/vc4_qir.h index f771c425415..0d490ff9ef5 100644 --- a/src/gallium/drivers/vc4/vc4_qir.h +++ b/src/gallium/drivers/vc4/vc4_qir.h @@ -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, diff --git a/src/gallium/drivers/vc4/vc4_resource.c b/src/gallium/drivers/vc4/vc4_resource.c index 3fb0b99b7d5..239443e7a7d 100644 --- a/src/gallium/drivers/vc4/vc4_resource.c +++ b/src/gallium/drivers/vc4/vc4_resource.c @@ -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; diff --git a/src/gallium/drivers/vc4/vc4_resource.h b/src/gallium/drivers/vc4/vc4_resource.h index 78869295774..01f481d15c4 100644 --- a/src/gallium/drivers/vc4/vc4_resource.h +++ b/src/gallium/drivers/vc4/vc4_resource.h @@ -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_* */ diff --git a/src/gallium/drivers/vc4/vc4_simulator_validate.c b/src/gallium/drivers/vc4/vc4_simulator_validate.c index 1b63bf334f2..99f01b238bd 100644 --- a/src/gallium/drivers/vc4/vc4_simulator_validate.c +++ b/src/gallium/drivers/vc4/vc4_simulator_validate.c @@ -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; } -- cgit v1.2.3