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