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