• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 = &current->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