1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright 2011 Joakim Sindholt <opensource@zhasha.com>
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * on the rights to use, copy, modify, merge, publish, distribute, sub
8bf215546Sopenharmony_ci * license, and/or sell copies of the Software, and to permit persons to whom
9bf215546Sopenharmony_ci * the Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci * Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18bf215546Sopenharmony_ci * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19bf215546Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20bf215546Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21bf215546Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE. */
22bf215546Sopenharmony_ci
23bf215546Sopenharmony_ci#ifndef _NINE_SHADER_H_
24bf215546Sopenharmony_ci#define _NINE_SHADER_H_
25bf215546Sopenharmony_ci
26bf215546Sopenharmony_ci#include "d3d9types.h"
27bf215546Sopenharmony_ci#include "d3d9caps.h"
28bf215546Sopenharmony_ci#include "nine_defines.h"
29bf215546Sopenharmony_ci#include "nine_helpers.h"
30bf215546Sopenharmony_ci#include "nine_state.h"
31bf215546Sopenharmony_ci#include "pipe/p_state.h" /* PIPE_MAX_ATTRIBS */
32bf215546Sopenharmony_ci#include "util/u_memory.h"
33bf215546Sopenharmony_ci
34bf215546Sopenharmony_cistruct NineDevice9;
35bf215546Sopenharmony_cistruct NineVertexDeclaration9;
36bf215546Sopenharmony_cistruct ureg_program;
37bf215546Sopenharmony_ci
38bf215546Sopenharmony_cistruct nine_lconstf /* NOTE: both pointers should be FREE'd by the user */
39bf215546Sopenharmony_ci{
40bf215546Sopenharmony_ci    struct nine_range *ranges; /* single MALLOC, but next-pointers valid */
41bf215546Sopenharmony_ci    float *data;
42bf215546Sopenharmony_ci};
43bf215546Sopenharmony_ci
44bf215546Sopenharmony_cistruct nine_shader_constant_combination;
45bf215546Sopenharmony_ci
46bf215546Sopenharmony_cistruct nine_shader_info
47bf215546Sopenharmony_ci{
48bf215546Sopenharmony_ci    unsigned type; /* in, PIPE_SHADER_x */
49bf215546Sopenharmony_ci
50bf215546Sopenharmony_ci    uint8_t version; /* (major << 4) | minor */
51bf215546Sopenharmony_ci
52bf215546Sopenharmony_ci    const DWORD *byte_code; /* in, pointer to shader tokens */
53bf215546Sopenharmony_ci    DWORD        byte_size; /* out, size of data at byte_code */
54bf215546Sopenharmony_ci
55bf215546Sopenharmony_ci    void *cso; /* out, pipe cso for bind_vs,fs_state */
56bf215546Sopenharmony_ci
57bf215546Sopenharmony_ci    uint16_t input_map[PIPE_MAX_ATTRIBS]; /* VS input -> NINE_DECLUSAGE_x */
58bf215546Sopenharmony_ci    uint8_t num_inputs; /* there may be unused inputs (NINE_DECLUSAGE_NONE) */
59bf215546Sopenharmony_ci
60bf215546Sopenharmony_ci    boolean position_t; /* out, true if VP writes pre-transformed position */
61bf215546Sopenharmony_ci    boolean point_size; /* out, true if VP writes point size */
62bf215546Sopenharmony_ci    float point_size_min;
63bf215546Sopenharmony_ci    float point_size_max;
64bf215546Sopenharmony_ci
65bf215546Sopenharmony_ci    uint32_t sampler_ps1xtypes; /* 2 bits per sampler */
66bf215546Sopenharmony_ci    uint16_t sampler_mask; /* out, which samplers are being used */
67bf215546Sopenharmony_ci    uint16_t sampler_mask_shadow; /* in, which samplers use depth compare */
68bf215546Sopenharmony_ci    uint8_t rt_mask; /* out, which render targets are being written */
69bf215546Sopenharmony_ci
70bf215546Sopenharmony_ci    uint8_t fog_enable;
71bf215546Sopenharmony_ci    uint8_t fog_mode;
72bf215546Sopenharmony_ci    uint8_t force_color_in_centroid;
73bf215546Sopenharmony_ci    uint8_t projected; /* ps 1.1 to 1.3 */
74bf215546Sopenharmony_ci    uint16_t fetch4;
75bf215546Sopenharmony_ci
76bf215546Sopenharmony_ci    unsigned const_i_base; /* in vec4 (16 byte) units */
77bf215546Sopenharmony_ci    unsigned const_b_base; /* in vec4 (16 byte) units */
78bf215546Sopenharmony_ci    unsigned const_used_size;
79bf215546Sopenharmony_ci
80bf215546Sopenharmony_ci    boolean int_slots_used[NINE_MAX_CONST_I];
81bf215546Sopenharmony_ci    boolean bool_slots_used[NINE_MAX_CONST_B];
82bf215546Sopenharmony_ci
83bf215546Sopenharmony_ci    unsigned const_float_slots;
84bf215546Sopenharmony_ci    unsigned const_int_slots;
85bf215546Sopenharmony_ci    unsigned const_bool_slots;
86bf215546Sopenharmony_ci
87bf215546Sopenharmony_ci    unsigned *const_ranges;
88bf215546Sopenharmony_ci
89bf215546Sopenharmony_ci    struct nine_lconstf lconstf; /* out, NOTE: members to be free'd by user */
90bf215546Sopenharmony_ci    uint8_t bumpenvmat_needed;
91bf215546Sopenharmony_ci
92bf215546Sopenharmony_ci    struct {
93bf215546Sopenharmony_ci        struct nine_shader_constant_combination* c_combination;
94bf215546Sopenharmony_ci        boolean (*int_const_added)[NINE_MAX_CONST_I];
95bf215546Sopenharmony_ci        boolean (*bool_const_added)[NINE_MAX_CONST_B];
96bf215546Sopenharmony_ci    } add_constants_defs;
97bf215546Sopenharmony_ci
98bf215546Sopenharmony_ci    boolean swvp_on;
99bf215546Sopenharmony_ci
100bf215546Sopenharmony_ci    boolean process_vertices;
101bf215546Sopenharmony_ci    struct NineVertexDeclaration9 *vdecl_out;
102bf215546Sopenharmony_ci    struct pipe_stream_output_info so;
103bf215546Sopenharmony_ci};
104bf215546Sopenharmony_ci
105bf215546Sopenharmony_cistruct nine_vs_output_info
106bf215546Sopenharmony_ci{
107bf215546Sopenharmony_ci    BYTE output_semantic;
108bf215546Sopenharmony_ci    int output_semantic_index;
109bf215546Sopenharmony_ci    int mask;
110bf215546Sopenharmony_ci    int output_index;
111bf215546Sopenharmony_ci};
112bf215546Sopenharmony_ci
113bf215546Sopenharmony_civoid *
114bf215546Sopenharmony_cinine_create_shader_with_so_and_destroy(struct ureg_program *p,
115bf215546Sopenharmony_ci                                       struct pipe_context *pipe,
116bf215546Sopenharmony_ci                                       const struct pipe_stream_output_info *so);
117bf215546Sopenharmony_ci
118bf215546Sopenharmony_ciHRESULT
119bf215546Sopenharmony_cinine_translate_shader(struct NineDevice9 *device,
120bf215546Sopenharmony_ci                      struct nine_shader_info *,
121bf215546Sopenharmony_ci                      struct pipe_context *);
122bf215546Sopenharmony_ci
123bf215546Sopenharmony_ci
124bf215546Sopenharmony_cistruct nine_shader_variant
125bf215546Sopenharmony_ci{
126bf215546Sopenharmony_ci    struct nine_shader_variant *next;
127bf215546Sopenharmony_ci    void *cso;
128bf215546Sopenharmony_ci    unsigned *const_ranges;
129bf215546Sopenharmony_ci    unsigned const_used_size;
130bf215546Sopenharmony_ci    uint64_t key;
131bf215546Sopenharmony_ci};
132bf215546Sopenharmony_ci
133bf215546Sopenharmony_cistatic inline void *
134bf215546Sopenharmony_cinine_shader_variant_get(struct nine_shader_variant *list,
135bf215546Sopenharmony_ci                        unsigned **const_ranges,
136bf215546Sopenharmony_ci                        unsigned *const_used_size,
137bf215546Sopenharmony_ci                        uint64_t key)
138bf215546Sopenharmony_ci{
139bf215546Sopenharmony_ci    while (list->key != key && list->next)
140bf215546Sopenharmony_ci        list = list->next;
141bf215546Sopenharmony_ci    if (list->key == key) {
142bf215546Sopenharmony_ci        *const_ranges = list->const_ranges;
143bf215546Sopenharmony_ci        *const_used_size = list->const_used_size;
144bf215546Sopenharmony_ci        return list->cso;
145bf215546Sopenharmony_ci    }
146bf215546Sopenharmony_ci    return NULL;
147bf215546Sopenharmony_ci}
148bf215546Sopenharmony_ci
149bf215546Sopenharmony_cistatic inline boolean
150bf215546Sopenharmony_cinine_shader_variant_add(struct nine_shader_variant *list,
151bf215546Sopenharmony_ci                        uint64_t key, void *cso,
152bf215546Sopenharmony_ci                        unsigned *const_ranges,
153bf215546Sopenharmony_ci                        unsigned const_used_size)
154bf215546Sopenharmony_ci{
155bf215546Sopenharmony_ci    while (list->next) {
156bf215546Sopenharmony_ci        assert(list->key != key);
157bf215546Sopenharmony_ci        list = list->next;
158bf215546Sopenharmony_ci    }
159bf215546Sopenharmony_ci    list->next = MALLOC_STRUCT(nine_shader_variant);
160bf215546Sopenharmony_ci    if (!list->next)
161bf215546Sopenharmony_ci        return FALSE;
162bf215546Sopenharmony_ci    list->next->next = NULL;
163bf215546Sopenharmony_ci    list->next->key = key;
164bf215546Sopenharmony_ci    list->next->cso = cso;
165bf215546Sopenharmony_ci    list->next->const_ranges = const_ranges;
166bf215546Sopenharmony_ci    list->next->const_used_size = const_used_size;
167bf215546Sopenharmony_ci    return TRUE;
168bf215546Sopenharmony_ci}
169bf215546Sopenharmony_ci
170bf215546Sopenharmony_cistatic inline void
171bf215546Sopenharmony_cinine_shader_variants_free(struct nine_shader_variant *list)
172bf215546Sopenharmony_ci{
173bf215546Sopenharmony_ci    while (list->next) {
174bf215546Sopenharmony_ci        struct nine_shader_variant *ptr = list->next;
175bf215546Sopenharmony_ci        list->next = ptr->next;
176bf215546Sopenharmony_ci        FREE(ptr);
177bf215546Sopenharmony_ci    }
178bf215546Sopenharmony_ci}
179bf215546Sopenharmony_ci
180bf215546Sopenharmony_cistruct nine_shader_variant_so
181bf215546Sopenharmony_ci{
182bf215546Sopenharmony_ci    struct nine_shader_variant_so *next;
183bf215546Sopenharmony_ci    struct NineVertexDeclaration9 *vdecl;
184bf215546Sopenharmony_ci    struct pipe_stream_output_info so;
185bf215546Sopenharmony_ci    void *cso;
186bf215546Sopenharmony_ci};
187bf215546Sopenharmony_ci
188bf215546Sopenharmony_cistatic inline void *
189bf215546Sopenharmony_cinine_shader_variant_so_get(struct nine_shader_variant_so *list,
190bf215546Sopenharmony_ci                           struct NineVertexDeclaration9 *vdecl,
191bf215546Sopenharmony_ci                           struct pipe_stream_output_info *so)
192bf215546Sopenharmony_ci{
193bf215546Sopenharmony_ci    while (list->vdecl != vdecl && list->next)
194bf215546Sopenharmony_ci        list = list->next;
195bf215546Sopenharmony_ci    if (list->vdecl == vdecl) {
196bf215546Sopenharmony_ci        *so = list->so;
197bf215546Sopenharmony_ci        return list->cso;
198bf215546Sopenharmony_ci    }
199bf215546Sopenharmony_ci    return NULL;
200bf215546Sopenharmony_ci}
201bf215546Sopenharmony_ci
202bf215546Sopenharmony_cistatic inline boolean
203bf215546Sopenharmony_cinine_shader_variant_so_add(struct nine_shader_variant_so *list,
204bf215546Sopenharmony_ci                           struct NineVertexDeclaration9 *vdecl,
205bf215546Sopenharmony_ci                           struct pipe_stream_output_info *so, void *cso)
206bf215546Sopenharmony_ci{
207bf215546Sopenharmony_ci    if (list->vdecl == NULL) { /* first shader */
208bf215546Sopenharmony_ci        list->next = NULL;
209bf215546Sopenharmony_ci        nine_bind(&list->vdecl, vdecl);
210bf215546Sopenharmony_ci        list->so = *so;
211bf215546Sopenharmony_ci        list->cso = cso;
212bf215546Sopenharmony_ci        return TRUE;
213bf215546Sopenharmony_ci    }
214bf215546Sopenharmony_ci    while (list->next) {
215bf215546Sopenharmony_ci        assert(list->vdecl != vdecl);
216bf215546Sopenharmony_ci        list = list->next;
217bf215546Sopenharmony_ci    }
218bf215546Sopenharmony_ci    list->next = MALLOC_STRUCT(nine_shader_variant_so);
219bf215546Sopenharmony_ci    if (!list->next)
220bf215546Sopenharmony_ci        return FALSE;
221bf215546Sopenharmony_ci    list->next->next = NULL;
222bf215546Sopenharmony_ci    nine_bind(&list->vdecl, vdecl);
223bf215546Sopenharmony_ci    list->next->so = *so;
224bf215546Sopenharmony_ci    list->next->cso = cso;
225bf215546Sopenharmony_ci    return TRUE;
226bf215546Sopenharmony_ci}
227bf215546Sopenharmony_ci
228bf215546Sopenharmony_cistatic inline void
229bf215546Sopenharmony_cinine_shader_variants_so_free(struct nine_shader_variant_so *list)
230bf215546Sopenharmony_ci{
231bf215546Sopenharmony_ci    while (list->next) {
232bf215546Sopenharmony_ci        struct nine_shader_variant_so *ptr = list->next;
233bf215546Sopenharmony_ci        list->next = ptr->next;
234bf215546Sopenharmony_ci        nine_bind(&ptr->vdecl, NULL);
235bf215546Sopenharmony_ci        FREE(ptr);
236bf215546Sopenharmony_ci    }
237bf215546Sopenharmony_ci    if (list->vdecl)
238bf215546Sopenharmony_ci        nine_bind(&list->vdecl, NULL);
239bf215546Sopenharmony_ci}
240bf215546Sopenharmony_ci
241bf215546Sopenharmony_cistruct nine_shader_constant_combination
242bf215546Sopenharmony_ci{
243bf215546Sopenharmony_ci    struct nine_shader_constant_combination *next;
244bf215546Sopenharmony_ci    int const_i[NINE_MAX_CONST_I][4];
245bf215546Sopenharmony_ci    BOOL const_b[NINE_MAX_CONST_B];
246bf215546Sopenharmony_ci};
247bf215546Sopenharmony_ci
248bf215546Sopenharmony_ci#define NINE_MAX_CONSTANT_COMBINATION_VARIANTS 32
249bf215546Sopenharmony_ci
250bf215546Sopenharmony_cistatic inline uint8_t
251bf215546Sopenharmony_cinine_shader_constant_combination_key(struct nine_shader_constant_combination **list,
252bf215546Sopenharmony_ci                                     boolean *int_slots_used,
253bf215546Sopenharmony_ci                                     boolean *bool_slots_used,
254bf215546Sopenharmony_ci                                     int *const_i,
255bf215546Sopenharmony_ci                                     BOOL *const_b)
256bf215546Sopenharmony_ci{
257bf215546Sopenharmony_ci    int i;
258bf215546Sopenharmony_ci    uint8_t index = 0;
259bf215546Sopenharmony_ci    boolean match;
260bf215546Sopenharmony_ci    struct nine_shader_constant_combination **next_allocate = list, *current = *list;
261bf215546Sopenharmony_ci
262bf215546Sopenharmony_ci    assert(int_slots_used);
263bf215546Sopenharmony_ci    assert(bool_slots_used);
264bf215546Sopenharmony_ci    assert(const_i);
265bf215546Sopenharmony_ci    assert(const_b);
266bf215546Sopenharmony_ci
267bf215546Sopenharmony_ci    while (current) {
268bf215546Sopenharmony_ci        index++; /* start at 1. 0 is for the variant without constant replacement */
269bf215546Sopenharmony_ci        match = TRUE;
270bf215546Sopenharmony_ci        for (i = 0; i < NINE_MAX_CONST_I; ++i) {
271bf215546Sopenharmony_ci            if (int_slots_used[i])
272bf215546Sopenharmony_ci                match &= !memcmp(const_i + 4*i, current->const_i[i], sizeof(current->const_i[0]));
273bf215546Sopenharmony_ci        }
274bf215546Sopenharmony_ci        for (i = 0; i < NINE_MAX_CONST_B; ++i) {
275bf215546Sopenharmony_ci            if (bool_slots_used[i])
276bf215546Sopenharmony_ci                match &= const_b[i] == current->const_b[i];
277bf215546Sopenharmony_ci        }
278bf215546Sopenharmony_ci        if (match)
279bf215546Sopenharmony_ci            return index;
280bf215546Sopenharmony_ci        next_allocate = &current->next;
281bf215546Sopenharmony_ci        current = current->next;
282bf215546Sopenharmony_ci    }
283bf215546Sopenharmony_ci
284bf215546Sopenharmony_ci    if (index < NINE_MAX_CONSTANT_COMBINATION_VARIANTS) {
285bf215546Sopenharmony_ci        *next_allocate = MALLOC_STRUCT(nine_shader_constant_combination);
286bf215546Sopenharmony_ci        current = *next_allocate;
287bf215546Sopenharmony_ci        index++;
288bf215546Sopenharmony_ci        current->next = NULL;
289bf215546Sopenharmony_ci        memcpy(current->const_i, const_i, sizeof(current->const_i));
290bf215546Sopenharmony_ci        memcpy(current->const_b, const_b, sizeof(current->const_b));
291bf215546Sopenharmony_ci        return index;
292bf215546Sopenharmony_ci    }
293bf215546Sopenharmony_ci
294bf215546Sopenharmony_ci    return 0; /* Too many variants, revert to no replacement */
295bf215546Sopenharmony_ci}
296bf215546Sopenharmony_ci
297bf215546Sopenharmony_cistatic inline struct nine_shader_constant_combination *
298bf215546Sopenharmony_cinine_shader_constant_combination_get(struct nine_shader_constant_combination *list, uint8_t index)
299bf215546Sopenharmony_ci{
300bf215546Sopenharmony_ci    if (index == 0)
301bf215546Sopenharmony_ci        return NULL;
302bf215546Sopenharmony_ci    while (index) {
303bf215546Sopenharmony_ci        assert(list != NULL);
304bf215546Sopenharmony_ci        index--;
305bf215546Sopenharmony_ci        if (index == 0)
306bf215546Sopenharmony_ci            return list;
307bf215546Sopenharmony_ci        list = list->next;
308bf215546Sopenharmony_ci    }
309bf215546Sopenharmony_ci    assert(FALSE);
310bf215546Sopenharmony_ci    return NULL;
311bf215546Sopenharmony_ci}
312bf215546Sopenharmony_ci
313bf215546Sopenharmony_cistatic inline void
314bf215546Sopenharmony_cinine_shader_constant_combination_free(struct nine_shader_constant_combination *list)
315bf215546Sopenharmony_ci{
316bf215546Sopenharmony_ci    if (!list)
317bf215546Sopenharmony_ci        return;
318bf215546Sopenharmony_ci
319bf215546Sopenharmony_ci    while (list->next) {
320bf215546Sopenharmony_ci        struct nine_shader_constant_combination *ptr = list->next;
321bf215546Sopenharmony_ci        list->next = ptr->next;
322bf215546Sopenharmony_ci        FREE(ptr);
323bf215546Sopenharmony_ci    }
324bf215546Sopenharmony_ci
325bf215546Sopenharmony_ci    FREE(list);
326bf215546Sopenharmony_ci}
327bf215546Sopenharmony_ci
328bf215546Sopenharmony_ci#endif /* _NINE_SHADER_H_ */
329