Home | History | Annotate | Download | only in i965
      1 /*
      2  * Copyright  2013 Intel Corporation
      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, sublicense,
      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 next
     12  * paragraph) shall be included in all copies or substantial portions of the
     13  * 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 NONINFRINGEMENT.  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 
     24 
     25 #include "brw_vs.h"
     26 
     27 
     28 namespace brw {
     29 
     30 void
     31 vec4_vs_visitor::emit_prolog()
     32 {
     33 }
     34 
     35 
     36 dst_reg *
     37 vec4_vs_visitor::make_reg_for_system_value(int location)
     38 {
     39    /* VertexID is stored by the VF as the last vertex element, but
     40     * we don't represent it with a flag in inputs_read, so we call
     41     * it VERT_ATTRIB_MAX, which setup_attributes() picks up on.
     42     */
     43    dst_reg *reg = new(mem_ctx) dst_reg(ATTR, VERT_ATTRIB_MAX);
     44 
     45    switch (location) {
     46    case SYSTEM_VALUE_BASE_VERTEX:
     47       reg->writemask = WRITEMASK_X;
     48       vs_prog_data->uses_basevertex = true;
     49       break;
     50    case SYSTEM_VALUE_BASE_INSTANCE:
     51       reg->writemask = WRITEMASK_Y;
     52       vs_prog_data->uses_baseinstance = true;
     53       break;
     54    case SYSTEM_VALUE_VERTEX_ID:
     55    case SYSTEM_VALUE_VERTEX_ID_ZERO_BASE:
     56       reg->writemask = WRITEMASK_Z;
     57       vs_prog_data->uses_vertexid = true;
     58       break;
     59    case SYSTEM_VALUE_INSTANCE_ID:
     60       reg->writemask = WRITEMASK_W;
     61       vs_prog_data->uses_instanceid = true;
     62       break;
     63    case SYSTEM_VALUE_DRAW_ID:
     64       reg = new(mem_ctx) dst_reg(ATTR, VERT_ATTRIB_MAX + 1);
     65       reg->writemask = WRITEMASK_X;
     66       vs_prog_data->uses_drawid = true;
     67       break;
     68    default:
     69       unreachable("not reached");
     70    }
     71 
     72    return reg;
     73 }
     74 
     75 
     76 void
     77 vec4_vs_visitor::emit_urb_write_header(int mrf)
     78 {
     79    /* No need to do anything for VS; an implied write to this MRF will be
     80     * performed by VS_OPCODE_URB_WRITE.
     81     */
     82    (void) mrf;
     83 }
     84 
     85 
     86 vec4_instruction *
     87 vec4_vs_visitor::emit_urb_write_opcode(bool complete)
     88 {
     89    /* For VS, the URB writes end the thread. */
     90    if (complete) {
     91       if (INTEL_DEBUG & DEBUG_SHADER_TIME)
     92          emit_shader_time_end();
     93    }
     94 
     95    vec4_instruction *inst = emit(VS_OPCODE_URB_WRITE);
     96    inst->urb_write_flags = complete ?
     97       BRW_URB_WRITE_EOT_COMPLETE : BRW_URB_WRITE_NO_FLAGS;
     98 
     99    return inst;
    100 }
    101 
    102 
    103 void
    104 vec4_vs_visitor::emit_urb_slot(dst_reg reg, int varying)
    105 {
    106    reg.type = BRW_REGISTER_TYPE_F;
    107    output_reg[varying][0].type = reg.type;
    108 
    109    switch (varying) {
    110    case VARYING_SLOT_COL0:
    111    case VARYING_SLOT_COL1:
    112    case VARYING_SLOT_BFC0:
    113    case VARYING_SLOT_BFC1: {
    114       /* These built-in varyings are only supported in compatibility mode,
    115        * and we only support GS in core profile.  So, this must be a vertex
    116        * shader.
    117        */
    118       vec4_instruction *inst = emit_generic_urb_slot(reg, varying, 0);
    119       if (inst && key->clamp_vertex_color)
    120          inst->saturate = true;
    121       break;
    122    }
    123    default:
    124       return vec4_visitor::emit_urb_slot(reg, varying);
    125    }
    126 }
    127 
    128 
    129 void
    130 vec4_vs_visitor::emit_clip_distances(dst_reg reg, int offset)
    131 {
    132    /* From the GLSL 1.30 spec, section 7.1 (Vertex Shader Special Variables):
    133     *
    134     *     "If a linked set of shaders forming the vertex stage contains no
    135     *     static write to gl_ClipVertex or gl_ClipDistance, but the
    136     *     application has requested clipping against user clip planes through
    137     *     the API, then the coordinate written to gl_Position is used for
    138     *     comparison against the user clip planes."
    139     *
    140     * This function is only called if the shader didn't write to
    141     * gl_ClipDistance.  Accordingly, we use gl_ClipVertex to perform clipping
    142     * if the user wrote to it; otherwise we use gl_Position.
    143     */
    144    gl_varying_slot clip_vertex = VARYING_SLOT_CLIP_VERTEX;
    145    if (!(prog_data->vue_map.slots_valid & VARYING_BIT_CLIP_VERTEX)) {
    146       clip_vertex = VARYING_SLOT_POS;
    147    }
    148 
    149    for (int i = 0; i + offset < key->nr_userclip_plane_consts && i < 4;
    150         ++i) {
    151       reg.writemask = 1 << i;
    152       emit(DP4(reg,
    153                src_reg(output_reg[clip_vertex][0]),
    154                src_reg(this->userplane[i + offset])));
    155    }
    156 }
    157 
    158 
    159 void
    160 vec4_vs_visitor::setup_uniform_clipplane_values()
    161 {
    162    for (int i = 0; i < key->nr_userclip_plane_consts; ++i) {
    163       this->userplane[i] = dst_reg(UNIFORM, this->uniforms);
    164       this->userplane[i].type = BRW_REGISTER_TYPE_F;
    165       for (int j = 0; j < 4; ++j) {
    166          stage_prog_data->param[this->uniforms * 4 + j] =
    167             (gl_constant_value *) &clip_planes[i][j];
    168       }
    169       ++this->uniforms;
    170    }
    171 }
    172 
    173 
    174 void
    175 vec4_vs_visitor::emit_thread_end()
    176 {
    177    setup_uniform_clipplane_values();
    178 
    179    /* Lower legacy ff and ClipVertex clipping to clip distances */
    180    if (key->nr_userclip_plane_consts > 0) {
    181       current_annotation = "user clip distances";
    182 
    183       output_reg[VARYING_SLOT_CLIP_DIST0][0] =
    184          dst_reg(this, glsl_type::vec4_type);
    185       output_reg[VARYING_SLOT_CLIP_DIST1][0] =
    186          dst_reg(this, glsl_type::vec4_type);
    187       output_num_components[VARYING_SLOT_CLIP_DIST0][0] = 4;
    188       output_num_components[VARYING_SLOT_CLIP_DIST1][0] = 4;
    189 
    190       emit_clip_distances(output_reg[VARYING_SLOT_CLIP_DIST0][0], 0);
    191       emit_clip_distances(output_reg[VARYING_SLOT_CLIP_DIST1][0], 4);
    192    }
    193 
    194    /* For VS, we always end the thread by emitting a single vertex.
    195     * emit_urb_write_opcode() will take care of setting the eot flag on the
    196     * SEND instruction.
    197     */
    198    emit_vertex();
    199 }
    200 
    201 
    202 vec4_vs_visitor::vec4_vs_visitor(const struct brw_compiler *compiler,
    203                                  void *log_data,
    204                                  const struct brw_vs_prog_key *key,
    205                                  struct brw_vs_prog_data *vs_prog_data,
    206                                  const nir_shader *shader,
    207                                  gl_clip_plane *clip_planes,
    208                                  void *mem_ctx,
    209                                  int shader_time_index,
    210                                  bool use_legacy_snorm_formula)
    211    : vec4_visitor(compiler, log_data, &key->tex, &vs_prog_data->base, shader,
    212                   mem_ctx, false /* no_spills */, shader_time_index),
    213      key(key),
    214      vs_prog_data(vs_prog_data),
    215      clip_planes(clip_planes),
    216      use_legacy_snorm_formula(use_legacy_snorm_formula)
    217 {
    218 }
    219 
    220 
    221 } /* namespace brw */
    222