1 /*
2 * Copyright 2011 Joakim Sindholt <opensource@zhasha.com>
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 * on the rights to use, copy, modify, merge, publish, distribute, sub
8 * license, and/or sell copies of the Software, and to permit persons to whom
9 * the 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 NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE. */
22
23 #ifndef _NINE_SHADER_H_
24 #define _NINE_SHADER_H_
25
26 #include "d3d9types.h"
27 #include "d3d9caps.h"
28 #include "nine_defines.h"
29 #include "nine_helpers.h"
30 #include "nine_state.h"
31 #include "pipe/p_state.h" /* PIPE_MAX_ATTRIBS */
32 #include "util/u_memory.h"
33 #include "tgsi/tgsi_ureg.h"
34
35 struct NineDevice9;
36 struct NineVertexDeclaration9;
37 struct ureg_program;
38
39 struct nine_lconstf /* NOTE: both pointers should be FREE'd by the user */
40 {
41 struct nine_range *ranges; /* single MALLOC, but next-pointers valid */
42 float *data;
43 };
44
45 struct nine_shader_constant_combination;
46
47 struct nine_shader_info
48 {
49 unsigned type; /* in, PIPE_SHADER_x */
50
51 uint8_t version; /* (major << 4) | minor */
52
53 const DWORD *byte_code; /* in, pointer to shader tokens */
54 DWORD byte_size; /* out, size of data at byte_code */
55
56 void *cso; /* out, pipe cso for bind_vs,fs_state */
57
58 uint16_t input_map[PIPE_MAX_ATTRIBS]; /* VS input -> NINE_DECLUSAGE_x */
59 uint8_t num_inputs; /* there may be unused inputs (NINE_DECLUSAGE_NONE) */
60
61 bool position_t; /* out, true if VP writes pre-transformed position */
62 bool point_size; /* out, true if VP writes point size */
63 float point_size_min;
64 float point_size_max;
65
66 uint32_t sampler_ps1xtypes; /* 2 bits per sampler */
67 uint16_t sampler_mask; /* out, which samplers are being used */
68 uint16_t sampler_mask_shadow; /* in, which samplers use depth compare */
69 uint8_t rt_mask; /* out, which render targets are being written */
70
71 uint8_t fog_enable;
72 uint8_t fog_mode;
73 uint8_t zfog;
74 uint8_t force_color_in_centroid;
75 uint8_t color_flatshade;
76 uint8_t projected; /* ps 1.1 to 1.3 */
77 uint16_t fetch4;
78 uint8_t alpha_test_emulation;
79 uint8_t clip_plane_emulation;
80 bool emulate_features;
81
82 unsigned const_i_base; /* in vec4 (16 byte) units */
83 unsigned const_b_base; /* in vec4 (16 byte) units */
84 unsigned const_used_size;
85
86 bool int_slots_used[NINE_MAX_CONST_I];
87 bool bool_slots_used[NINE_MAX_CONST_B];
88
89 unsigned const_float_slots;
90 unsigned const_int_slots;
91 unsigned const_bool_slots;
92
93 unsigned *const_ranges;
94
95 struct nine_lconstf lconstf; /* out, NOTE: members to be free'd by user */
96 uint8_t bumpenvmat_needed;
97
98 struct {
99 struct nine_shader_constant_combination* c_combination;
100 bool (*int_const_added)[NINE_MAX_CONST_I];
101 bool (*bool_const_added)[NINE_MAX_CONST_B];
102 } add_constants_defs;
103
104 bool swvp_on;
105
106 bool process_vertices;
107 struct NineVertexDeclaration9 *vdecl_out;
108 struct pipe_stream_output_info so;
109 };
110
111 struct nine_vs_output_info
112 {
113 BYTE output_semantic;
114 int output_semantic_index;
115 int mask;
116 int output_index;
117 };
118
119 void *
120 nine_create_shader_with_so_and_destroy(struct ureg_program *p,
121 struct pipe_context *pipe,
122 const struct pipe_stream_output_info *so);
123
124 HRESULT
125 nine_translate_shader(struct NineDevice9 *device,
126 struct nine_shader_info *,
127 struct pipe_context *);
128
129
130 struct nine_shader_variant
131 {
132 struct nine_shader_variant *next;
133 void *cso;
134 unsigned *const_ranges;
135 unsigned const_used_size;
136 uint64_t key;
137 };
138
139 static inline void *
nine_shader_variant_get(struct nine_shader_variant * list,unsigned ** const_ranges,unsigned * const_used_size,uint64_t key)140 nine_shader_variant_get(struct nine_shader_variant *list,
141 unsigned **const_ranges,
142 unsigned *const_used_size,
143 uint64_t key)
144 {
145 while (list->key != key && list->next)
146 list = list->next;
147 if (list->key == key) {
148 *const_ranges = list->const_ranges;
149 *const_used_size = list->const_used_size;
150 return list->cso;
151 }
152 return NULL;
153 }
154
155 static inline bool
nine_shader_variant_add(struct nine_shader_variant * list,uint64_t key,void * cso,unsigned * const_ranges,unsigned const_used_size)156 nine_shader_variant_add(struct nine_shader_variant *list,
157 uint64_t key, void *cso,
158 unsigned *const_ranges,
159 unsigned const_used_size)
160 {
161 while (list->next) {
162 assert(list->key != key);
163 list = list->next;
164 }
165 list->next = MALLOC_STRUCT(nine_shader_variant);
166 if (!list->next)
167 return false;
168 list->next->next = NULL;
169 list->next->key = key;
170 list->next->cso = cso;
171 list->next->const_ranges = const_ranges;
172 list->next->const_used_size = const_used_size;
173 return true;
174 }
175
176 static inline void
nine_shader_variants_free(struct nine_shader_variant * list)177 nine_shader_variants_free(struct nine_shader_variant *list)
178 {
179 while (list->next) {
180 struct nine_shader_variant *ptr = list->next;
181 list->next = ptr->next;
182 FREE(ptr);
183 }
184 }
185
186 struct nine_shader_variant_so
187 {
188 struct nine_shader_variant_so *next;
189 struct NineVertexDeclaration9 *vdecl;
190 struct pipe_stream_output_info so;
191 void *cso;
192 };
193
194 static inline void *
nine_shader_variant_so_get(struct nine_shader_variant_so * list,struct NineVertexDeclaration9 * vdecl,struct pipe_stream_output_info * so)195 nine_shader_variant_so_get(struct nine_shader_variant_so *list,
196 struct NineVertexDeclaration9 *vdecl,
197 struct pipe_stream_output_info *so)
198 {
199 while (list->vdecl != vdecl && list->next)
200 list = list->next;
201 if (list->vdecl == vdecl) {
202 *so = list->so;
203 return list->cso;
204 }
205 return NULL;
206 }
207
208 static inline bool
nine_shader_variant_so_add(struct nine_shader_variant_so * list,struct NineVertexDeclaration9 * vdecl,struct pipe_stream_output_info * so,void * cso)209 nine_shader_variant_so_add(struct nine_shader_variant_so *list,
210 struct NineVertexDeclaration9 *vdecl,
211 struct pipe_stream_output_info *so, void *cso)
212 {
213 if (list->vdecl == NULL) { /* first shader */
214 list->next = NULL;
215 nine_bind(&list->vdecl, vdecl);
216 list->so = *so;
217 list->cso = cso;
218 return true;
219 }
220 while (list->next) {
221 assert(list->vdecl != vdecl);
222 list = list->next;
223 }
224 list->next = MALLOC_STRUCT(nine_shader_variant_so);
225 if (!list->next)
226 return false;
227 list->next->next = NULL;
228 nine_bind(&list->vdecl, vdecl);
229 list->next->so = *so;
230 list->next->cso = cso;
231 return true;
232 }
233
234 static inline void
nine_shader_variants_so_free(struct nine_shader_variant_so * list)235 nine_shader_variants_so_free(struct nine_shader_variant_so *list)
236 {
237 while (list->next) {
238 struct nine_shader_variant_so *ptr = list->next;
239 list->next = ptr->next;
240 nine_bind(&ptr->vdecl, NULL);
241 FREE(ptr);
242 }
243 if (list->vdecl)
244 nine_bind(&list->vdecl, NULL);
245 }
246
247 struct nine_shader_constant_combination
248 {
249 struct nine_shader_constant_combination *next;
250 int const_i[NINE_MAX_CONST_I][4];
251 BOOL const_b[NINE_MAX_CONST_B];
252 };
253
254 #define NINE_MAX_CONSTANT_COMBINATION_VARIANTS 32
255
256 static inline uint8_t
nine_shader_constant_combination_key(struct nine_shader_constant_combination ** list,bool * int_slots_used,bool * bool_slots_used,int * const_i,BOOL * const_b)257 nine_shader_constant_combination_key(struct nine_shader_constant_combination **list,
258 bool *int_slots_used,
259 bool *bool_slots_used,
260 int *const_i,
261 BOOL *const_b)
262 {
263 int i;
264 uint8_t index = 0;
265 bool match;
266 struct nine_shader_constant_combination **next_allocate = list, *current = *list;
267
268 assert(int_slots_used);
269 assert(bool_slots_used);
270 assert(const_i);
271 assert(const_b);
272
273 while (current) {
274 index++; /* start at 1. 0 is for the variant without constant replacement */
275 match = true;
276 for (i = 0; i < NINE_MAX_CONST_I; ++i) {
277 if (int_slots_used[i])
278 match &= !memcmp(const_i + 4*i, current->const_i[i], sizeof(current->const_i[0]));
279 }
280 for (i = 0; i < NINE_MAX_CONST_B; ++i) {
281 if (bool_slots_used[i])
282 match &= const_b[i] == current->const_b[i];
283 }
284 if (match)
285 return index;
286 next_allocate = ¤t->next;
287 current = current->next;
288 }
289
290 if (index < NINE_MAX_CONSTANT_COMBINATION_VARIANTS) {
291 *next_allocate = MALLOC_STRUCT(nine_shader_constant_combination);
292 current = *next_allocate;
293 index++;
294 current->next = NULL;
295 memcpy(current->const_i, const_i, sizeof(current->const_i));
296 memcpy(current->const_b, const_b, sizeof(current->const_b));
297 return index;
298 }
299
300 return 0; /* Too many variants, revert to no replacement */
301 }
302
303 static inline struct nine_shader_constant_combination *
nine_shader_constant_combination_get(struct nine_shader_constant_combination * list,uint8_t index)304 nine_shader_constant_combination_get(struct nine_shader_constant_combination *list, uint8_t index)
305 {
306 if (index == 0)
307 return NULL;
308 while (index) {
309 assert(list != NULL);
310 index--;
311 if (index == 0)
312 return list;
313 list = list->next;
314 }
315 assert(false);
316 return NULL;
317 }
318
319 static inline void
nine_shader_constant_combination_free(struct nine_shader_constant_combination * list)320 nine_shader_constant_combination_free(struct nine_shader_constant_combination *list)
321 {
322 if (!list)
323 return;
324
325 while (list->next) {
326 struct nine_shader_constant_combination *ptr = list->next;
327 list->next = ptr->next;
328 FREE(ptr);
329 }
330
331 FREE(list);
332 }
333
334 /* Returns corresponding opposite test */
335 static inline unsigned
pipe_comp_to_tgsi_opposite(BYTE flags)336 pipe_comp_to_tgsi_opposite(BYTE flags)
337 {
338 switch (flags) {
339 case PIPE_FUNC_GREATER: return TGSI_OPCODE_SLE;
340 case PIPE_FUNC_EQUAL: return TGSI_OPCODE_SNE;
341 case PIPE_FUNC_GEQUAL: return TGSI_OPCODE_SLT;
342 case PIPE_FUNC_LESS: return TGSI_OPCODE_SGE;
343 case PIPE_FUNC_NOTEQUAL: return TGSI_OPCODE_SEQ;
344 case PIPE_FUNC_LEQUAL: return TGSI_OPCODE_SGT;
345 default:
346 assert(!"invalid comparison flags");
347 return TGSI_OPCODE_SGT;
348 }
349 }
350
351 #endif /* _NINE_SHADER_H_ */
352