Home | History | Annotate | Download | only in etnaviv
      1 /*
      2  * Copyright (c) 2012-2015 Etnaviv Project
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the "Software"),
      6  * to deal in the Software without restriction, including without limitation
      7  * the rights to use, copy, modify, merge, publish, distribute, sub license,
      8  * and/or sell copies of the Software, and to permit persons to whom the
      9  * Software is furnished to do so, subject to the following conditions:
     10  *
     11  * The above copyright notice and this permission notice (including the
     12  * next paragraph) shall be included in all copies or substantial portions
     13  * of the Software.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
     18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     21  * DEALINGS IN THE SOFTWARE.
     22  *
     23  * Authors:
     24  *    Wladimir J. van der Laan <laanwj (at) gmail.com>
     25  */
     26 
     27 #include "etnaviv_shader.h"
     28 
     29 #include "etnaviv_compiler.h"
     30 #include "etnaviv_context.h"
     31 #include "etnaviv_debug.h"
     32 #include "etnaviv_util.h"
     33 
     34 #include "util/u_math.h"
     35 #include "util/u_memory.h"
     36 
     37 /* Link vs and fs together: fill in shader_state from vs and fs
     38  * as this function is called every time a new fs or vs is bound, the goal is to
     39  * do little processing as possible here, and to precompute as much as possible in
     40  * the vs/fs shader_object.
     41  *
     42  * XXX we could cache the link result for a certain set of VS/PS; usually a pair
     43  * of VS and PS will be used together anyway.
     44  */
     45 static bool
     46 etna_link_shaders(struct etna_context *ctx, struct compiled_shader_state *cs,
     47                   const struct etna_shader *vs, const struct etna_shader *fs)
     48 {
     49    struct etna_shader_link_info link = { };
     50 
     51    assert(vs->processor == PIPE_SHADER_VERTEX);
     52    assert(fs->processor == PIPE_SHADER_FRAGMENT);
     53 
     54 #ifdef DEBUG
     55    if (DBG_ENABLED(ETNA_DBG_DUMP_SHADERS)) {
     56       etna_dump_shader(vs);
     57       etna_dump_shader(fs);
     58    }
     59 #endif
     60 
     61    if (etna_link_shader(&link, vs, fs)) {
     62       /* linking failed: some fs inputs do not have corresponding
     63        * vs outputs */
     64       assert(0);
     65 
     66       return false;
     67    }
     68 
     69    if (DBG_ENABLED(ETNA_DBG_LINKER_MSGS)) {
     70       debug_printf("link result:\n");
     71       debug_printf("  vs  -> fs  comps use     pa_attr\n");
     72 
     73       for (int idx = 0; idx < link.num_varyings; ++idx)
     74          debug_printf("  t%-2u -> t%-2u %-5.*s %u,%u,%u,%u 0x%08x\n",
     75                       link.varyings[idx].reg, idx + 1,
     76                       link.varyings[idx].num_components, "xyzw",
     77                       link.varyings[idx].use[0], link.varyings[idx].use[1],
     78                       link.varyings[idx].use[2], link.varyings[idx].use[3],
     79                       link.varyings[idx].pa_attributes);
     80    }
     81 
     82    /* set last_varying_2x flag if the last varying has 1 or 2 components */
     83    bool last_varying_2x = false;
     84    if (link.num_varyings > 0 && link.varyings[link.num_varyings - 1].num_components <= 2)
     85       last_varying_2x = true;
     86 
     87    cs->RA_CONTROL = VIVS_RA_CONTROL_UNK0 |
     88                     COND(last_varying_2x, VIVS_RA_CONTROL_LAST_VARYING_2X);
     89 
     90    cs->PA_ATTRIBUTE_ELEMENT_COUNT = VIVS_PA_ATTRIBUTE_ELEMENT_COUNT_COUNT(link.num_varyings);
     91    for (int idx = 0; idx < link.num_varyings; ++idx)
     92       cs->PA_SHADER_ATTRIBUTES[idx] = link.varyings[idx].pa_attributes;
     93 
     94    cs->VS_END_PC = vs->code_size / 4;
     95    cs->VS_OUTPUT_COUNT = 1 + link.num_varyings; /* position + varyings */
     96 
     97    /* vs outputs (varyings) */
     98    DEFINE_ETNA_BITARRAY(vs_output, 16, 8) = {0};
     99    int varid = 0;
    100    etna_bitarray_set(vs_output, 8, varid++, vs->vs_pos_out_reg);
    101    for (int idx = 0; idx < link.num_varyings; ++idx)
    102       etna_bitarray_set(vs_output, 8, varid++, link.varyings[idx].reg);
    103    if (vs->vs_pointsize_out_reg >= 0)
    104       etna_bitarray_set(vs_output, 8, varid++, vs->vs_pointsize_out_reg); /* pointsize is last */
    105 
    106    for (int idx = 0; idx < ARRAY_SIZE(cs->VS_OUTPUT); ++idx)
    107       cs->VS_OUTPUT[idx] = vs_output[idx];
    108 
    109    if (vs->vs_pointsize_out_reg != -1) {
    110       /* vertex shader outputs point coordinate, provide extra output and make
    111        * sure PA config is
    112        * not masked */
    113       cs->PA_CONFIG = ~0;
    114       cs->VS_OUTPUT_COUNT_PSIZE = cs->VS_OUTPUT_COUNT + 1;
    115    } else {
    116       /* vertex shader does not output point coordinate, make sure thate
    117        * POINT_SIZE_ENABLE is masked
    118        * and no extra output is given */
    119       cs->PA_CONFIG = ~VIVS_PA_CONFIG_POINT_SIZE_ENABLE;
    120       cs->VS_OUTPUT_COUNT_PSIZE = cs->VS_OUTPUT_COUNT;
    121    }
    122 
    123    cs->VS_LOAD_BALANCING = vs->vs_load_balancing;
    124    cs->VS_START_PC = 0;
    125 
    126    cs->PS_END_PC = fs->code_size / 4;
    127    cs->PS_OUTPUT_REG = fs->ps_color_out_reg;
    128    cs->PS_INPUT_COUNT =
    129       VIVS_PS_INPUT_COUNT_COUNT(link.num_varyings + 1) | /* Number of inputs plus position */
    130       VIVS_PS_INPUT_COUNT_UNK8(fs->input_count_unk8);
    131    cs->PS_TEMP_REGISTER_CONTROL =
    132       VIVS_PS_TEMP_REGISTER_CONTROL_NUM_TEMPS(MAX2(fs->num_temps, link.num_varyings + 1));
    133    cs->PS_CONTROL = VIVS_PS_CONTROL_UNK1; /* XXX when can we set BYPASS? */
    134    cs->PS_START_PC = 0;
    135 
    136    /* Precompute PS_INPUT_COUNT and TEMP_REGISTER_CONTROL in the case of MSAA
    137     * mode, avoids some fumbling in sync_context. */
    138    cs->PS_INPUT_COUNT_MSAA =
    139       VIVS_PS_INPUT_COUNT_COUNT(link.num_varyings + 2) | /* MSAA adds another input */
    140       VIVS_PS_INPUT_COUNT_UNK8(fs->input_count_unk8);
    141    cs->PS_TEMP_REGISTER_CONTROL_MSAA =
    142       VIVS_PS_TEMP_REGISTER_CONTROL_NUM_TEMPS(MAX2(fs->num_temps, link.num_varyings + 2));
    143 
    144    uint32_t total_components = 0;
    145    DEFINE_ETNA_BITARRAY(num_components, ETNA_NUM_VARYINGS, 4) = {0};
    146    DEFINE_ETNA_BITARRAY(component_use, 4 * ETNA_NUM_VARYINGS, 2) = {0};
    147    for (int idx = 0; idx < link.num_varyings; ++idx) {
    148       const struct etna_varying *varying = &link.varyings[idx];
    149 
    150       etna_bitarray_set(num_components, 4, idx, varying->num_components);
    151       for (int comp = 0; comp < varying->num_components; ++comp) {
    152          etna_bitarray_set(component_use, 2, total_components, varying->use[comp]);
    153          total_components += 1;
    154       }
    155    }
    156 
    157    cs->GL_VARYING_TOTAL_COMPONENTS =
    158       VIVS_GL_VARYING_TOTAL_COMPONENTS_NUM(align(total_components, 2));
    159    cs->GL_VARYING_NUM_COMPONENTS = num_components[0];
    160    cs->GL_VARYING_COMPONENT_USE[0] = component_use[0];
    161    cs->GL_VARYING_COMPONENT_USE[1] = component_use[1];
    162 
    163    /* reference instruction memory */
    164    cs->vs_inst_mem_size = vs->code_size;
    165    cs->VS_INST_MEM = vs->code;
    166    cs->ps_inst_mem_size = fs->code_size;
    167    cs->PS_INST_MEM = fs->code;
    168 
    169    return true;
    170 }
    171 
    172 bool
    173 etna_shader_link(struct etna_context *ctx)
    174 {
    175    if (!ctx->vs || !ctx->fs)
    176       return false;
    177 
    178    /* re-link vs and fs if needed */
    179    return etna_link_shaders(ctx, &ctx->shader_state, ctx->vs, ctx->fs);
    180 }
    181 
    182 static bool
    183 etna_shader_update_vs_inputs(struct etna_context *ctx,
    184                              struct compiled_shader_state *cs,
    185                              const struct etna_shader *vs,
    186                              const struct compiled_vertex_elements_state *ves)
    187 {
    188    unsigned num_temps, cur_temp, num_vs_inputs;
    189 
    190    if (!vs)
    191       return false;
    192 
    193    /* Number of vertex elements determines number of VS inputs. Otherwise,
    194     * the GPU crashes. Allocate any unused vertex elements to VS temporary
    195     * registers. */
    196    num_vs_inputs = MAX2(ves->num_elements, vs->infile.num_reg);
    197    if (num_vs_inputs != ves->num_elements) {
    198       BUG("Number of elements %u does not match the number of VS inputs %zu",
    199           ctx->vertex_elements->num_elements, ctx->vs->infile.num_reg);
    200       return false;
    201    }
    202 
    203    cur_temp = vs->num_temps;
    204    num_temps = num_vs_inputs - vs->infile.num_reg + cur_temp;
    205 
    206    cs->VS_INPUT_COUNT = VIVS_VS_INPUT_COUNT_COUNT(num_vs_inputs) |
    207                         VIVS_VS_INPUT_COUNT_UNK8(vs->input_count_unk8);
    208    cs->VS_TEMP_REGISTER_CONTROL =
    209       VIVS_VS_TEMP_REGISTER_CONTROL_NUM_TEMPS(num_temps);
    210 
    211    /* vs inputs (attributes) */
    212    DEFINE_ETNA_BITARRAY(vs_input, 16, 8) = {0};
    213    for (int idx = 0; idx < num_vs_inputs; ++idx) {
    214       if (idx < vs->infile.num_reg)
    215          etna_bitarray_set(vs_input, 8, idx, vs->infile.reg[idx].reg);
    216       else
    217          etna_bitarray_set(vs_input, 8, idx, cur_temp++);
    218    }
    219 
    220    for (int idx = 0; idx < ARRAY_SIZE(cs->VS_INPUT); ++idx)
    221       cs->VS_INPUT[idx] = vs_input[idx];
    222 
    223    return true;
    224 }
    225 
    226 bool
    227 etna_shader_update_vertex(struct etna_context *ctx)
    228 {
    229    return etna_shader_update_vs_inputs(ctx, &ctx->shader_state, ctx->vs,
    230                                        ctx->vertex_elements);
    231 }
    232 
    233 static void *
    234 etna_create_shader_state(struct pipe_context *pctx,
    235                          const struct pipe_shader_state *pss)
    236 {
    237    struct etna_context *ctx = etna_context(pctx);
    238 
    239    return etna_compile_shader(&ctx->specs, pss->tokens);
    240 }
    241 
    242 static void
    243 etna_delete_shader_state(struct pipe_context *pctx, void *ss)
    244 {
    245    etna_destroy_shader(ss);
    246 }
    247 
    248 static void
    249 etna_bind_fs_state(struct pipe_context *pctx, void *fss_)
    250 {
    251    struct etna_context *ctx = etna_context(pctx);
    252    struct etna_shader *fss = fss_;
    253 
    254    if (ctx->fs == fss) /* skip if already bound */
    255       return;
    256 
    257    assert(fss == NULL || fss->processor == PIPE_SHADER_FRAGMENT);
    258    ctx->fs = fss;
    259    ctx->dirty |= ETNA_DIRTY_SHADER;
    260 }
    261 
    262 static void
    263 etna_bind_vs_state(struct pipe_context *pctx, void *vss_)
    264 {
    265    struct etna_context *ctx = etna_context(pctx);
    266    struct etna_shader *vss = vss_;
    267 
    268    if (ctx->vs == vss) /* skip if already bound */
    269       return;
    270 
    271    assert(vss == NULL || vss->processor == PIPE_SHADER_VERTEX);
    272    ctx->vs = vss;
    273    ctx->dirty |= ETNA_DIRTY_SHADER;
    274 }
    275 
    276 void
    277 etna_shader_init(struct pipe_context *pctx)
    278 {
    279    pctx->create_fs_state = etna_create_shader_state;
    280    pctx->bind_fs_state = etna_bind_fs_state;
    281    pctx->delete_fs_state = etna_delete_shader_state;
    282    pctx->create_vs_state = etna_create_shader_state;
    283    pctx->bind_vs_state = etna_bind_vs_state;
    284    pctx->delete_vs_state = etna_delete_shader_state;
    285 }
    286