101e04c3fSmrg/*
201e04c3fSmrg * Copyright © 2016-2018 Broadcom
301e04c3fSmrg *
401e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a
501e04c3fSmrg * copy of this software and associated documentation files (the "Software"),
601e04c3fSmrg * to deal in the Software without restriction, including without limitation
701e04c3fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
801e04c3fSmrg * and/or sell copies of the Software, and to permit persons to whom the
901e04c3fSmrg * Software is furnished to do so, subject to the following conditions:
1001e04c3fSmrg *
1101e04c3fSmrg * The above copyright notice and this permission notice (including the next
1201e04c3fSmrg * paragraph) shall be included in all copies or substantial portions of the
1301e04c3fSmrg * Software.
1401e04c3fSmrg *
1501e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1601e04c3fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1701e04c3fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1801e04c3fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1901e04c3fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2001e04c3fSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
2101e04c3fSmrg * IN THE SOFTWARE.
2201e04c3fSmrg */
2301e04c3fSmrg
2401e04c3fSmrg#include "v3d_compiler.h"
2501e04c3fSmrg
2601e04c3fSmrg/* We don't do any address packing. */
2701e04c3fSmrg#define __gen_user_data void
2801e04c3fSmrg#define __gen_address_type uint32_t
2901e04c3fSmrg#define __gen_address_offset(reloc) (*reloc)
3001e04c3fSmrg#define __gen_emit_reloc(cl, reloc)
3101e04c3fSmrg#include "cle/v3d_packet_v33_pack.h"
3201e04c3fSmrg
3301e04c3fSmrgvoid
3401e04c3fSmrgv3d33_vir_emit_tex(struct v3d_compile *c, nir_tex_instr *instr)
3501e04c3fSmrg{
367ec681f3Smrg        /* FIXME: We don't bother implementing pipelining for texture reads
377ec681f3Smrg         * for any pre 4.x hardware. It should be straight forward to do but
387ec681f3Smrg         * we are not really testing or even targetting this hardware at
397ec681f3Smrg         * present.
407ec681f3Smrg         */
417ec681f3Smrg        ntq_flush_tmu(c);
427ec681f3Smrg
4301e04c3fSmrg        unsigned unit = instr->texture_index;
4401e04c3fSmrg
4501e04c3fSmrg        struct V3D33_TEXTURE_UNIFORM_PARAMETER_0_CFG_MODE1 p0_unpacked = {
4601e04c3fSmrg                V3D33_TEXTURE_UNIFORM_PARAMETER_0_CFG_MODE1_header,
4701e04c3fSmrg
4801e04c3fSmrg                .fetch_sample_mode = instr->op == nir_texop_txf,
4901e04c3fSmrg        };
5001e04c3fSmrg
5101e04c3fSmrg        struct V3D33_TEXTURE_UNIFORM_PARAMETER_1_CFG_MODE1 p1_unpacked = {
5201e04c3fSmrg        };
5301e04c3fSmrg
5401e04c3fSmrg        switch (instr->sampler_dim) {
5501e04c3fSmrg        case GLSL_SAMPLER_DIM_1D:
5601e04c3fSmrg                if (instr->is_array)
5701e04c3fSmrg                        p0_unpacked.lookup_type = TEXTURE_1D_ARRAY;
5801e04c3fSmrg                else
5901e04c3fSmrg                        p0_unpacked.lookup_type = TEXTURE_1D;
6001e04c3fSmrg                break;
6101e04c3fSmrg        case GLSL_SAMPLER_DIM_2D:
6201e04c3fSmrg        case GLSL_SAMPLER_DIM_RECT:
6301e04c3fSmrg                if (instr->is_array)
6401e04c3fSmrg                        p0_unpacked.lookup_type = TEXTURE_2D_ARRAY;
6501e04c3fSmrg                else
6601e04c3fSmrg                        p0_unpacked.lookup_type = TEXTURE_2D;
6701e04c3fSmrg                break;
6801e04c3fSmrg        case GLSL_SAMPLER_DIM_3D:
6901e04c3fSmrg                p0_unpacked.lookup_type = TEXTURE_3D;
7001e04c3fSmrg                break;
7101e04c3fSmrg        case GLSL_SAMPLER_DIM_CUBE:
7201e04c3fSmrg                p0_unpacked.lookup_type = TEXTURE_CUBE_MAP;
7301e04c3fSmrg                break;
7401e04c3fSmrg        default:
7501e04c3fSmrg                unreachable("Bad sampler type");
7601e04c3fSmrg        }
7701e04c3fSmrg
7801e04c3fSmrg        struct qreg coords[5];
7901e04c3fSmrg        int next_coord = 0;
8001e04c3fSmrg        for (unsigned i = 0; i < instr->num_srcs; i++) {
8101e04c3fSmrg                switch (instr->src[i].src_type) {
8201e04c3fSmrg                case nir_tex_src_coord:
8301e04c3fSmrg                        for (int j = 0; j < instr->coord_components; j++) {
8401e04c3fSmrg                                coords[next_coord++] =
8501e04c3fSmrg                                        ntq_get_src(c, instr->src[i].src, j);
8601e04c3fSmrg                        }
8701e04c3fSmrg                        if (instr->coord_components < 2)
8801e04c3fSmrg                                coords[next_coord++] = vir_uniform_f(c, 0.5);
8901e04c3fSmrg                        break;
9001e04c3fSmrg                case nir_tex_src_bias:
9101e04c3fSmrg                        coords[next_coord++] =
9201e04c3fSmrg                                ntq_get_src(c, instr->src[i].src, 0);
9301e04c3fSmrg
9401e04c3fSmrg                        p0_unpacked.bias_supplied = true;
9501e04c3fSmrg                        break;
9601e04c3fSmrg                case nir_tex_src_lod:
9701e04c3fSmrg                        coords[next_coord++] =
9801e04c3fSmrg                                vir_FADD(c,
9901e04c3fSmrg                                         ntq_get_src(c, instr->src[i].src, 0),
10001e04c3fSmrg                                         vir_uniform(c, QUNIFORM_TEXTURE_FIRST_LEVEL,
10101e04c3fSmrg                                                     unit));
10201e04c3fSmrg
10301e04c3fSmrg                        if (instr->op != nir_texop_txf &&
10401e04c3fSmrg                            instr->op != nir_texop_tg4) {
10501e04c3fSmrg                                p0_unpacked.disable_autolod_use_bias_only = true;
10601e04c3fSmrg                        }
10701e04c3fSmrg                        break;
10801e04c3fSmrg                case nir_tex_src_comparator:
10901e04c3fSmrg                        coords[next_coord++] =
11001e04c3fSmrg                                ntq_get_src(c, instr->src[i].src, 0);
11101e04c3fSmrg
11201e04c3fSmrg                        p0_unpacked.shadow = true;
11301e04c3fSmrg                        break;
11401e04c3fSmrg
11501e04c3fSmrg                case nir_tex_src_offset: {
11601e04c3fSmrg                        p0_unpacked.texel_offset_for_s_coordinate =
117ed98bd31Smaya                                nir_src_comp_as_int(instr->src[i].src, 0);
11801e04c3fSmrg
11901e04c3fSmrg                        if (instr->coord_components >= 2)
12001e04c3fSmrg                                p0_unpacked.texel_offset_for_t_coordinate =
121ed98bd31Smaya                                        nir_src_comp_as_int(instr->src[i].src, 1);
12201e04c3fSmrg
12301e04c3fSmrg                        if (instr->coord_components >= 3)
12401e04c3fSmrg                                p0_unpacked.texel_offset_for_r_coordinate =
125ed98bd31Smaya                                        nir_src_comp_as_int(instr->src[i].src, 2);
12601e04c3fSmrg                        break;
12701e04c3fSmrg                }
12801e04c3fSmrg
12901e04c3fSmrg                default:
13001e04c3fSmrg                        unreachable("unknown texture source");
13101e04c3fSmrg                }
13201e04c3fSmrg        }
13301e04c3fSmrg
13401e04c3fSmrg        /* Limit the number of channels returned to both how many the NIR
13501e04c3fSmrg         * instruction writes and how many the instruction could produce.
13601e04c3fSmrg         */
13701e04c3fSmrg        p1_unpacked.return_words_of_texture_data =
1387ec681f3Smrg                instr->dest.is_ssa ?
1397ec681f3Smrg                nir_ssa_def_components_read(&instr->dest.ssa) :
1407ec681f3Smrg                (1 << instr->dest.reg.reg->num_components) - 1;
14101e04c3fSmrg
14201e04c3fSmrg        uint32_t p0_packed;
14301e04c3fSmrg        V3D33_TEXTURE_UNIFORM_PARAMETER_0_CFG_MODE1_pack(NULL,
14401e04c3fSmrg                                                         (uint8_t *)&p0_packed,
14501e04c3fSmrg                                                         &p0_unpacked);
14601e04c3fSmrg
14701e04c3fSmrg        uint32_t p1_packed;
14801e04c3fSmrg        V3D33_TEXTURE_UNIFORM_PARAMETER_1_CFG_MODE1_pack(NULL,
14901e04c3fSmrg                                                         (uint8_t *)&p1_packed,
15001e04c3fSmrg                                                         &p1_unpacked);
15101e04c3fSmrg        /* Load unit number into the address field, which will be be used by
15201e04c3fSmrg         * the driver to decide which texture to put in the actual address
15301e04c3fSmrg         * field.
15401e04c3fSmrg         */
15501e04c3fSmrg        p1_packed |= unit << 5;
15601e04c3fSmrg
15701e04c3fSmrg        /* There is no native support for GL texture rectangle coordinates, so
15801e04c3fSmrg         * we have to rescale from ([0, width], [0, height]) to ([0, 1], [0,
15901e04c3fSmrg         * 1]).
16001e04c3fSmrg         */
16101e04c3fSmrg        if (instr->sampler_dim == GLSL_SAMPLER_DIM_RECT) {
16201e04c3fSmrg                coords[0] = vir_FMUL(c, coords[0],
16301e04c3fSmrg                                     vir_uniform(c, QUNIFORM_TEXRECT_SCALE_X,
16401e04c3fSmrg                                                 unit));
16501e04c3fSmrg                coords[1] = vir_FMUL(c, coords[1],
16601e04c3fSmrg                                     vir_uniform(c, QUNIFORM_TEXRECT_SCALE_Y,
16701e04c3fSmrg                                                 unit));
16801e04c3fSmrg        }
16901e04c3fSmrg
170ed98bd31Smaya        int texture_u[] = {
171ed98bd31Smaya                vir_get_uniform_index(c, QUNIFORM_TEXTURE_CONFIG_P0_0 + unit, p0_packed),
172ed98bd31Smaya                vir_get_uniform_index(c, QUNIFORM_TEXTURE_CONFIG_P1, p1_packed),
17301e04c3fSmrg        };
17401e04c3fSmrg
17501e04c3fSmrg        for (int i = 0; i < next_coord; i++) {
17601e04c3fSmrg                struct qreg dst;
17701e04c3fSmrg
17801e04c3fSmrg                if (i == next_coord - 1)
17901e04c3fSmrg                        dst = vir_reg(QFILE_MAGIC, V3D_QPU_WADDR_TMUL);
18001e04c3fSmrg                else
18101e04c3fSmrg                        dst = vir_reg(QFILE_MAGIC, V3D_QPU_WADDR_TMU);
18201e04c3fSmrg
18301e04c3fSmrg                struct qinst *tmu = vir_MOV_dest(c, dst, coords[i]);
18401e04c3fSmrg
185ed98bd31Smaya                if (i < 2)
186ed98bd31Smaya                        tmu->uniform = texture_u[i];
18701e04c3fSmrg        }
18801e04c3fSmrg
18901e04c3fSmrg        vir_emit_thrsw(c);
19001e04c3fSmrg
19101e04c3fSmrg        for (int i = 0; i < 4; i++) {
19201e04c3fSmrg                if (p1_unpacked.return_words_of_texture_data & (1 << i))
193ed98bd31Smaya                        ntq_store_dest(c, &instr->dest, i, vir_LDTMU(c));
19401e04c3fSmrg        }
19501e04c3fSmrg}
196