sm4.h revision 6c598c78bd17642d731cf57b8369cc794f64ba2f
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
43extern const char* sm4_opcode_names[];
44extern const char* sm4_file_names[];
45extern const char* sm4_file_ms_names[];
46extern const char* sm4_target_names[];
47extern const char* sm4_interpolation_names[];
48extern const char* sm4_sv_names[];
49
50struct sm4_token_version
51{
52	unsigned minor : 4;
53	unsigned major : 4;
54	unsigned format : 8;
55	unsigned type : 16;
56};
57
58struct 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
160union 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
191struct sm4_token_resource_return_type
192{
193	unsigned x : 4;
194	unsigned y : 4;
195	unsigned z : 4;
196	unsigned w : 4;
197};
198
199struct 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
216struct sm4_token_operand_extended
217{
218	unsigned type : 6;
219	unsigned neg : 1;
220	unsigned abs : 1;
221};
222
223union 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
233struct sm4_op;
234struct sm4_insn;
235struct sm4_dcl;
236struct sm4_program;
237std::ostream& operator <<(std::ostream& out, const sm4_op& op);
238std::ostream& operator <<(std::ostream& out, const sm4_insn& op);
239std::ostream& operator <<(std::ostream& out, const sm4_dcl& op);
240std::ostream& operator <<(std::ostream& out, const sm4_program& op);
241
242struct 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
276private:
277	sm4_op(const sm4_op& op)
278	{}
279};
280
281/* for sample_d */
282#define SM4_MAX_OPS 6
283
284struct 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
301private:
302	sm4_insn(const sm4_insn& op)
303	{}
304};
305
306struct 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
349private:
350	sm4_dcl(const sm4_dcl& op)
351	{}
352};
353
354struct sm4_program
355{
356	sm4_token_version version;
357	std::vector<sm4_dcl*> dcls;
358	std::vector<sm4_insn*> insns;
359
360	/* for ifs, the insn number of the else or endif if there is no else
361	 * for elses, the insn number of the endif
362	 * for endifs, the insn number of the if
363	 * for loops, the insn number of the endloop
364	 * for endloops, the insn number of the loop
365	 * for all others, -1
366	 */
367	std::vector<int> cf_insn_linked;
368
369	/* NOTE: sampler 0 is the unnormalized nearest sampler for LD/LD_MS, while
370	 * sampler 1 is user-specified sampler 0
371	 */
372	bool resource_sampler_slots_assigned;
373	std::vector<int> slot_to_resource;
374	std::vector<int> slot_to_sampler;
375	std::map<std::pair<int, int>, int> resource_sampler_to_slot;
376	std::map<int, int> resource_to_slot;
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		resource_sampler_slots_assigned = false;
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
396	void dump();
397
398private:
399	sm4_program(const sm4_dcl& op)
400	{}
401};
402
403sm4_program* sm4_parse(void* tokens, int size);
404
405bool sm4_link_cf_insns(sm4_program& program);
406bool sm4_find_labels(sm4_program& program);
407bool sm4_allocate_resource_sampler_pairs(sm4_program& program);
408
409#endif /* SM4_H_ */
410
411