wined3d: Recognize SM5 vForkInstanceId register.
[wine.git] / dlls / wined3d / shader_sm4.c
blob26bd3537492cf0afd22f7f921e7998771590d386
1 /*
2 * Copyright 2009 Henri Verbeet for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include "config.h"
20 #include "wine/port.h"
22 #include "wined3d_private.h"
24 WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader);
25 WINE_DECLARE_DEBUG_CHANNEL(d3d_bytecode);
27 #define WINED3D_SM4_INSTRUCTION_MODIFIER (0x1u << 31)
29 #define WINED3D_SM4_MODIFIER_AOFFIMMI 0x1
30 #define WINED3D_SM4_AOFFIMMI_U_SHIFT 9
31 #define WINED3D_SM4_AOFFIMMI_U_MASK (0xfu << WINED3D_SM4_AOFFIMMI_U_SHIFT)
32 #define WINED3D_SM4_AOFFIMMI_V_SHIFT 13
33 #define WINED3D_SM4_AOFFIMMI_V_MASK (0xfu << WINED3D_SM4_AOFFIMMI_V_SHIFT)
34 #define WINED3D_SM4_AOFFIMMI_W_SHIFT 17
35 #define WINED3D_SM4_AOFFIMMI_W_MASK (0xfu << WINED3D_SM4_AOFFIMMI_W_SHIFT)
37 #define WINED3D_SM4_INSTRUCTION_LENGTH_SHIFT 24
38 #define WINED3D_SM4_INSTRUCTION_LENGTH_MASK (0x1fu << WINED3D_SM4_INSTRUCTION_LENGTH_SHIFT)
40 #define WINED3D_SM4_INSTRUCTION_FLAGS_SHIFT 11
41 #define WINED3D_SM4_INSTRUCTION_FLAGS_MASK (0x7u << WINED3D_SM4_INSTRUCTION_FLAGS_SHIFT)
43 #define WINED3D_SM4_RESOURCE_TYPE_SHIFT 11
44 #define WINED3D_SM4_RESOURCE_TYPE_MASK (0xfu << WINED3D_SM4_RESOURCE_TYPE_SHIFT)
46 #define WINED3D_SM4_PRIMITIVE_TYPE_SHIFT 11
47 #define WINED3D_SM4_PRIMITIVE_TYPE_MASK (0x7u << WINED3D_SM4_PRIMITIVE_TYPE_SHIFT)
49 #define WINED3D_SM4_INDEX_TYPE_SHIFT 11
50 #define WINED3D_SM4_INDEX_TYPE_MASK (0x1u << WINED3D_SM4_INDEX_TYPE_SHIFT)
52 #define WINED3D_SM4_SAMPLER_MODE_SHIFT 11
53 #define WINED3D_SM4_SAMPLER_MODE_MASK (0xfu << WINED3D_SM4_SAMPLER_MODE_SHIFT)
55 #define WINED3D_SM4_SHADER_DATA_TYPE_SHIFT 11
56 #define WINED3D_SM4_SHADER_DATA_TYPE_MASK (0xfu << WINED3D_SM4_SHADER_DATA_TYPE_SHIFT)
58 #define WINED3D_SM4_INTERPOLATION_MODE_SHIFT 11
59 #define WINED3D_SM4_INTERPOLATION_MODE_MASK (0xfu << WINED3D_SM4_INTERPOLATION_MODE_SHIFT)
61 #define WINED3D_SM4_GLOBAL_FLAGS_SHIFT 11
62 #define WINED3D_SM4_GLOBAL_FLAGS_MASK (0xffu << WINED3D_SM4_GLOBAL_FLAGS_SHIFT)
64 #define WINED3D_SM5_CONTROL_POINT_COUNT_SHIFT 11
65 #define WINED3D_SM5_CONTROL_POINT_COUNT_MASK (0xffu << WINED3D_SM5_CONTROL_POINT_COUNT_SHIFT)
67 #define WINED3D_SM4_OPCODE_MASK 0xff
69 #define WINED3D_SM4_REGISTER_MODIFIER (0x1u << 31)
71 #define WINED3D_SM4_ADDRESSING_SHIFT1 25
72 #define WINED3D_SM4_ADDRESSING_MASK1 (0x3u << WINED3D_SM4_ADDRESSING_SHIFT1)
74 #define WINED3D_SM4_ADDRESSING_SHIFT0 22
75 #define WINED3D_SM4_ADDRESSING_MASK0 (0x3u << WINED3D_SM4_ADDRESSING_SHIFT0)
77 #define WINED3D_SM4_REGISTER_ORDER_SHIFT 20
78 #define WINED3D_SM4_REGISTER_ORDER_MASK (0x3u << WINED3D_SM4_REGISTER_ORDER_SHIFT)
80 #define WINED3D_SM4_REGISTER_TYPE_SHIFT 12
81 #define WINED3D_SM4_REGISTER_TYPE_MASK (0xffu << WINED3D_SM4_REGISTER_TYPE_SHIFT)
83 #define WINED3D_SM4_SWIZZLE_TYPE_SHIFT 2
84 #define WINED3D_SM4_SWIZZLE_TYPE_MASK (0x3u << WINED3D_SM4_SWIZZLE_TYPE_SHIFT)
86 #define WINED3D_SM4_IMMCONST_TYPE_SHIFT 0
87 #define WINED3D_SM4_IMMCONST_TYPE_MASK (0x3u << WINED3D_SM4_IMMCONST_TYPE_SHIFT)
89 #define WINED3D_SM4_WRITEMASK_SHIFT 4
90 #define WINED3D_SM4_WRITEMASK_MASK (0xfu << WINED3D_SM4_WRITEMASK_SHIFT)
92 #define WINED3D_SM4_SWIZZLE_SHIFT 4
93 #define WINED3D_SM4_SWIZZLE_MASK (0xffu << WINED3D_SM4_SWIZZLE_SHIFT)
95 #define WINED3D_SM4_VERSION_MAJOR(version) (((version) >> 4) & 0xf)
96 #define WINED3D_SM4_VERSION_MINOR(version) (((version) >> 0) & 0xf)
98 #define WINED3D_SM4_ADDRESSING_RELATIVE 0x2
99 #define WINED3D_SM4_ADDRESSING_OFFSET 0x1
101 #define WINED3D_SM4_INSTRUCTION_FLAG_SATURATE 0x4
103 enum wined3d_sm4_opcode
105 WINED3D_SM4_OP_ADD = 0x00,
106 WINED3D_SM4_OP_AND = 0x01,
107 WINED3D_SM4_OP_BREAK = 0x02,
108 WINED3D_SM4_OP_BREAKC = 0x03,
109 WINED3D_SM4_OP_CUT = 0x09,
110 WINED3D_SM4_OP_DERIV_RTX = 0x0b,
111 WINED3D_SM4_OP_DERIV_RTY = 0x0c,
112 WINED3D_SM4_OP_DISCARD = 0x0d,
113 WINED3D_SM4_OP_DIV = 0x0e,
114 WINED3D_SM4_OP_DP2 = 0x0f,
115 WINED3D_SM4_OP_DP3 = 0x10,
116 WINED3D_SM4_OP_DP4 = 0x11,
117 WINED3D_SM4_OP_ELSE = 0x12,
118 WINED3D_SM4_OP_EMIT = 0x13,
119 WINED3D_SM4_OP_ENDIF = 0x15,
120 WINED3D_SM4_OP_ENDLOOP = 0x16,
121 WINED3D_SM4_OP_EQ = 0x18,
122 WINED3D_SM4_OP_EXP = 0x19,
123 WINED3D_SM4_OP_FRC = 0x1a,
124 WINED3D_SM4_OP_FTOI = 0x1b,
125 WINED3D_SM4_OP_FTOU = 0x1c,
126 WINED3D_SM4_OP_GE = 0x1d,
127 WINED3D_SM4_OP_IADD = 0x1e,
128 WINED3D_SM4_OP_IF = 0x1f,
129 WINED3D_SM4_OP_IEQ = 0x20,
130 WINED3D_SM4_OP_IGE = 0x21,
131 WINED3D_SM4_OP_ILT = 0x22,
132 WINED3D_SM4_OP_IMAD = 0x23,
133 WINED3D_SM4_OP_IMAX = 0x24,
134 WINED3D_SM4_OP_IMIN = 0x25,
135 WINED3D_SM4_OP_IMUL = 0x26,
136 WINED3D_SM4_OP_INE = 0x27,
137 WINED3D_SM4_OP_INEG = 0x28,
138 WINED3D_SM4_OP_ISHL = 0x29,
139 WINED3D_SM4_OP_ITOF = 0x2b,
140 WINED3D_SM4_OP_LD = 0x2d,
141 WINED3D_SM4_OP_LD2DMS = 0x2e,
142 WINED3D_SM4_OP_LOG = 0x2f,
143 WINED3D_SM4_OP_LOOP = 0x30,
144 WINED3D_SM4_OP_LT = 0x31,
145 WINED3D_SM4_OP_MAD = 0x32,
146 WINED3D_SM4_OP_MIN = 0x33,
147 WINED3D_SM4_OP_MAX = 0x34,
148 WINED3D_SM4_OP_SHADER_DATA = 0x35,
149 WINED3D_SM4_OP_MOV = 0x36,
150 WINED3D_SM4_OP_MOVC = 0x37,
151 WINED3D_SM4_OP_MUL = 0x38,
152 WINED3D_SM4_OP_NE = 0x39,
153 WINED3D_SM4_OP_NOT = 0x3b,
154 WINED3D_SM4_OP_OR = 0x3c,
155 WINED3D_SM4_OP_RESINFO = 0x3d,
156 WINED3D_SM4_OP_RET = 0x3e,
157 WINED3D_SM4_OP_ROUND_NI = 0x41,
158 WINED3D_SM4_OP_ROUND_PI = 0x42,
159 WINED3D_SM4_OP_ROUND_Z = 0x43,
160 WINED3D_SM4_OP_RSQ = 0x44,
161 WINED3D_SM4_OP_SAMPLE = 0x45,
162 WINED3D_SM4_OP_SAMPLE_C = 0x46,
163 WINED3D_SM4_OP_SAMPLE_C_LZ = 0x47,
164 WINED3D_SM4_OP_SAMPLE_LOD = 0x48,
165 WINED3D_SM4_OP_SAMPLE_GRAD = 0x49,
166 WINED3D_SM4_OP_SAMPLE_B = 0x4a,
167 WINED3D_SM4_OP_SQRT = 0x4b,
168 WINED3D_SM4_OP_SINCOS = 0x4d,
169 WINED3D_SM4_OP_UDIV = 0x4e,
170 WINED3D_SM4_OP_UGE = 0x50,
171 WINED3D_SM4_OP_USHR = 0x55,
172 WINED3D_SM4_OP_UTOF = 0x56,
173 WINED3D_SM4_OP_XOR = 0x57,
174 WINED3D_SM4_OP_DCL_RESOURCE = 0x58,
175 WINED3D_SM4_OP_DCL_CONSTANT_BUFFER = 0x59,
176 WINED3D_SM4_OP_DCL_SAMPLER = 0x5a,
177 WINED3D_SM4_OP_DCL_OUTPUT_TOPOLOGY = 0x5c,
178 WINED3D_SM4_OP_DCL_INPUT_PRIMITIVE = 0x5d,
179 WINED3D_SM4_OP_DCL_VERTICES_OUT = 0x5e,
180 WINED3D_SM4_OP_DCL_INPUT = 0x5f,
181 WINED3D_SM4_OP_DCL_INPUT_SGV = 0x60,
182 WINED3D_SM4_OP_DCL_INPUT_SIV = 0x61,
183 WINED3D_SM4_OP_DCL_INPUT_PS = 0x62,
184 WINED3D_SM4_OP_DCL_INPUT_PS_SGV = 0x63,
185 WINED3D_SM4_OP_DCL_INPUT_PS_SIV = 0x64,
186 WINED3D_SM4_OP_DCL_OUTPUT = 0x65,
187 WINED3D_SM4_OP_DCL_OUTPUT_SIV = 0x67,
188 WINED3D_SM4_OP_DCL_TEMPS = 0x68,
189 WINED3D_SM4_OP_DCL_GLOBAL_FLAGS = 0x6a,
190 WINED3D_SM5_OP_HS_DECLS = 0x71,
191 WINED3D_SM5_OP_HS_FORK_PHASE = 0x73,
192 WINED3D_SM5_OP_DERIV_RTX_COARSE = 0x7a,
193 WINED3D_SM5_OP_DERIV_RTX_FINE = 0x7b,
194 WINED3D_SM5_OP_DERIV_RTY_COARSE = 0x7c,
195 WINED3D_SM5_OP_DERIV_RTY_FINE = 0x7d,
196 WINED3D_SM5_OP_DCL_INPUT_CONTROL_POINT_COUNT = 0x93,
197 WINED3D_SM5_OP_DCL_OUTPUT_CONTROL_POINT_COUNT = 0x94,
198 WINED3D_SM5_OP_DCL_HS_MAX_TESSFACTOR = 0x98,
199 WINED3D_SM5_OP_DCL_HS_FORK_PHASE_INSTANCE_COUNT = 0x99,
200 WINED3D_SM5_OP_DCL_UAV_TYPED = 0x9c,
201 WINED3D_SM5_OP_DCL_RESOURCE_STRUCTURED = 0xa2,
202 WINED3D_SM5_OP_STORE_UAV_TYPED = 0xa4,
203 WINED3D_SM5_OP_LD_STRUCTURED = 0xa7,
206 enum wined3d_sm4_register_type
208 WINED3D_SM4_RT_TEMP = 0x0,
209 WINED3D_SM4_RT_INPUT = 0x1,
210 WINED3D_SM4_RT_OUTPUT = 0x2,
211 WINED3D_SM4_RT_IMMCONST = 0x4,
212 WINED3D_SM4_RT_SAMPLER = 0x6,
213 WINED3D_SM4_RT_RESOURCE = 0x7,
214 WINED3D_SM4_RT_CONSTBUFFER = 0x8,
215 WINED3D_SM4_RT_IMMCONSTBUFFER = 0x9,
216 WINED3D_SM4_RT_PRIMID = 0xb,
217 WINED3D_SM4_RT_DEPTHOUT = 0xc,
218 WINED3D_SM4_RT_NULL = 0xd,
219 WINED3D_SM5_RT_FORK_INSTANCE_ID = 0x17,
220 WINED3D_SM5_RT_UAV = 0x1e,
223 enum wined3d_sm4_output_primitive_type
225 WINED3D_SM4_OUTPUT_PT_POINTLIST = 0x1,
226 WINED3D_SM4_OUTPUT_PT_LINELIST = 0x3,
227 WINED3D_SM4_OUTPUT_PT_TRIANGLESTRIP = 0x5,
230 enum wined3d_sm4_input_primitive_type
232 WINED3D_SM4_INPUT_PT_POINT = 0x1,
233 WINED3D_SM4_INPUT_PT_LINE = 0x2,
234 WINED3D_SM4_INPUT_PT_TRIANGLE = 0x3,
235 WINED3D_SM4_INPUT_PT_LINEADJ = 0x6,
236 WINED3D_SM4_INPUT_PT_TRIANGLEADJ = 0x7,
239 enum wined3d_sm4_swizzle_type
241 WINED3D_SM4_SWIZZLE_NONE = 0x0,
242 WINED3D_SM4_SWIZZLE_VEC4 = 0x1,
243 WINED3D_SM4_SWIZZLE_SCALAR = 0x2,
246 enum wined3d_sm4_immconst_type
248 WINED3D_SM4_IMMCONST_SCALAR = 0x1,
249 WINED3D_SM4_IMMCONST_VEC4 = 0x2,
252 enum wined3d_sm4_resource_type
254 WINED3D_SM4_RESOURCE_BUFFER = 0x1,
255 WINED3D_SM4_RESOURCE_TEXTURE_1D = 0x2,
256 WINED3D_SM4_RESOURCE_TEXTURE_2D = 0x3,
257 WINED3D_SM4_RESOURCE_TEXTURE_2DMS = 0x4,
258 WINED3D_SM4_RESOURCE_TEXTURE_3D = 0x5,
259 WINED3D_SM4_RESOURCE_TEXTURE_CUBE = 0x6,
260 WINED3D_SM4_RESOURCE_TEXTURE_1DARRAY = 0x7,
261 WINED3D_SM4_RESOURCE_TEXTURE_2DARRAY = 0x8,
262 WINED3D_SM4_RESOURCE_TEXTURE_2DMSARRAY = 0x9,
265 enum wined3d_sm4_data_type
267 WINED3D_SM4_DATA_UNORM = 0x1,
268 WINED3D_SM4_DATA_SNORM = 0x2,
269 WINED3D_SM4_DATA_INT = 0x3,
270 WINED3D_SM4_DATA_UINT = 0x4,
271 WINED3D_SM4_DATA_FLOAT = 0x5,
274 enum wined3d_sm4_sampler_mode
276 WINED3D_SM4_SAMPLER_DEFAULT = 0x0,
277 WINED3D_SM4_SAMPLER_COMPARISON = 0x1,
280 enum wined3d_sm4_shader_data_type
282 WINED3D_SM4_SHADER_DATA_IMMEDIATE_CONSTANT_BUFFER = 0x3,
283 WINED3D_SM4_SHADER_DATA_MESSAGE = 0x4,
286 struct wined3d_shader_src_param_entry
288 struct list entry;
289 struct wined3d_shader_src_param param;
292 struct wined3d_sm4_data
294 struct wined3d_shader_version shader_version;
295 const DWORD *end;
297 unsigned int output_map[MAX_REG_OUTPUT];
299 struct wined3d_shader_src_param src_param[5];
300 struct wined3d_shader_dst_param dst_param[2];
301 struct list src_free;
302 struct list src;
303 struct wined3d_shader_immediate_constant_buffer icb;
306 struct wined3d_sm4_opcode_info
308 enum wined3d_sm4_opcode opcode;
309 enum WINED3D_SHADER_INSTRUCTION_HANDLER handler_idx;
310 const char *dst_info;
311 const char *src_info;
315 * f -> WINED3D_DATA_FLOAT
316 * i -> WINED3D_DATA_INT
317 * u -> WINED3D_DATA_UINT
318 * R -> WINED3D_DATA_RESOURCE
319 * S -> WINED3D_DATA_SAMPLER
320 * U -> WINED3D_DATA_UAV
322 static const struct wined3d_sm4_opcode_info opcode_table[] =
324 {WINED3D_SM4_OP_ADD, WINED3DSIH_ADD, "f", "ff"},
325 {WINED3D_SM4_OP_AND, WINED3DSIH_AND, "u", "uu"},
326 {WINED3D_SM4_OP_BREAK, WINED3DSIH_BREAK, "", ""},
327 {WINED3D_SM4_OP_BREAKC, WINED3DSIH_BREAKP, "", "u"},
328 {WINED3D_SM4_OP_CUT, WINED3DSIH_CUT, "", ""},
329 {WINED3D_SM4_OP_DERIV_RTX, WINED3DSIH_DSX, "f", "f"},
330 {WINED3D_SM4_OP_DERIV_RTY, WINED3DSIH_DSY, "f", "f"},
331 {WINED3D_SM4_OP_DISCARD, WINED3DSIH_TEXKILL, "", "u"},
332 {WINED3D_SM4_OP_DIV, WINED3DSIH_DIV, "f", "ff"},
333 {WINED3D_SM4_OP_DP2, WINED3DSIH_DP2, "f", "ff"},
334 {WINED3D_SM4_OP_DP3, WINED3DSIH_DP3, "f", "ff"},
335 {WINED3D_SM4_OP_DP4, WINED3DSIH_DP4, "f", "ff"},
336 {WINED3D_SM4_OP_ELSE, WINED3DSIH_ELSE, "", ""},
337 {WINED3D_SM4_OP_EMIT, WINED3DSIH_EMIT, "", ""},
338 {WINED3D_SM4_OP_ENDIF, WINED3DSIH_ENDIF, "", ""},
339 {WINED3D_SM4_OP_ENDLOOP, WINED3DSIH_ENDLOOP, "", ""},
340 {WINED3D_SM4_OP_EQ, WINED3DSIH_EQ, "u", "ff"},
341 {WINED3D_SM4_OP_EXP, WINED3DSIH_EXP, "f", "f"},
342 {WINED3D_SM4_OP_FRC, WINED3DSIH_FRC, "f", "f"},
343 {WINED3D_SM4_OP_FTOI, WINED3DSIH_FTOI, "i", "f"},
344 {WINED3D_SM4_OP_FTOU, WINED3DSIH_FTOU, "u", "f"},
345 {WINED3D_SM4_OP_GE, WINED3DSIH_GE, "u", "ff"},
346 {WINED3D_SM4_OP_IADD, WINED3DSIH_IADD, "i", "ii"},
347 {WINED3D_SM4_OP_IF, WINED3DSIH_IF, "", "u"},
348 {WINED3D_SM4_OP_IEQ, WINED3DSIH_IEQ, "u", "ii"},
349 {WINED3D_SM4_OP_IGE, WINED3DSIH_IGE, "u", "ii"},
350 {WINED3D_SM4_OP_ILT, WINED3DSIH_ILT, "u", "ii"},
351 {WINED3D_SM4_OP_IMAD, WINED3DSIH_IMAD, "i", "iii"},
352 {WINED3D_SM4_OP_IMAX, WINED3DSIH_IMAX, "i", "ii"},
353 {WINED3D_SM4_OP_IMIN, WINED3DSIH_IMIN, "i", "ii"},
354 {WINED3D_SM4_OP_IMUL, WINED3DSIH_IMUL, "ii", "ii"},
355 {WINED3D_SM4_OP_INE, WINED3DSIH_INE, "u", "ii"},
356 {WINED3D_SM4_OP_INEG, WINED3DSIH_INEG, "i", "i"},
357 {WINED3D_SM4_OP_ISHL, WINED3DSIH_ISHL, "i", "ii"},
358 {WINED3D_SM4_OP_ITOF, WINED3DSIH_ITOF, "f", "i"},
359 {WINED3D_SM4_OP_LD, WINED3DSIH_LD, "u", "iR"},
360 {WINED3D_SM4_OP_LD2DMS, WINED3DSIH_LD2DMS, "u", "iRi"},
361 {WINED3D_SM4_OP_LOG, WINED3DSIH_LOG, "f", "f"},
362 {WINED3D_SM4_OP_LOOP, WINED3DSIH_LOOP, "", ""},
363 {WINED3D_SM4_OP_LT, WINED3DSIH_LT, "u", "ff"},
364 {WINED3D_SM4_OP_MAD, WINED3DSIH_MAD, "f", "fff"},
365 {WINED3D_SM4_OP_MIN, WINED3DSIH_MIN, "f", "ff"},
366 {WINED3D_SM4_OP_MAX, WINED3DSIH_MAX, "f", "ff"},
367 {WINED3D_SM4_OP_SHADER_DATA, WINED3DSIH_DCL_IMMEDIATE_CONSTANT_BUFFER, "", ""},
368 {WINED3D_SM4_OP_MOV, WINED3DSIH_MOV, "f", "f"},
369 {WINED3D_SM4_OP_MOVC, WINED3DSIH_MOVC, "f", "uff"},
370 {WINED3D_SM4_OP_MUL, WINED3DSIH_MUL, "f", "ff"},
371 {WINED3D_SM4_OP_NE, WINED3DSIH_NE, "u", "ff"},
372 {WINED3D_SM4_OP_NOT, WINED3DSIH_NOT, "u", "u"},
373 {WINED3D_SM4_OP_OR, WINED3DSIH_OR, "u", "uu"},
374 {WINED3D_SM4_OP_RESINFO, WINED3DSIH_RESINFO, "f", "iR"},
375 {WINED3D_SM4_OP_RET, WINED3DSIH_RET, "", ""},
376 {WINED3D_SM4_OP_ROUND_NI, WINED3DSIH_ROUND_NI, "f", "f"},
377 {WINED3D_SM4_OP_ROUND_PI, WINED3DSIH_ROUND_PI, "f", "f"},
378 {WINED3D_SM4_OP_ROUND_Z, WINED3DSIH_ROUND_Z, "f", "f"},
379 {WINED3D_SM4_OP_RSQ, WINED3DSIH_RSQ, "f", "f"},
380 {WINED3D_SM4_OP_SAMPLE, WINED3DSIH_SAMPLE, "u", "fRS"},
381 {WINED3D_SM4_OP_SAMPLE_C, WINED3DSIH_SAMPLE_C, "f", "fRSf"},
382 {WINED3D_SM4_OP_SAMPLE_C_LZ, WINED3DSIH_SAMPLE_C_LZ, "f", "fRSf"},
383 {WINED3D_SM4_OP_SAMPLE_LOD, WINED3DSIH_SAMPLE_LOD, "u", "fRSf"},
384 {WINED3D_SM4_OP_SAMPLE_GRAD, WINED3DSIH_SAMPLE_GRAD, "u", "fRSff"},
385 {WINED3D_SM4_OP_SAMPLE_B, WINED3DSIH_SAMPLE_B, "u", "fRSf"},
386 {WINED3D_SM4_OP_SQRT, WINED3DSIH_SQRT, "f", "f"},
387 {WINED3D_SM4_OP_SINCOS, WINED3DSIH_SINCOS, "ff", "f"},
388 {WINED3D_SM4_OP_UDIV, WINED3DSIH_UDIV, "uu", "uu"},
389 {WINED3D_SM4_OP_UGE, WINED3DSIH_UGE, "u", "uu"},
390 {WINED3D_SM4_OP_USHR, WINED3DSIH_USHR, "u", "uu"},
391 {WINED3D_SM4_OP_UTOF, WINED3DSIH_UTOF, "f", "u"},
392 {WINED3D_SM4_OP_XOR, WINED3DSIH_XOR, "u", "uu"},
393 {WINED3D_SM4_OP_DCL_RESOURCE, WINED3DSIH_DCL, "R", ""},
394 {WINED3D_SM4_OP_DCL_CONSTANT_BUFFER, WINED3DSIH_DCL_CONSTANT_BUFFER, "", ""},
395 {WINED3D_SM4_OP_DCL_SAMPLER, WINED3DSIH_DCL_SAMPLER, "", ""},
396 {WINED3D_SM4_OP_DCL_OUTPUT_TOPOLOGY, WINED3DSIH_DCL_OUTPUT_TOPOLOGY, "", ""},
397 {WINED3D_SM4_OP_DCL_INPUT_PRIMITIVE, WINED3DSIH_DCL_INPUT_PRIMITIVE, "", ""},
398 {WINED3D_SM4_OP_DCL_VERTICES_OUT, WINED3DSIH_DCL_VERTICES_OUT, "", ""},
399 {WINED3D_SM4_OP_DCL_INPUT, WINED3DSIH_DCL_INPUT, "", ""},
400 {WINED3D_SM4_OP_DCL_INPUT_SGV, WINED3DSIH_DCL_INPUT_SGV, "", ""},
401 {WINED3D_SM4_OP_DCL_INPUT_SIV, WINED3DSIH_DCL_INPUT_SIV, "", ""},
402 {WINED3D_SM4_OP_DCL_INPUT_PS, WINED3DSIH_DCL_INPUT_PS, "", ""},
403 {WINED3D_SM4_OP_DCL_INPUT_PS_SGV, WINED3DSIH_DCL_INPUT_PS_SGV, "", ""},
404 {WINED3D_SM4_OP_DCL_INPUT_PS_SIV, WINED3DSIH_DCL_INPUT_PS_SIV, "", ""},
405 {WINED3D_SM4_OP_DCL_OUTPUT, WINED3DSIH_DCL_OUTPUT, "", ""},
406 {WINED3D_SM4_OP_DCL_OUTPUT_SIV, WINED3DSIH_DCL_OUTPUT_SIV, "", ""},
407 {WINED3D_SM4_OP_DCL_TEMPS, WINED3DSIH_DCL_TEMPS, "", ""},
408 {WINED3D_SM4_OP_DCL_GLOBAL_FLAGS, WINED3DSIH_DCL_GLOBAL_FLAGS, "", ""},
409 {WINED3D_SM5_OP_HS_DECLS, WINED3DSIH_HS_DECLS, "", ""},
410 {WINED3D_SM5_OP_HS_FORK_PHASE, WINED3DSIH_HS_FORK_PHASE, "", ""},
411 {WINED3D_SM5_OP_DERIV_RTX_COARSE, WINED3DSIH_DSX_COARSE, "f", "f"},
412 {WINED3D_SM5_OP_DERIV_RTX_FINE, WINED3DSIH_DSX_FINE, "f", "f"},
413 {WINED3D_SM5_OP_DERIV_RTY_COARSE, WINED3DSIH_DSY_COARSE, "f", "f"},
414 {WINED3D_SM5_OP_DERIV_RTY_FINE, WINED3DSIH_DSY_FINE, "f", "f"},
415 {WINED3D_SM5_OP_DCL_INPUT_CONTROL_POINT_COUNT, WINED3DSIH_DCL_INPUT_CONTROL_POINT_COUNT, "", ""},
416 {WINED3D_SM5_OP_DCL_OUTPUT_CONTROL_POINT_COUNT, WINED3DSIH_DCL_OUTPUT_CONTROL_POINT_COUNT, "", ""},
417 {WINED3D_SM5_OP_DCL_HS_MAX_TESSFACTOR, WINED3DSIH_DCL_HS_MAX_TESSFACTOR, "", ""},
418 {WINED3D_SM5_OP_DCL_HS_FORK_PHASE_INSTANCE_COUNT, WINED3DSIH_DCL_HS_FORK_PHASE_INSTANCE_COUNT, "", ""},
419 {WINED3D_SM5_OP_DCL_UAV_TYPED, WINED3DSIH_DCL_UAV_TYPED, "", ""},
420 {WINED3D_SM5_OP_DCL_RESOURCE_STRUCTURED, WINED3DSIH_DCL_RESOURCE_STRUCTURED, "", ""},
421 {WINED3D_SM5_OP_STORE_UAV_TYPED, WINED3DSIH_STORE_UAV_TYPED, "", "Uif"},
422 {WINED3D_SM5_OP_LD_STRUCTURED, WINED3DSIH_LD_STRUCTURED, "u", "uuR"},
425 static const enum wined3d_shader_register_type register_type_table[] =
427 /* WINED3D_SM4_RT_TEMP */ WINED3DSPR_TEMP,
428 /* WINED3D_SM4_RT_INPUT */ WINED3DSPR_INPUT,
429 /* WINED3D_SM4_RT_OUTPUT */ WINED3DSPR_OUTPUT,
430 /* UNKNOWN */ 0,
431 /* WINED3D_SM4_RT_IMMCONST */ WINED3DSPR_IMMCONST,
432 /* UNKNOWN */ 0,
433 /* WINED3D_SM4_RT_SAMPLER */ WINED3DSPR_SAMPLER,
434 /* WINED3D_SM4_RT_RESOURCE */ WINED3DSPR_RESOURCE,
435 /* WINED3D_SM4_RT_CONSTBUFFER */ WINED3DSPR_CONSTBUFFER,
436 /* WINED3D_SM4_RT_IMMCONSTBUFFER */ WINED3DSPR_IMMCONSTBUFFER,
437 /* UNKNOWN */ 0,
438 /* WINED3D_SM4_RT_PRIMID */ WINED3DSPR_PRIMID,
439 /* WINED3D_SM4_RT_DEPTHOUT */ WINED3DSPR_DEPTHOUT,
440 /* WINED3D_SM4_RT_NULL */ WINED3DSPR_NULL,
441 /* UNKNOWN */ 0,
442 /* UNKNOWN */ 0,
443 /* UNKNOWN */ 0,
444 /* UNKNOWN */ 0,
445 /* UNKNOWN */ 0,
446 /* UNKNOWN */ 0,
447 /* UNKNOWN */ 0,
448 /* UNKNOWN */ 0,
449 /* UNKNOWN */ 0,
450 /* WINED3D_SM5_RT_FORK_INSTANCE_ID */ WINED3DSPR_FORKINSTID,
451 /* UNKNOWN */ 0,
452 /* UNKNOWN */ 0,
453 /* UNKNOWN */ 0,
454 /* UNKNOWN */ 0,
455 /* UNKNOWN */ 0,
456 /* UNKNOWN */ 0,
457 /* WINED3D_SM5_RT_UAV */ WINED3DSPR_UAV,
460 static const enum wined3d_primitive_type output_primitive_type_table[] =
462 /* UNKNOWN */ WINED3D_PT_UNDEFINED,
463 /* WINED3D_SM4_OUTPUT_PT_POINTLIST */ WINED3D_PT_POINTLIST,
464 /* UNKNOWN */ WINED3D_PT_UNDEFINED,
465 /* WINED3D_SM4_OUTPUT_PT_LINELIST */ WINED3D_PT_LINELIST,
466 /* UNKNOWN */ WINED3D_PT_UNDEFINED,
467 /* WINED3D_SM4_OUTPUT_PT_TRIANGLESTRIP */ WINED3D_PT_TRIANGLESTRIP,
470 static const enum wined3d_primitive_type input_primitive_type_table[] =
472 /* UNKNOWN */ WINED3D_PT_UNDEFINED,
473 /* WINED3D_SM4_INPUT_PT_POINT */ WINED3D_PT_POINTLIST,
474 /* WINED3D_SM4_INPUT_PT_LINE */ WINED3D_PT_LINELIST,
475 /* WINED3D_SM4_INPUT_PT_TRIANGLE */ WINED3D_PT_TRIANGLELIST,
476 /* UNKNOWN */ WINED3D_PT_UNDEFINED,
477 /* UNKNOWN */ WINED3D_PT_UNDEFINED,
478 /* WINED3D_SM4_INPUT_PT_LINEADJ */ WINED3D_PT_LINELIST_ADJ,
479 /* WINED3D_SM4_INPUT_PT_TRIANGLEADJ */ WINED3D_PT_TRIANGLELIST_ADJ,
482 static const enum wined3d_shader_resource_type resource_type_table[] =
484 /* 0 */ WINED3D_SHADER_RESOURCE_NONE,
485 /* WINED3D_SM4_RESOURCE_BUFFER */ WINED3D_SHADER_RESOURCE_BUFFER,
486 /* WINED3D_SM4_RESOURCE_TEXTURE_1D */ WINED3D_SHADER_RESOURCE_TEXTURE_1D,
487 /* WINED3D_SM4_RESOURCE_TEXTURE_2D */ WINED3D_SHADER_RESOURCE_TEXTURE_2D,
488 /* WINED3D_SM4_RESOURCE_TEXTURE_2DMS */ WINED3D_SHADER_RESOURCE_TEXTURE_2DMS,
489 /* WINED3D_SM4_RESOURCE_TEXTURE_3D */ WINED3D_SHADER_RESOURCE_TEXTURE_3D,
490 /* WINED3D_SM4_RESOURCE_TEXTURE_CUBE */ WINED3D_SHADER_RESOURCE_TEXTURE_CUBE,
491 /* WINED3D_SM4_RESOURCE_TEXTURE_1DARRAY */ WINED3D_SHADER_RESOURCE_TEXTURE_1DARRAY,
492 /* WINED3D_SM4_RESOURCE_TEXTURE_2DARRAY */ WINED3D_SHADER_RESOURCE_TEXTURE_2DARRAY,
493 /* WINED3D_SM4_RESOURCE_TEXTURE_2DMSARRAY */ WINED3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY,
496 static const enum wined3d_data_type data_type_table[] =
498 /* 0 */ WINED3D_DATA_FLOAT,
499 /* WINED3D_SM4_DATA_UNORM */ WINED3D_DATA_UNORM,
500 /* WINED3D_SM4_DATA_SNORM */ WINED3D_DATA_SNORM,
501 /* WINED3D_SM4_DATA_INT */ WINED3D_DATA_INT,
502 /* WINED3D_SM4_DATA_UINT */ WINED3D_DATA_UINT,
503 /* WINED3D_SM4_DATA_FLOAT */ WINED3D_DATA_FLOAT,
506 static BOOL shader_sm4_read_src_param(struct wined3d_sm4_data *priv, const DWORD **ptr,
507 enum wined3d_data_type data_type, struct wined3d_shader_src_param *src_param);
509 static const struct wined3d_sm4_opcode_info *get_opcode_info(enum wined3d_sm4_opcode opcode)
511 unsigned int i;
513 for (i = 0; i < sizeof(opcode_table) / sizeof(*opcode_table); ++i)
515 if (opcode == opcode_table[i].opcode) return &opcode_table[i];
518 return NULL;
521 static void map_register(const struct wined3d_sm4_data *priv, struct wined3d_shader_register *reg)
523 switch (priv->shader_version.type)
525 case WINED3D_SHADER_TYPE_PIXEL:
526 if (reg->type == WINED3DSPR_OUTPUT)
528 unsigned int reg_idx = reg->idx[0].offset;
530 if (reg_idx >= ARRAY_SIZE(priv->output_map))
532 ERR("Invalid output index %u.\n", reg_idx);
533 break;
536 reg->type = WINED3DSPR_COLOROUT;
537 reg->idx[0].offset = priv->output_map[reg_idx];
539 break;
541 default:
542 break;
546 static enum wined3d_data_type map_data_type(char t)
548 switch (t)
550 case 'f':
551 return WINED3D_DATA_FLOAT;
552 case 'i':
553 return WINED3D_DATA_INT;
554 case 'u':
555 return WINED3D_DATA_UINT;
556 case 'R':
557 return WINED3D_DATA_RESOURCE;
558 case 'S':
559 return WINED3D_DATA_SAMPLER;
560 case 'U':
561 return WINED3D_DATA_UAV;
562 default:
563 ERR("Invalid data type '%c'.\n", t);
564 return WINED3D_DATA_FLOAT;
568 static void *shader_sm4_init(const DWORD *byte_code, const struct wined3d_shader_signature *output_signature)
570 struct wined3d_sm4_data *priv;
571 unsigned int i;
573 if (!(priv = HeapAlloc(GetProcessHeap(), 0, sizeof(*priv))))
575 ERR("Failed to allocate private data\n");
576 return NULL;
579 memset(priv->output_map, 0xff, sizeof(priv->output_map));
580 for (i = 0; i < output_signature->element_count; ++i)
582 struct wined3d_shader_signature_element *e = &output_signature->elements[i];
584 if (e->register_idx >= ARRAY_SIZE(priv->output_map))
586 WARN("Invalid output index %u.\n", e->register_idx);
587 continue;
590 priv->output_map[e->register_idx] = e->semantic_idx;
593 list_init(&priv->src_free);
594 list_init(&priv->src);
596 return priv;
599 static void shader_sm4_free(void *data)
601 struct wined3d_shader_src_param_entry *e1, *e2;
602 struct wined3d_sm4_data *priv = data;
604 list_move_head(&priv->src_free, &priv->src);
605 LIST_FOR_EACH_ENTRY_SAFE(e1, e2, &priv->src_free, struct wined3d_shader_src_param_entry, entry)
607 HeapFree(GetProcessHeap(), 0, e1);
609 HeapFree(GetProcessHeap(), 0, priv);
612 static struct wined3d_shader_src_param *get_src_param(struct wined3d_sm4_data *priv)
614 struct wined3d_shader_src_param_entry *e;
615 struct list *elem;
617 if (!list_empty(&priv->src_free))
619 elem = list_head(&priv->src_free);
620 list_remove(elem);
622 else
624 if (!(e = HeapAlloc(GetProcessHeap(), 0, sizeof(*e))))
625 return NULL;
626 elem = &e->entry;
629 list_add_tail(&priv->src, elem);
630 e = LIST_ENTRY(elem, struct wined3d_shader_src_param_entry, entry);
631 return &e->param;
634 static void shader_sm4_read_header(void *data, const DWORD **ptr, struct wined3d_shader_version *shader_version)
636 struct wined3d_sm4_data *priv = data;
637 DWORD version_token;
639 priv->end = *ptr;
641 version_token = *(*ptr)++;
642 TRACE("Version: 0x%08x.\n", version_token);
644 TRACE("Token count: %u.\n", **ptr);
645 priv->end += *(*ptr)++;
647 switch (version_token >> 16)
649 case WINED3D_SM4_PS:
650 priv->shader_version.type = WINED3D_SHADER_TYPE_PIXEL;
651 break;
653 case WINED3D_SM4_VS:
654 priv->shader_version.type = WINED3D_SHADER_TYPE_VERTEX;
655 break;
657 case WINED3D_SM4_GS:
658 priv->shader_version.type = WINED3D_SHADER_TYPE_GEOMETRY;
659 break;
661 case WINED3D_SM5_HS:
662 priv->shader_version.type = WINED3D_SHADER_TYPE_HULL;
663 break;
665 default:
666 FIXME("Unrecognized shader type %#x.\n", version_token >> 16);
668 priv->shader_version.major = WINED3D_SM4_VERSION_MAJOR(version_token);
669 priv->shader_version.minor = WINED3D_SM4_VERSION_MINOR(version_token);
671 *shader_version = priv->shader_version;
674 static BOOL shader_sm4_read_reg_idx(struct wined3d_sm4_data *priv, const DWORD **ptr,
675 DWORD addressing, struct wined3d_shader_register_index *reg_idx)
677 if (addressing & WINED3D_SM4_ADDRESSING_RELATIVE)
679 struct wined3d_shader_src_param *rel_addr = get_src_param(priv);
681 if (!(reg_idx->rel_addr = rel_addr))
683 ERR("Failed to get src param for relative addressing.\n");
684 return FALSE;
687 if (addressing & WINED3D_SM4_ADDRESSING_OFFSET)
688 reg_idx->offset = *(*ptr)++;
689 else
690 reg_idx->offset = 0;
691 shader_sm4_read_src_param(priv, ptr, WINED3D_DATA_INT, rel_addr);
693 else
695 reg_idx->rel_addr = NULL;
696 reg_idx->offset = *(*ptr)++;
699 return TRUE;
702 static BOOL shader_sm4_read_param(struct wined3d_sm4_data *priv, const DWORD **ptr,
703 enum wined3d_data_type data_type, struct wined3d_shader_register *param,
704 enum wined3d_shader_src_modifier *modifier)
706 enum wined3d_sm4_register_type register_type;
707 DWORD token = *(*ptr)++;
708 DWORD order;
710 register_type = (token & WINED3D_SM4_REGISTER_TYPE_MASK) >> WINED3D_SM4_REGISTER_TYPE_SHIFT;
711 if (register_type >= sizeof(register_type_table) / sizeof(*register_type_table))
713 FIXME("Unhandled register type %#x.\n", register_type);
714 param->type = WINED3DSPR_TEMP;
716 else
718 param->type = register_type_table[register_type];
720 param->data_type = data_type;
722 if (token & WINED3D_SM4_REGISTER_MODIFIER)
724 DWORD m = *(*ptr)++;
726 switch (m)
728 case 0x41:
729 *modifier = WINED3DSPSM_NEG;
730 break;
732 case 0x81:
733 *modifier = WINED3DSPSM_ABS;
734 break;
736 case 0xc1:
737 *modifier = WINED3DSPSM_ABSNEG;
738 break;
740 default:
741 FIXME("Skipping modifier 0x%08x.\n", m);
742 *modifier = WINED3DSPSM_NONE;
743 break;
746 else
748 *modifier = WINED3DSPSM_NONE;
751 order = (token & WINED3D_SM4_REGISTER_ORDER_MASK) >> WINED3D_SM4_REGISTER_ORDER_SHIFT;
753 if (order < 1)
754 param->idx[0].offset = ~0U;
755 else
757 DWORD addressing = (token & WINED3D_SM4_ADDRESSING_MASK0) >> WINED3D_SM4_ADDRESSING_SHIFT0;
758 if (!(shader_sm4_read_reg_idx(priv, ptr, addressing, &param->idx[0])))
760 ERR("Failed to read register index.\n");
761 return FALSE;
765 if (order < 2)
766 param->idx[1].offset = ~0U;
767 else
769 DWORD addressing = (token & WINED3D_SM4_ADDRESSING_MASK1) >> WINED3D_SM4_ADDRESSING_SHIFT1;
770 if (!(shader_sm4_read_reg_idx(priv, ptr, addressing, &param->idx[1])))
772 ERR("Failed to read register index.\n");
773 return FALSE;
777 if (order > 2)
778 FIXME("Unhandled order %u.\n", order);
780 if (register_type == WINED3D_SM4_RT_IMMCONST)
782 enum wined3d_sm4_immconst_type immconst_type =
783 (token & WINED3D_SM4_IMMCONST_TYPE_MASK) >> WINED3D_SM4_IMMCONST_TYPE_SHIFT;
785 switch (immconst_type)
787 case WINED3D_SM4_IMMCONST_SCALAR:
788 param->immconst_type = WINED3D_IMMCONST_SCALAR;
789 memcpy(param->immconst_data, *ptr, 1 * sizeof(DWORD));
790 *ptr += 1;
791 break;
793 case WINED3D_SM4_IMMCONST_VEC4:
794 param->immconst_type = WINED3D_IMMCONST_VEC4;
795 memcpy(param->immconst_data, *ptr, 4 * sizeof(DWORD));
796 *ptr += 4;
797 break;
799 default:
800 FIXME("Unhandled immediate constant type %#x.\n", immconst_type);
801 break;
805 map_register(priv, param);
807 return TRUE;
810 static BOOL shader_sm4_read_src_param(struct wined3d_sm4_data *priv, const DWORD **ptr,
811 enum wined3d_data_type data_type, struct wined3d_shader_src_param *src_param)
813 DWORD token = **ptr;
815 if (!shader_sm4_read_param(priv, ptr, data_type, &src_param->reg, &src_param->modifiers))
817 ERR("Failed to read parameter.\n");
818 return FALSE;
821 if (src_param->reg.type == WINED3DSPR_IMMCONST)
823 src_param->swizzle = WINED3DSP_NOSWIZZLE;
825 else
827 enum wined3d_sm4_swizzle_type swizzle_type =
828 (token & WINED3D_SM4_SWIZZLE_TYPE_MASK) >> WINED3D_SM4_SWIZZLE_TYPE_SHIFT;
830 switch (swizzle_type)
832 case WINED3D_SM4_SWIZZLE_NONE:
833 src_param->swizzle = WINED3DSP_NOSWIZZLE;
834 break;
836 case WINED3D_SM4_SWIZZLE_SCALAR:
837 src_param->swizzle = (token & WINED3D_SM4_SWIZZLE_MASK) >> WINED3D_SM4_SWIZZLE_SHIFT;
838 src_param->swizzle = (src_param->swizzle & 0x3) * 0x55;
839 break;
841 case WINED3D_SM4_SWIZZLE_VEC4:
842 src_param->swizzle = (token & WINED3D_SM4_SWIZZLE_MASK) >> WINED3D_SM4_SWIZZLE_SHIFT;
843 break;
845 default:
846 FIXME("Unhandled swizzle type %#x.\n", swizzle_type);
847 break;
851 return TRUE;
854 static BOOL shader_sm4_read_dst_param(struct wined3d_sm4_data *priv, const DWORD **ptr,
855 enum wined3d_data_type data_type, struct wined3d_shader_dst_param *dst_param)
857 enum wined3d_shader_src_modifier modifier;
858 DWORD token = **ptr;
860 if (!shader_sm4_read_param(priv, ptr, data_type, &dst_param->reg, &modifier))
862 ERR("Failed to read parameter.\n");
863 return FALSE;
866 if (modifier != WINED3DSPSM_NONE)
868 ERR("Invalid source modifier %#x on destination register.\n", modifier);
869 return FALSE;
872 dst_param->write_mask = (token & WINED3D_SM4_WRITEMASK_MASK) >> WINED3D_SM4_WRITEMASK_SHIFT;
873 dst_param->modifiers = 0;
874 dst_param->shift = 0;
876 return TRUE;
879 static void shader_sm4_read_instruction(void *data, const DWORD **ptr, struct wined3d_shader_instruction *ins)
881 const struct wined3d_sm4_opcode_info *opcode_info;
882 struct wined3d_sm4_data *priv = data;
883 DWORD opcode_token, opcode;
884 const DWORD *p;
885 UINT i, len;
887 list_move_head(&priv->src_free, &priv->src);
889 opcode_token = *(*ptr)++;
890 opcode = opcode_token & WINED3D_SM4_OPCODE_MASK;
892 len = ((opcode_token & WINED3D_SM4_INSTRUCTION_LENGTH_MASK) >> WINED3D_SM4_INSTRUCTION_LENGTH_SHIFT);
893 if (!len)
894 len = **ptr;
895 --len;
897 if (TRACE_ON(d3d_bytecode))
899 TRACE_(d3d_bytecode)("[ %08x ", opcode_token);
900 for (i = 0; i < len; ++i)
902 TRACE_(d3d_bytecode)("%08x ", (*ptr)[i]);
904 TRACE_(d3d_bytecode)("]\n");
907 if (!(opcode_info = get_opcode_info(opcode)))
909 FIXME("Unrecognized opcode %#x, opcode_token 0x%08x.\n", opcode, opcode_token);
910 ins->handler_idx = WINED3DSIH_TABLE_SIZE;
911 *ptr += len;
912 return;
915 ins->handler_idx = opcode_info->handler_idx;
916 ins->flags = 0;
917 ins->coissue = 0;
918 ins->predicate = NULL;
919 ins->dst_count = strlen(opcode_info->dst_info);
920 ins->dst = priv->dst_param;
921 ins->src_count = strlen(opcode_info->src_info);
922 ins->src = priv->src_param;
923 memset(&ins->texel_offset, 0, sizeof(ins->texel_offset));
925 p = *ptr;
926 *ptr += len;
928 if (opcode_token & WINED3D_SM4_INSTRUCTION_MODIFIER)
930 static const DWORD recognized_bits = WINED3D_SM4_MODIFIER_AOFFIMMI
931 | WINED3D_SM4_AOFFIMMI_U_MASK
932 | WINED3D_SM4_AOFFIMMI_V_MASK
933 | WINED3D_SM4_AOFFIMMI_W_MASK;
934 DWORD modifier = *p++;
935 /* Bit fields are used for sign extension */
936 struct
938 int u : 4;
939 int v : 4;
940 int w : 4;
942 aoffimmi;
944 if (modifier & ~recognized_bits)
946 FIXME("Skipping modifier 0x%08x.\n", modifier);
948 else
950 aoffimmi.u = (modifier & WINED3D_SM4_AOFFIMMI_U_MASK) >> WINED3D_SM4_AOFFIMMI_U_SHIFT;
951 aoffimmi.v = (modifier & WINED3D_SM4_AOFFIMMI_V_MASK) >> WINED3D_SM4_AOFFIMMI_V_SHIFT;
952 aoffimmi.w = (modifier & WINED3D_SM4_AOFFIMMI_W_MASK) >> WINED3D_SM4_AOFFIMMI_W_SHIFT;
953 ins->texel_offset.u = aoffimmi.u;
954 ins->texel_offset.v = aoffimmi.v;
955 ins->texel_offset.w = aoffimmi.w;
959 if (opcode == WINED3D_SM4_OP_SHADER_DATA)
961 unsigned int icb_size;
962 enum wined3d_sm4_shader_data_type type;
964 type = (opcode_token & WINED3D_SM4_SHADER_DATA_TYPE_MASK) >> WINED3D_SM4_SHADER_DATA_TYPE_SHIFT;
965 if (type != WINED3D_SM4_SHADER_DATA_IMMEDIATE_CONSTANT_BUFFER)
967 FIXME("Unhandled shader data type %#x.\n", type);
968 ins->handler_idx = WINED3DSIH_TABLE_SIZE;
969 return;
972 ++p;
973 icb_size = len - 1;
974 if (icb_size % 4 || icb_size > MAX_IMMEDIATE_CONSTANT_BUFFER_SIZE)
976 FIXME("Unexpected immediate constant buffer size %u.\n", len);
977 ins->handler_idx = WINED3DSIH_TABLE_SIZE;
978 return;
981 priv->icb.element_count = len;
982 memcpy(priv->icb.data, p, sizeof(*p) * icb_size);
983 ins->declaration.icb = &priv->icb;
985 else if (opcode == WINED3D_SM4_OP_DCL_RESOURCE || opcode == WINED3D_SM5_OP_DCL_UAV_TYPED)
987 enum wined3d_sm4_resource_type resource_type;
988 enum wined3d_sm4_data_type data_type;
989 enum wined3d_data_type reg_data_type;
990 DWORD components;
992 resource_type = (opcode_token & WINED3D_SM4_RESOURCE_TYPE_MASK) >> WINED3D_SM4_RESOURCE_TYPE_SHIFT;
993 if (!resource_type || (resource_type >= ARRAY_SIZE(resource_type_table)))
995 FIXME("Unhandled resource type %#x.\n", resource_type);
996 ins->declaration.semantic.resource_type = WINED3D_SHADER_RESOURCE_NONE;
998 else
1000 ins->declaration.semantic.resource_type = resource_type_table[resource_type];
1002 reg_data_type = opcode == WINED3D_SM4_OP_DCL_RESOURCE ? WINED3D_DATA_RESOURCE : WINED3D_DATA_UAV;
1003 shader_sm4_read_dst_param(priv, &p, reg_data_type, &ins->declaration.semantic.reg);
1005 components = *p++;
1006 if ((components & 0xfff0) != (components & 0xf) * 0x1110)
1007 FIXME("Components (%#x) have different data types.\n", components);
1008 data_type = components & 0xf;
1010 if (!data_type || (data_type >= ARRAY_SIZE(data_type_table)))
1012 FIXME("Unhandled data type %#x.\n", data_type);
1013 ins->declaration.semantic.resource_data_type = WINED3D_DATA_FLOAT;
1015 else
1017 ins->declaration.semantic.resource_data_type = data_type_table[data_type];
1020 else if (opcode == WINED3D_SM5_OP_DCL_RESOURCE_STRUCTURED)
1022 shader_sm4_read_dst_param(priv, &p, WINED3D_DATA_RESOURCE, &ins->declaration.structured_resource.reg);
1023 ins->declaration.structured_resource.byte_stride = *p++;
1025 else if (opcode == WINED3D_SM4_OP_DCL_CONSTANT_BUFFER)
1027 shader_sm4_read_src_param(priv, &p, WINED3D_DATA_FLOAT, &ins->declaration.src);
1028 if (opcode_token & WINED3D_SM4_INDEX_TYPE_MASK)
1029 ins->flags |= WINED3DSI_INDEXED_DYNAMIC;
1031 else if (opcode == WINED3D_SM5_OP_DCL_HS_MAX_TESSFACTOR)
1033 ins->declaration.max_tessellation_factor = *(float *)p++;
1035 else if (opcode == WINED3D_SM4_OP_DCL_SAMPLER)
1037 ins->flags = (opcode_token & WINED3D_SM4_SAMPLER_MODE_MASK) >> WINED3D_SM4_SAMPLER_MODE_SHIFT;
1038 if (ins->flags & ~WINED3D_SM4_SAMPLER_COMPARISON)
1039 FIXME("Unhandled sampler mode %#x.\n", ins->flags);
1040 shader_sm4_read_dst_param(priv, &p, WINED3D_DATA_SAMPLER, &ins->declaration.dst);
1042 else if (opcode == WINED3D_SM4_OP_DCL_OUTPUT_TOPOLOGY)
1044 enum wined3d_sm4_output_primitive_type primitive_type;
1046 primitive_type = (opcode_token & WINED3D_SM4_PRIMITIVE_TYPE_MASK) >> WINED3D_SM4_PRIMITIVE_TYPE_SHIFT;
1047 if (primitive_type >= sizeof(output_primitive_type_table) / sizeof(*output_primitive_type_table))
1049 FIXME("Unhandled output primitive type %#x.\n", primitive_type);
1050 ins->declaration.primitive_type = WINED3D_PT_UNDEFINED;
1052 else
1054 ins->declaration.primitive_type = output_primitive_type_table[primitive_type];
1057 else if (opcode == WINED3D_SM5_OP_DCL_INPUT_CONTROL_POINT_COUNT
1058 || opcode == WINED3D_SM5_OP_DCL_OUTPUT_CONTROL_POINT_COUNT)
1060 ins->declaration.count = (opcode_token & WINED3D_SM5_CONTROL_POINT_COUNT_MASK)
1061 >> WINED3D_SM5_CONTROL_POINT_COUNT_SHIFT;
1063 else if (opcode == WINED3D_SM4_OP_DCL_INPUT_PRIMITIVE)
1065 enum wined3d_sm4_input_primitive_type primitive_type;
1067 primitive_type = (opcode_token & WINED3D_SM4_PRIMITIVE_TYPE_MASK) >> WINED3D_SM4_PRIMITIVE_TYPE_SHIFT;
1068 if (primitive_type >= sizeof(input_primitive_type_table) / sizeof(*input_primitive_type_table))
1070 FIXME("Unhandled input primitive type %#x.\n", primitive_type);
1071 ins->declaration.primitive_type = WINED3D_PT_UNDEFINED;
1073 else
1075 ins->declaration.primitive_type = input_primitive_type_table[primitive_type];
1078 else if (opcode == WINED3D_SM4_OP_DCL_INPUT_PS)
1080 ins->flags = (opcode_token & WINED3D_SM4_INTERPOLATION_MODE_MASK) >> WINED3D_SM4_INTERPOLATION_MODE_SHIFT;
1081 shader_sm4_read_dst_param(priv, &p, WINED3D_DATA_FLOAT, &ins->declaration.dst);
1083 else if (opcode == WINED3D_SM4_OP_DCL_INPUT_PS_SGV
1084 || opcode == WINED3D_SM4_OP_DCL_INPUT_SGV
1085 || opcode == WINED3D_SM4_OP_DCL_INPUT_SIV
1086 || opcode == WINED3D_SM4_OP_DCL_OUTPUT_SIV)
1088 shader_sm4_read_dst_param(priv, &p, WINED3D_DATA_FLOAT, &ins->declaration.register_semantic.reg);
1089 ins->declaration.register_semantic.sysval_semantic = *p++;
1091 else if (opcode == WINED3D_SM4_OP_DCL_INPUT_PS_SIV)
1093 ins->flags = (opcode_token & WINED3D_SM4_INTERPOLATION_MODE_MASK) >> WINED3D_SM4_INTERPOLATION_MODE_SHIFT;
1094 shader_sm4_read_dst_param(priv, &p, WINED3D_DATA_FLOAT, &ins->declaration.register_semantic.reg);
1095 ins->declaration.register_semantic.sysval_semantic = *p++;
1097 else if (opcode == WINED3D_SM4_OP_DCL_INPUT
1098 || opcode == WINED3D_SM4_OP_DCL_OUTPUT)
1100 shader_sm4_read_dst_param(priv, &p, WINED3D_DATA_FLOAT, &ins->declaration.dst);
1102 else if (opcode == WINED3D_SM4_OP_DCL_VERTICES_OUT
1103 || opcode == WINED3D_SM4_OP_DCL_TEMPS
1104 || opcode == WINED3D_SM5_OP_DCL_HS_FORK_PHASE_INSTANCE_COUNT)
1106 ins->declaration.count = *p++;
1108 else if (opcode == WINED3D_SM4_OP_DCL_GLOBAL_FLAGS)
1110 ins->flags = (opcode_token & WINED3D_SM4_GLOBAL_FLAGS_MASK) >> WINED3D_SM4_GLOBAL_FLAGS_SHIFT;
1112 else
1114 enum wined3d_shader_dst_modifier instruction_dst_modifier = WINED3DSPDM_NONE;
1116 ins->flags = (opcode_token & WINED3D_SM4_INSTRUCTION_FLAGS_MASK) >> WINED3D_SM4_INSTRUCTION_FLAGS_SHIFT;
1118 if (ins->flags & WINED3D_SM4_INSTRUCTION_FLAG_SATURATE)
1120 ins->flags &= ~WINED3D_SM4_INSTRUCTION_FLAG_SATURATE;
1121 instruction_dst_modifier = WINED3DSPDM_SATURATE;
1124 for (i = 0; i < ins->dst_count; ++i)
1126 if (!(shader_sm4_read_dst_param(priv, &p, map_data_type(opcode_info->dst_info[i]), &priv->dst_param[i])))
1128 ins->handler_idx = WINED3DSIH_TABLE_SIZE;
1129 return;
1131 priv->dst_param[i].modifiers |= instruction_dst_modifier;
1134 for (i = 0; i < ins->src_count; ++i)
1136 if (!(shader_sm4_read_src_param(priv, &p, map_data_type(opcode_info->src_info[i]), &priv->src_param[i])))
1138 ins->handler_idx = WINED3DSIH_TABLE_SIZE;
1139 return;
1145 static BOOL shader_sm4_is_end(void *data, const DWORD **ptr)
1147 struct wined3d_sm4_data *priv = data;
1148 return *ptr == priv->end;
1151 const struct wined3d_shader_frontend sm4_shader_frontend =
1153 shader_sm4_init,
1154 shader_sm4_free,
1155 shader_sm4_read_header,
1156 shader_sm4_read_instruction,
1157 shader_sm4_is_end,