1 /************************************************************************** 2 * 3 * Copyright 2010 Luca Barbieri 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining 6 * a copy of this software and associated documentation files (the 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sublicense, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject to 11 * the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the 14 * next paragraph) shall be included in all copies or substantial 15 * portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE 21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 * 25 **************************************************************************/ 26 27 /* Header for Shader Model 4.0, 4.1 and 5.0 */ 28 29 #ifndef SM4_H_ 30 #define SM4_H_ 31 32 #include <stdint.h> 33 #include <string.h> 34 #include <stdlib.h> 35 #include <memory> 36 #include <vector> 37 #include <map> 38 #include <iostream> 39 #include "le32.h" 40 41 #include "sm4_defs.h" 42 43 extern const char* sm4_opcode_names[]; 44 extern const char* sm4_file_names[]; 45 extern const char* sm4_shortfile_names[]; 46 extern const char* sm4_target_names[]; 47 extern const char* sm4_interpolation_names[]; 48 extern const char* sm4_sv_names[]; 49 50 struct sm4_token_version 51 { 52 unsigned minor : 4; 53 unsigned major : 4; 54 unsigned format : 8; 55 unsigned type : 16; 56 }; 57 58 struct sm4_token_instruction 59 { 60 // we don't make it an union directly because unions can't be inherited from 61 union 62 { 63 // length and extended are always present, but they are only here to reduce duplication 64 struct 65 { 66 unsigned opcode : 11; 67 unsigned _11_23 : 13; 68 unsigned length : 7; 69 unsigned extended : 1; 70 }; 71 struct 72 { 73 unsigned opcode : 11; 74 unsigned resinfo_return_type : 2; 75 unsigned sat : 1; 76 unsigned _14_17 : 4; 77 unsigned test_nz : 1; // bit 18 78 unsigned precise_mask : 4; 79 unsigned _23 : 1; 80 unsigned length : 7; 81 unsigned extended : 1; 82 } insn; 83 struct 84 { 85 unsigned opcode : 11; 86 unsigned threads_in_group : 1; 87 unsigned shared_memory : 1; 88 unsigned uav_group : 1; 89 unsigned uav_global : 1; 90 unsigned _15_17 : 3; 91 } sync; 92 struct 93 { 94 unsigned opcode : 11; 95 unsigned allow_refactoring : 1; 96 unsigned fp64 : 1; 97 unsigned early_depth_stencil : 1; 98 unsigned enable_raw_and_structured_in_non_cs : 1; 99 } dcl_global_flags; 100 struct 101 { 102 unsigned opcode : 11; 103 unsigned target : 5; 104 unsigned nr_samples : 7; 105 } dcl_resource; 106 struct 107 { 108 unsigned opcode : 11; 109 unsigned shadow : 1; 110 unsigned mono : 1; 111 } dcl_sampler; 112 struct 113 { 114 unsigned opcode : 11; 115 unsigned interpolation : 5; 116 } dcl_input_ps; 117 struct 118 { 119 unsigned opcode : 11; 120 unsigned dynamic : 1; 121 } dcl_constant_buffer; 122 struct 123 { 124 unsigned opcode : 11; 125 unsigned primitive : 6; 126 } dcl_gs_input_primitive; 127 struct 128 { 129 unsigned opcode : 11; 130 unsigned primitive_topology : 7; 131 } dcl_gs_output_primitive_topology; 132 struct 133 { 134 unsigned opcode : 11; 135 unsigned control_points : 6; 136 } dcl_input_control_point_count; 137 struct 138 { 139 unsigned opcode : 11; 140 unsigned control_points : 6; 141 } dcl_output_control_point_count; 142 struct 143 { 144 unsigned opcode : 11; 145 unsigned domain : 3; /* D3D_TESSELLATOR_DOMAIN */ 146 } dcl_tess_domain; 147 struct 148 { 149 unsigned opcode : 11; 150 unsigned partitioning : 3; /* D3D_TESSELLATOR_PARTITIONING */ 151 } dcl_tess_partitioning; 152 struct 153 { 154 unsigned opcode : 11; 155 unsigned primitive : 3; /* D3D_TESSELLATOR_OUTPUT_PRIMITIVE */ 156 } dcl_tess_output_primitive; 157 }; 158 }; 159 160 union sm4_token_instruction_extended 161 { 162 struct 163 { 164 unsigned type : 6; 165 unsigned _6_30 : 25; 166 unsigned extended :1; 167 }; 168 struct 169 { 170 unsigned type : 6; 171 unsigned _6_8 : 3; 172 int offset_u : 4; 173 int offset_v : 4; 174 int offset_w : 4; 175 } sample_controls; 176 struct 177 { 178 unsigned type : 6; 179 unsigned target : 5; 180 } resource_target; 181 struct 182 { 183 unsigned type : 6; 184 unsigned x : 4; 185 unsigned y : 4; 186 unsigned z : 4; 187 unsigned w : 4; 188 } resource_return_type; 189 }; 190 191 struct sm4_token_resource_return_type 192 { 193 unsigned x : 4; 194 unsigned y : 4; 195 unsigned z : 4; 196 unsigned w : 4; 197 }; 198 199 struct sm4_token_operand 200 { 201 unsigned comps_enum : 2; /* sm4_operands_comps */ 202 unsigned mode : 2; /* sm4_operand_mode */ 203 unsigned sel : 8; 204 unsigned file : 8; /* sm4_file */ 205 unsigned num_indices : 2; 206 unsigned index0_repr : 3; /* sm4_operand_index_repr */ 207 unsigned index1_repr : 3; /* sm4_operand_index_repr */ 208 unsigned index2_repr : 3; /* sm4_operand_index_repr */ 209 unsigned extended : 1; 210 }; 211 212 #define SM4_OPERAND_SEL_MASK(sel) ((sel) & 0xf) 213 #define SM4_OPERAND_SEL_SWZ(sel, i) (((sel) >> ((i) * 2)) & 3) 214 #define SM4_OPERAND_SEL_SCALAR(sel) ((sel) & 3) 215 216 struct sm4_token_operand_extended 217 { 218 unsigned type : 6; 219 unsigned neg : 1; 220 unsigned abs : 1; 221 }; 222 223 union sm4_any 224 { 225 double f64; 226 float f32; 227 int64_t i64; 228 int32_t i32; 229 uint64_t u64; 230 int64_t u32; 231 }; 232 233 struct sm4_op; 234 struct sm4_insn; 235 struct sm4_dcl; 236 struct sm4_program; 237 std::ostream& operator <<(std::ostream& out, const sm4_op& op); 238 std::ostream& operator <<(std::ostream& out, const sm4_insn& op); 239 std::ostream& operator <<(std::ostream& out, const sm4_dcl& op); 240 std::ostream& operator <<(std::ostream& out, const sm4_program& op); 241 242 struct sm4_op 243 { 244 uint8_t mode; 245 uint8_t comps; 246 uint8_t mask; 247 uint8_t num_indices; 248 uint8_t swizzle[4]; 249 sm4_file file; 250 sm4_any imm_values[4]; 251 bool neg; 252 bool abs; 253 struct 254 { 255 int64_t disp; 256 std::auto_ptr<sm4_op> reg; 257 } indices[3]; 258 259 bool is_index_simple(unsigned i) const 260 { 261 return !indices[i].reg.get() && indices[i].disp >= 0 && (int64_t)(int32_t)indices[i].disp == indices[i].disp; 262 } 263 264 bool has_simple_index() const 265 { 266 return num_indices == 1 && is_index_simple(0); 267 } 268 269 sm4_op() 270 { 271 memset(this, 0, sizeof(*this)); 272 } 273 274 void dump(); 275 276 private: 277 sm4_op(const sm4_op& op) 278 {} 279 }; 280 281 /* for sample_d */ 282 #define SM4_MAX_OPS 6 283 284 struct sm4_insn : public sm4_token_instruction 285 { 286 int8_t sample_offset[3]; 287 uint8_t resource_target; 288 uint8_t resource_return_type[4]; 289 290 unsigned num; 291 unsigned num_ops; 292 std::auto_ptr<sm4_op> ops[SM4_MAX_OPS]; 293 294 sm4_insn() 295 { 296 memset(this, 0, sizeof(*this)); 297 } 298 299 void dump(); 300 301 private: 302 sm4_insn(const sm4_insn& op) 303 {} 304 }; 305 306 struct sm4_dcl : public sm4_token_instruction 307 { 308 std::auto_ptr<sm4_op> op; 309 union 310 { 311 unsigned num; 312 float f32; 313 sm4_sv sv; 314 struct 315 { 316 unsigned id; 317 unsigned expected_function_table_length; 318 unsigned table_length; 319 unsigned array_length; 320 } intf; 321 unsigned thread_group_size[3]; 322 sm4_token_resource_return_type rrt; 323 struct 324 { 325 unsigned num; 326 unsigned comps; 327 } indexable_temp; 328 struct 329 { 330 unsigned stride; 331 unsigned count; 332 } structured; 333 }; 334 335 void* data; 336 337 sm4_dcl() 338 { 339 memset(this, 0, sizeof(*this)); 340 } 341 342 ~sm4_dcl() 343 { 344 free(data); 345 } 346 347 void dump(); 348 349 private: 350 sm4_dcl(const sm4_dcl& op) 351 {} 352 }; 353 354 struct _D3D11_SIGNATURE_PARAMETER_DESC; 355 356 struct sm4_program 357 { 358 sm4_token_version version; 359 std::vector<sm4_dcl*> dcls; 360 std::vector<sm4_insn*> insns; 361 362 _D3D11_SIGNATURE_PARAMETER_DESC* params_in; 363 _D3D11_SIGNATURE_PARAMETER_DESC* params_out; 364 _D3D11_SIGNATURE_PARAMETER_DESC* params_patch; 365 unsigned num_params_in; 366 unsigned num_params_out; 367 unsigned num_params_patch; 368 369 /* for ifs, the insn number of the else or endif if there is no else 370 * for elses, the insn number of the endif 371 * for endifs, the insn number of the if 372 * for loops, the insn number of the endloop 373 * for endloops, the insn number of the loop 374 * for all others, -1 375 */ 376 std::vector<int> cf_insn_linked; 377 378 bool labels_found; 379 std::vector<int> label_to_insn_num; 380 381 sm4_program() 382 { 383 memset(&version, 0, sizeof(version)); 384 labels_found = false; 385 num_params_in = num_params_out = num_params_patch = 0; 386 } 387 388 ~sm4_program() 389 { 390 for(std::vector<sm4_dcl*>::iterator i = dcls.begin(), e = dcls.end(); i != e; ++i) 391 delete *i; 392 for(std::vector<sm4_insn*>::iterator i = insns.begin(), e = insns.end(); i != e; ++i) 393 delete *i; 394 395 if(num_params_in) 396 free(params_in); 397 if(num_params_out) 398 free(params_out); 399 if(num_params_patch) 400 free(params_patch); 401 } 402 403 void dump(); 404 405 private: 406 sm4_program(const sm4_dcl& op) 407 {} 408 }; 409 410 sm4_program* sm4_parse(void* tokens, int size); 411 412 bool sm4_link_cf_insns(sm4_program& program); 413 bool sm4_find_labels(sm4_program& program); 414 415 #endif /* SM4_H_ */ 416 417