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
34 struct NineDevice9;
35 struct NineVertexDeclaration9;
36 struct ureg_program;
37
38 struct nine_lconstf /* NOTE: both pointers should be FREE'd by the user */
39 {
40 struct nine_range *ranges; /* single MALLOC, but next-pointers valid */
41 float *data;
42 };
43
44 struct nine_shader_constant_combination;
45
46 struct nine_shader_info
47 {
48 unsigned type; /* in, PIPE_SHADER_x */
49
50 uint8_t version; /* (major << 4) | minor */
51
52 const DWORD *byte_code; /* in, pointer to shader tokens */
53 DWORD byte_size; /* out, size of data at byte_code */
54
55 void *cso; /* out, pipe cso for bind_vs,fs_state */
56
57 uint16_t input_map[PIPE_MAX_ATTRIBS]; /* VS input -> NINE_DECLUSAGE_x */
58 uint8_t num_inputs; /* there may be unused inputs (NINE_DECLUSAGE_NONE) */
59
60 boolean position_t; /* out, true if VP writes pre-transformed position */
61 boolean point_size; /* out, true if VP writes point size */
62 float point_size_min;
63 float point_size_max;
64
65 uint32_t sampler_ps1xtypes; /* 2 bits per sampler */
66 uint16_t sampler_mask; /* out, which samplers are being used */
67 uint16_t sampler_mask_shadow; /* in, which samplers use depth compare */
68 uint8_t rt_mask; /* out, which render targets are being written */
69
70 uint8_t fog_enable;
71 uint8_t fog_mode;
72 uint8_t force_color_in_centroid;
73 uint8_t projected; /* ps 1.1 to 1.3 */
74
75 unsigned const_i_base; /* in vec4 (16 byte) units */
76 unsigned const_b_base; /* in vec4 (16 byte) units */
77 unsigned const_used_size;
78
79 boolean int_slots_used[NINE_MAX_CONST_I];
80 boolean bool_slots_used[NINE_MAX_CONST_B];
81
82 unsigned const_float_slots;
83 unsigned const_int_slots;
84 unsigned const_bool_slots;
85
86 unsigned *const_ranges;
87
88 struct nine_lconstf lconstf; /* out, NOTE: members to be free'd by user */
89 uint8_t bumpenvmat_needed;
90
91 struct {
92 struct nine_shader_constant_combination* c_combination;
93 boolean (*int_const_added)[NINE_MAX_CONST_I];
94 boolean (*bool_const_added)[NINE_MAX_CONST_B];
95 } add_constants_defs;
96
97 boolean swvp_on;
98
99 boolean process_vertices;
100 struct NineVertexDeclaration9 *vdecl_out;
101 struct pipe_stream_output_info so;
102 };
103
104 struct nine_vs_output_info
105 {
106 BYTE output_semantic;
107 int output_semantic_index;
108 int mask;
109 int output_index;
110 };
111
112 void *
113 nine_create_shader_with_so_and_destroy(struct ureg_program *p,
114 struct pipe_context *pipe,
115 const struct pipe_stream_output_info *so);
116
117 HRESULT
118 nine_translate_shader(struct NineDevice9 *device,
119 struct nine_shader_info *,
120 struct pipe_context *);
121
122
123 struct nine_shader_variant
124 {
125 struct nine_shader_variant *next;
126 void *cso;
127 unsigned *const_ranges;
128 unsigned const_used_size;
129 uint64_t key;
130 };
131
132 static inline void *
nine_shader_variant_get(struct nine_shader_variant * list,unsigned ** const_ranges,unsigned * const_used_size,uint64_t key)133 nine_shader_variant_get(struct nine_shader_variant *list,
134 unsigned **const_ranges,
135 unsigned *const_used_size,
136 uint64_t key)
137 {
138 while (list->key != key && list->next)
139 list = list->next;
140 if (list->key == key) {
141 *const_ranges = list->const_ranges;
142 *const_used_size = list->const_used_size;
143 return list->cso;
144 }
145 return NULL;
146 }
147
148 static inline boolean
nine_shader_variant_add(struct nine_shader_variant * list,uint64_t key,void * cso,unsigned * const_ranges,unsigned const_used_size)149 nine_shader_variant_add(struct nine_shader_variant *list,
150 uint64_t key, void *cso,
151 unsigned *const_ranges,
152 unsigned const_used_size)
153 {
154 while (list->next) {
155 assert(list->key != key);
156 list = list->next;
157 }
158 list->next = MALLOC_STRUCT(nine_shader_variant);
159 if (!list->next)
160 return FALSE;
161 list->next->next = NULL;
162 list->next->key = key;
163 list->next->cso = cso;
164 list->next->const_ranges = const_ranges;
165 list->next->const_used_size = const_used_size;
166 return TRUE;
167 }
168
169 static inline void
nine_shader_variants_free(struct nine_shader_variant * list)170 nine_shader_variants_free(struct nine_shader_variant *list)
171 {
172 while (list->next) {
173 struct nine_shader_variant *ptr = list->next;
174 list->next = ptr->next;
175 FREE(ptr);
176 }
177 }
178
179 struct nine_shader_variant_so
180 {
181 struct nine_shader_variant_so *next;
182 struct NineVertexDeclaration9 *vdecl;
183 struct pipe_stream_output_info so;
184 void *cso;
185 };
186
187 static inline void *
nine_shader_variant_so_get(struct nine_shader_variant_so * list,struct NineVertexDeclaration9 * vdecl,struct pipe_stream_output_info * so)188 nine_shader_variant_so_get(struct nine_shader_variant_so *list,
189 struct NineVertexDeclaration9 *vdecl,
190 struct pipe_stream_output_info *so)
191 {
192 while (list->vdecl != vdecl && list->next)
193 list = list->next;
194 if (list->vdecl == vdecl) {
195 *so = list->so;
196 return list->cso;
197 }
198 return NULL;
199 }
200
201 static inline boolean
nine_shader_variant_so_add(struct nine_shader_variant_so * list,struct NineVertexDeclaration9 * vdecl,struct pipe_stream_output_info * so,void * cso)202 nine_shader_variant_so_add(struct nine_shader_variant_so *list,
203 struct NineVertexDeclaration9 *vdecl,
204 struct pipe_stream_output_info *so, void *cso)
205 {
206 if (list->vdecl == NULL) { /* first shader */
207 list->next = NULL;
208 nine_bind(&list->vdecl, vdecl);
209 list->so = *so;
210 list->cso = cso;
211 return TRUE;
212 }
213 while (list->next) {
214 assert(list->vdecl != vdecl);
215 list = list->next;
216 }
217 list->next = MALLOC_STRUCT(nine_shader_variant_so);
218 if (!list->next)
219 return FALSE;
220 list->next->next = NULL;
221 nine_bind(&list->vdecl, vdecl);
222 list->next->so = *so;
223 list->next->cso = cso;
224 return TRUE;
225 }
226
227 static inline void
nine_shader_variants_so_free(struct nine_shader_variant_so * list)228 nine_shader_variants_so_free(struct nine_shader_variant_so *list)
229 {
230 while (list->next) {
231 struct nine_shader_variant_so *ptr = list->next;
232 list->next = ptr->next;
233 nine_bind(&ptr->vdecl, NULL);
234 FREE(ptr);
235 }
236 if (list->vdecl)
237 nine_bind(&list->vdecl, NULL);
238 }
239
240 struct nine_shader_constant_combination
241 {
242 struct nine_shader_constant_combination *next;
243 int const_i[NINE_MAX_CONST_I][4];
244 BOOL const_b[NINE_MAX_CONST_B];
245 };
246
247 #define NINE_MAX_CONSTANT_COMBINATION_VARIANTS 32
248
249 static inline uint8_t
nine_shader_constant_combination_key(struct nine_shader_constant_combination ** list,boolean * int_slots_used,boolean * bool_slots_used,int * const_i,BOOL * const_b)250 nine_shader_constant_combination_key(struct nine_shader_constant_combination **list,
251 boolean *int_slots_used,
252 boolean *bool_slots_used,
253 int *const_i,
254 BOOL *const_b)
255 {
256 int i;
257 uint8_t index = 0;
258 boolean match;
259 struct nine_shader_constant_combination **next_allocate = list, *current = *list;
260
261 assert(int_slots_used);
262 assert(bool_slots_used);
263 assert(const_i);
264 assert(const_b);
265
266 while (current) {
267 index++; /* start at 1. 0 is for the variant without constant replacement */
268 match = TRUE;
269 for (i = 0; i < NINE_MAX_CONST_I; ++i) {
270 if (int_slots_used[i])
271 match &= !memcmp(const_i + 4*i, current->const_i[i], sizeof(current->const_i[0]));
272 }
273 for (i = 0; i < NINE_MAX_CONST_B; ++i) {
274 if (bool_slots_used[i])
275 match &= const_b[i] == current->const_b[i];
276 }
277 if (match)
278 return index;
279 next_allocate = ¤t->next;
280 current = current->next;
281 }
282
283 if (index < NINE_MAX_CONSTANT_COMBINATION_VARIANTS) {
284 *next_allocate = MALLOC_STRUCT(nine_shader_constant_combination);
285 current = *next_allocate;
286 index++;
287 current->next = NULL;
288 memcpy(current->const_i, const_i, sizeof(current->const_i));
289 memcpy(current->const_b, const_b, sizeof(current->const_b));
290 return index;
291 }
292
293 return 0; /* Too many variants, revert to no replacement */
294 }
295
296 static inline struct nine_shader_constant_combination *
nine_shader_constant_combination_get(struct nine_shader_constant_combination * list,uint8_t index)297 nine_shader_constant_combination_get(struct nine_shader_constant_combination *list, uint8_t index)
298 {
299 if (index == 0)
300 return NULL;
301 while (index) {
302 assert(list != NULL);
303 index--;
304 if (index == 0)
305 return list;
306 list = list->next;
307 }
308 assert(FALSE);
309 return NULL;
310 }
311
312 static inline void
nine_shader_constant_combination_free(struct nine_shader_constant_combination * list)313 nine_shader_constant_combination_free(struct nine_shader_constant_combination *list)
314 {
315 if (!list)
316 return;
317
318 while (list->next) {
319 struct nine_shader_constant_combination *ptr = list->next;
320 list->next = ptr->next;
321 FREE(ptr);
322 }
323
324 FREE(list);
325 }
326
327 #endif /* _NINE_SHADER_H_ */
328