1 /* 2 * Mesa 3-D graphics library 3 * 4 * Copyright (C) 2012-2013 LunarG, Inc. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included 14 * in all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 * DEALINGS IN THE SOFTWARE. 23 * 24 * Authors: 25 * Chia-I Wu <olv (at) lunarg.com> 26 */ 27 28 #ifndef TOY_HELPERS_H 29 #define TOY_HELPERS_H 30 31 #include "toy_compiler.h" 32 33 /** 34 * Transpose a dst operand. 35 * 36 * Instead of processing a single vertex with each of its attributes in one 37 * register, such as 38 * 39 * r0 = [x0, y0, z0, w0] 40 * 41 * we want to process four vertices at a time 42 * 43 * r0 = [x0, y0, z0, w0] 44 * r1 = [x1, y1, z1, w1] 45 * r2 = [x2, y2, z2, w2] 46 * r3 = [x3, y3, z3, w3] 47 * 48 * but with the attribute data "transposed" 49 * 50 * r0 = [x0, x1, x2, x3] 51 * r1 = [y0, y1, y2, y3] 52 * r2 = [z0, z1, z2, z3] 53 * r3 = [w0, w1, w2, w3] 54 * 55 * This is also known as the SoA form. 56 */ 57 static inline void 58 tdst_transpose(struct toy_dst dst, struct toy_dst *trans) 59 { 60 int i; 61 62 switch (dst.file) { 63 case TOY_FILE_VRF: 64 assert(!dst.indirect); 65 for (i = 0; i < 4; i++) { 66 if (dst.writemask & (1 << i)) { 67 trans[i] = tdst_offset(dst, i, 0); 68 trans[i].writemask = TOY_WRITEMASK_XYZW; 69 } 70 else { 71 trans[i] = tdst_null(); 72 } 73 } 74 break; 75 case TOY_FILE_ARF: 76 assert(tdst_is_null(dst)); 77 for (i = 0; i < 4; i++) 78 trans[i] = dst; 79 break; 80 case TOY_FILE_GRF: 81 case TOY_FILE_MRF: 82 case TOY_FILE_IMM: 83 default: 84 assert(!"unexpected file in dst transposition"); 85 for (i = 0; i < 4; i++) 86 trans[i] = tdst_null(); 87 break; 88 } 89 } 90 91 /** 92 * Transpose a src operand. 93 */ 94 static inline void 95 tsrc_transpose(struct toy_src src, struct toy_src *trans) 96 { 97 const enum toy_swizzle swizzle[4] = { 98 src.swizzle_x, src.swizzle_y, 99 src.swizzle_z, src.swizzle_w, 100 }; 101 int i; 102 103 switch (src.file) { 104 case TOY_FILE_VRF: 105 assert(!src.indirect); 106 for (i = 0; i < 4; i++) { 107 trans[i] = tsrc_offset(src, swizzle[i], 0); 108 trans[i].swizzle_x = TOY_SWIZZLE_X; 109 trans[i].swizzle_y = TOY_SWIZZLE_Y; 110 trans[i].swizzle_z = TOY_SWIZZLE_Z; 111 trans[i].swizzle_w = TOY_SWIZZLE_W; 112 } 113 break; 114 case TOY_FILE_ARF: 115 assert(tsrc_is_null(src)); 116 /* fall through */ 117 case TOY_FILE_IMM: 118 for (i = 0; i < 4; i++) 119 trans[i] = src; 120 break; 121 case TOY_FILE_GRF: 122 case TOY_FILE_MRF: 123 default: 124 assert(!"unexpected file in src transposition"); 125 for (i = 0; i < 4; i++) 126 trans[i] = tsrc_null(); 127 break; 128 } 129 } 130 131 static inline struct toy_src 132 tsrc_imm_mdesc(const struct toy_compiler *tc, 133 bool eot, 134 unsigned message_length, 135 unsigned response_length, 136 bool header_present, 137 uint32_t function_control) 138 { 139 uint32_t desc; 140 141 assert(message_length >= 1 && message_length <= 15); 142 assert(response_length >= 0 && response_length <= 16); 143 assert(function_control < 1 << 19); 144 145 desc = eot << 31 | 146 message_length << 25 | 147 response_length << 20 | 148 header_present << 19 | 149 function_control; 150 151 return tsrc_imm_ud(desc); 152 } 153 154 static inline struct toy_src 155 tsrc_imm_mdesc_sampler(const struct toy_compiler *tc, 156 unsigned message_length, 157 unsigned response_length, 158 bool header_present, 159 unsigned simd_mode, 160 unsigned message_type, 161 unsigned sampler_index, 162 unsigned binding_table_index) 163 { 164 const bool eot = false; 165 uint32_t ctrl; 166 167 assert(simd_mode < 4); 168 assert(sampler_index < 16); 169 assert(binding_table_index < 256); 170 171 if (ilo_dev_gen(tc->dev) >= ILO_GEN(7)) { 172 ctrl = simd_mode << 17 | 173 message_type << 12 | 174 sampler_index << 8 | 175 binding_table_index; 176 } 177 else { 178 ctrl = simd_mode << 16 | 179 message_type << 12 | 180 sampler_index << 8 | 181 binding_table_index; 182 } 183 184 return tsrc_imm_mdesc(tc, eot, message_length, 185 response_length, header_present, ctrl); 186 } 187 188 static inline struct toy_src 189 tsrc_imm_mdesc_data_port(const struct toy_compiler *tc, 190 bool eot, 191 unsigned message_length, 192 unsigned response_length, 193 bool header_present, 194 bool send_write_commit_message, 195 unsigned message_type, 196 unsigned message_specific_control, 197 unsigned binding_table_index) 198 { 199 uint32_t ctrl; 200 201 if (ilo_dev_gen(tc->dev) >= ILO_GEN(7)) { 202 assert(!send_write_commit_message); 203 assert((message_specific_control & 0x3f00) == message_specific_control); 204 205 ctrl = message_type << 14 | 206 (message_specific_control & 0x3f00) | 207 binding_table_index; 208 } 209 else { 210 assert(!send_write_commit_message || 211 message_type == GEN6_MSG_DP_SVB_WRITE); 212 assert((message_specific_control & 0x1f00) == message_specific_control); 213 214 ctrl = send_write_commit_message << 17 | 215 message_type << 13 | 216 (message_specific_control & 0x1f00) | 217 binding_table_index; 218 } 219 220 return tsrc_imm_mdesc(tc, eot, message_length, 221 response_length, header_present, ctrl); 222 } 223 224 static inline struct toy_src 225 tsrc_imm_mdesc_data_port_scratch(const struct toy_compiler *tc, 226 unsigned message_length, 227 unsigned response_length, 228 bool write_type, 229 bool dword_mode, 230 bool invalidate_after_read, 231 int num_registers, 232 int hword_offset) 233 { 234 const bool eot = false; 235 const bool header_present = true; 236 uint32_t ctrl; 237 238 assert(ilo_dev_gen(tc->dev) >= ILO_GEN(7)); 239 assert(num_registers == 1 || num_registers == 2 || num_registers == 4); 240 241 ctrl = 1 << 18 | 242 write_type << 17 | 243 dword_mode << 16 | 244 invalidate_after_read << 15 | 245 (num_registers - 1) << 12 | 246 hword_offset; 247 248 return tsrc_imm_mdesc(tc, eot, message_length, 249 response_length, header_present, ctrl); 250 } 251 252 static inline struct toy_src 253 tsrc_imm_mdesc_urb(const struct toy_compiler *tc, 254 bool eot, 255 unsigned message_length, 256 unsigned response_length, 257 bool complete, 258 bool used, 259 bool allocate, 260 unsigned swizzle_control, 261 unsigned global_offset, 262 unsigned urb_opcode) 263 { 264 const bool header_present = true; 265 uint32_t ctrl; 266 267 if (ilo_dev_gen(tc->dev) >= ILO_GEN(8)) { 268 const bool per_slot_offset = false; 269 270 ctrl = per_slot_offset << 17 | 271 swizzle_control << 15 | 272 global_offset << 4 | 273 urb_opcode; 274 } else if (ilo_dev_gen(tc->dev) >= ILO_GEN(7)) { 275 const bool per_slot_offset = false; 276 277 ctrl = per_slot_offset << 16 | 278 complete << 15 | 279 swizzle_control << 14 | 280 global_offset << 3 | 281 urb_opcode; 282 } else { 283 ctrl = complete << 15 | 284 used << 14 | 285 allocate << 13 | 286 swizzle_control << 10 | 287 global_offset << 4 | 288 urb_opcode; 289 } 290 291 return tsrc_imm_mdesc(tc, eot, message_length, 292 response_length, header_present, ctrl); 293 } 294 295 #endif /* TOY_HELPERS_H */ 296