17ec681f3Smrg/*
27ec681f3Smrg * Copyright 2011 Joakim Sindholt <opensource@zhasha.com>
37ec681f3Smrg *
47ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a
57ec681f3Smrg * copy of this software and associated documentation files (the "Software"),
67ec681f3Smrg * to deal in the Software without restriction, including without limitation
77ec681f3Smrg * on the rights to use, copy, modify, merge, publish, distribute, sub
87ec681f3Smrg * license, and/or sell copies of the Software, and to permit persons to whom
97ec681f3Smrg * the Software is furnished to do so, subject to the following conditions:
107ec681f3Smrg *
117ec681f3Smrg * The above copyright notice and this permission notice (including the next
127ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the
137ec681f3Smrg * Software.
147ec681f3Smrg *
157ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
167ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
177ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
187ec681f3Smrg * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
197ec681f3Smrg * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
207ec681f3Smrg * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
217ec681f3Smrg * USE OR OTHER DEALINGS IN THE SOFTWARE. */
227ec681f3Smrg
237ec681f3Smrg#ifndef _NINE_SHADER_H_
247ec681f3Smrg#define _NINE_SHADER_H_
257ec681f3Smrg
267ec681f3Smrg#include "d3d9types.h"
277ec681f3Smrg#include "d3d9caps.h"
287ec681f3Smrg#include "nine_defines.h"
297ec681f3Smrg#include "nine_helpers.h"
307ec681f3Smrg#include "nine_state.h"
317ec681f3Smrg#include "pipe/p_state.h" /* PIPE_MAX_ATTRIBS */
327ec681f3Smrg#include "util/u_memory.h"
337ec681f3Smrg
347ec681f3Smrgstruct NineDevice9;
357ec681f3Smrgstruct NineVertexDeclaration9;
367ec681f3Smrgstruct ureg_program;
377ec681f3Smrg
387ec681f3Smrgstruct nine_lconstf /* NOTE: both pointers should be FREE'd by the user */
397ec681f3Smrg{
407ec681f3Smrg    struct nine_range *ranges; /* single MALLOC, but next-pointers valid */
417ec681f3Smrg    float *data;
427ec681f3Smrg};
437ec681f3Smrg
447ec681f3Smrgstruct nine_shader_constant_combination;
457ec681f3Smrg
467ec681f3Smrgstruct nine_shader_info
477ec681f3Smrg{
487ec681f3Smrg    unsigned type; /* in, PIPE_SHADER_x */
497ec681f3Smrg
507ec681f3Smrg    uint8_t version; /* (major << 4) | minor */
517ec681f3Smrg
527ec681f3Smrg    const DWORD *byte_code; /* in, pointer to shader tokens */
537ec681f3Smrg    DWORD        byte_size; /* out, size of data at byte_code */
547ec681f3Smrg
557ec681f3Smrg    void *cso; /* out, pipe cso for bind_vs,fs_state */
567ec681f3Smrg
577ec681f3Smrg    uint16_t input_map[PIPE_MAX_ATTRIBS]; /* VS input -> NINE_DECLUSAGE_x */
587ec681f3Smrg    uint8_t num_inputs; /* there may be unused inputs (NINE_DECLUSAGE_NONE) */
597ec681f3Smrg
607ec681f3Smrg    boolean position_t; /* out, true if VP writes pre-transformed position */
617ec681f3Smrg    boolean point_size; /* out, true if VP writes point size */
627ec681f3Smrg    float point_size_min;
637ec681f3Smrg    float point_size_max;
647ec681f3Smrg
657ec681f3Smrg    uint32_t sampler_ps1xtypes; /* 2 bits per sampler */
667ec681f3Smrg    uint16_t sampler_mask; /* out, which samplers are being used */
677ec681f3Smrg    uint16_t sampler_mask_shadow; /* in, which samplers use depth compare */
687ec681f3Smrg    uint8_t rt_mask; /* out, which render targets are being written */
697ec681f3Smrg
707ec681f3Smrg    uint8_t fog_enable;
717ec681f3Smrg    uint8_t fog_mode;
727ec681f3Smrg    uint8_t force_color_in_centroid;
737ec681f3Smrg    uint8_t projected; /* ps 1.1 to 1.3 */
747ec681f3Smrg    uint16_t fetch4;
757ec681f3Smrg
767ec681f3Smrg    unsigned const_i_base; /* in vec4 (16 byte) units */
777ec681f3Smrg    unsigned const_b_base; /* in vec4 (16 byte) units */
787ec681f3Smrg    unsigned const_used_size;
797ec681f3Smrg
807ec681f3Smrg    boolean int_slots_used[NINE_MAX_CONST_I];
817ec681f3Smrg    boolean bool_slots_used[NINE_MAX_CONST_B];
827ec681f3Smrg
837ec681f3Smrg    unsigned const_float_slots;
847ec681f3Smrg    unsigned const_int_slots;
857ec681f3Smrg    unsigned const_bool_slots;
867ec681f3Smrg
877ec681f3Smrg    unsigned *const_ranges;
887ec681f3Smrg
897ec681f3Smrg    struct nine_lconstf lconstf; /* out, NOTE: members to be free'd by user */
907ec681f3Smrg    uint8_t bumpenvmat_needed;
917ec681f3Smrg
927ec681f3Smrg    struct {
937ec681f3Smrg        struct nine_shader_constant_combination* c_combination;
947ec681f3Smrg        boolean (*int_const_added)[NINE_MAX_CONST_I];
957ec681f3Smrg        boolean (*bool_const_added)[NINE_MAX_CONST_B];
967ec681f3Smrg    } add_constants_defs;
977ec681f3Smrg
987ec681f3Smrg    boolean swvp_on;
997ec681f3Smrg
1007ec681f3Smrg    boolean process_vertices;
1017ec681f3Smrg    struct NineVertexDeclaration9 *vdecl_out;
1027ec681f3Smrg    struct pipe_stream_output_info so;
1037ec681f3Smrg};
1047ec681f3Smrg
1057ec681f3Smrgstruct nine_vs_output_info
1067ec681f3Smrg{
1077ec681f3Smrg    BYTE output_semantic;
1087ec681f3Smrg    int output_semantic_index;
1097ec681f3Smrg    int mask;
1107ec681f3Smrg    int output_index;
1117ec681f3Smrg};
1127ec681f3Smrg
1137ec681f3Smrgvoid *
1147ec681f3Smrgnine_create_shader_with_so_and_destroy(struct ureg_program *p,
1157ec681f3Smrg                                       struct pipe_context *pipe,
1167ec681f3Smrg                                       const struct pipe_stream_output_info *so);
1177ec681f3Smrg
1187ec681f3SmrgHRESULT
1197ec681f3Smrgnine_translate_shader(struct NineDevice9 *device,
1207ec681f3Smrg                      struct nine_shader_info *,
1217ec681f3Smrg                      struct pipe_context *);
1227ec681f3Smrg
1237ec681f3Smrg
1247ec681f3Smrgstruct nine_shader_variant
1257ec681f3Smrg{
1267ec681f3Smrg    struct nine_shader_variant *next;
1277ec681f3Smrg    void *cso;
1287ec681f3Smrg    unsigned *const_ranges;
1297ec681f3Smrg    unsigned const_used_size;
1307ec681f3Smrg    uint64_t key;
1317ec681f3Smrg};
1327ec681f3Smrg
1337ec681f3Smrgstatic inline void *
1347ec681f3Smrgnine_shader_variant_get(struct nine_shader_variant *list,
1357ec681f3Smrg                        unsigned **const_ranges,
1367ec681f3Smrg                        unsigned *const_used_size,
1377ec681f3Smrg                        uint64_t key)
1387ec681f3Smrg{
1397ec681f3Smrg    while (list->key != key && list->next)
1407ec681f3Smrg        list = list->next;
1417ec681f3Smrg    if (list->key == key) {
1427ec681f3Smrg        *const_ranges = list->const_ranges;
1437ec681f3Smrg        *const_used_size = list->const_used_size;
1447ec681f3Smrg        return list->cso;
1457ec681f3Smrg    }
1467ec681f3Smrg    return NULL;
1477ec681f3Smrg}
1487ec681f3Smrg
1497ec681f3Smrgstatic inline boolean
1507ec681f3Smrgnine_shader_variant_add(struct nine_shader_variant *list,
1517ec681f3Smrg                        uint64_t key, void *cso,
1527ec681f3Smrg                        unsigned *const_ranges,
1537ec681f3Smrg                        unsigned const_used_size)
1547ec681f3Smrg{
1557ec681f3Smrg    while (list->next) {
1567ec681f3Smrg        assert(list->key != key);
1577ec681f3Smrg        list = list->next;
1587ec681f3Smrg    }
1597ec681f3Smrg    list->next = MALLOC_STRUCT(nine_shader_variant);
1607ec681f3Smrg    if (!list->next)
1617ec681f3Smrg        return FALSE;
1627ec681f3Smrg    list->next->next = NULL;
1637ec681f3Smrg    list->next->key = key;
1647ec681f3Smrg    list->next->cso = cso;
1657ec681f3Smrg    list->next->const_ranges = const_ranges;
1667ec681f3Smrg    list->next->const_used_size = const_used_size;
1677ec681f3Smrg    return TRUE;
1687ec681f3Smrg}
1697ec681f3Smrg
1707ec681f3Smrgstatic inline void
1717ec681f3Smrgnine_shader_variants_free(struct nine_shader_variant *list)
1727ec681f3Smrg{
1737ec681f3Smrg    while (list->next) {
1747ec681f3Smrg        struct nine_shader_variant *ptr = list->next;
1757ec681f3Smrg        list->next = ptr->next;
1767ec681f3Smrg        FREE(ptr);
1777ec681f3Smrg    }
1787ec681f3Smrg}
1797ec681f3Smrg
1807ec681f3Smrgstruct nine_shader_variant_so
1817ec681f3Smrg{
1827ec681f3Smrg    struct nine_shader_variant_so *next;
1837ec681f3Smrg    struct NineVertexDeclaration9 *vdecl;
1847ec681f3Smrg    struct pipe_stream_output_info so;
1857ec681f3Smrg    void *cso;
1867ec681f3Smrg};
1877ec681f3Smrg
1887ec681f3Smrgstatic inline void *
1897ec681f3Smrgnine_shader_variant_so_get(struct nine_shader_variant_so *list,
1907ec681f3Smrg                           struct NineVertexDeclaration9 *vdecl,
1917ec681f3Smrg                           struct pipe_stream_output_info *so)
1927ec681f3Smrg{
1937ec681f3Smrg    while (list->vdecl != vdecl && list->next)
1947ec681f3Smrg        list = list->next;
1957ec681f3Smrg    if (list->vdecl == vdecl) {
1967ec681f3Smrg        *so = list->so;
1977ec681f3Smrg        return list->cso;
1987ec681f3Smrg    }
1997ec681f3Smrg    return NULL;
2007ec681f3Smrg}
2017ec681f3Smrg
2027ec681f3Smrgstatic inline boolean
2037ec681f3Smrgnine_shader_variant_so_add(struct nine_shader_variant_so *list,
2047ec681f3Smrg                           struct NineVertexDeclaration9 *vdecl,
2057ec681f3Smrg                           struct pipe_stream_output_info *so, void *cso)
2067ec681f3Smrg{
2077ec681f3Smrg    if (list->vdecl == NULL) { /* first shader */
2087ec681f3Smrg        list->next = NULL;
2097ec681f3Smrg        nine_bind(&list->vdecl, vdecl);
2107ec681f3Smrg        list->so = *so;
2117ec681f3Smrg        list->cso = cso;
2127ec681f3Smrg        return TRUE;
2137ec681f3Smrg    }
2147ec681f3Smrg    while (list->next) {
2157ec681f3Smrg        assert(list->vdecl != vdecl);
2167ec681f3Smrg        list = list->next;
2177ec681f3Smrg    }
2187ec681f3Smrg    list->next = MALLOC_STRUCT(nine_shader_variant_so);
2197ec681f3Smrg    if (!list->next)
2207ec681f3Smrg        return FALSE;
2217ec681f3Smrg    list->next->next = NULL;
2227ec681f3Smrg    nine_bind(&list->vdecl, vdecl);
2237ec681f3Smrg    list->next->so = *so;
2247ec681f3Smrg    list->next->cso = cso;
2257ec681f3Smrg    return TRUE;
2267ec681f3Smrg}
2277ec681f3Smrg
2287ec681f3Smrgstatic inline void
2297ec681f3Smrgnine_shader_variants_so_free(struct nine_shader_variant_so *list)
2307ec681f3Smrg{
2317ec681f3Smrg    while (list->next) {
2327ec681f3Smrg        struct nine_shader_variant_so *ptr = list->next;
2337ec681f3Smrg        list->next = ptr->next;
2347ec681f3Smrg        nine_bind(&ptr->vdecl, NULL);
2357ec681f3Smrg        FREE(ptr);
2367ec681f3Smrg    }
2377ec681f3Smrg    if (list->vdecl)
2387ec681f3Smrg        nine_bind(&list->vdecl, NULL);
2397ec681f3Smrg}
2407ec681f3Smrg
2417ec681f3Smrgstruct nine_shader_constant_combination
2427ec681f3Smrg{
2437ec681f3Smrg    struct nine_shader_constant_combination *next;
2447ec681f3Smrg    int const_i[NINE_MAX_CONST_I][4];
2457ec681f3Smrg    BOOL const_b[NINE_MAX_CONST_B];
2467ec681f3Smrg};
2477ec681f3Smrg
2487ec681f3Smrg#define NINE_MAX_CONSTANT_COMBINATION_VARIANTS 32
2497ec681f3Smrg
2507ec681f3Smrgstatic inline uint8_t
2517ec681f3Smrgnine_shader_constant_combination_key(struct nine_shader_constant_combination **list,
2527ec681f3Smrg                                     boolean *int_slots_used,
2537ec681f3Smrg                                     boolean *bool_slots_used,
2547ec681f3Smrg                                     int *const_i,
2557ec681f3Smrg                                     BOOL *const_b)
2567ec681f3Smrg{
2577ec681f3Smrg    int i;
2587ec681f3Smrg    uint8_t index = 0;
2597ec681f3Smrg    boolean match;
2607ec681f3Smrg    struct nine_shader_constant_combination **next_allocate = list, *current = *list;
2617ec681f3Smrg
2627ec681f3Smrg    assert(int_slots_used);
2637ec681f3Smrg    assert(bool_slots_used);
2647ec681f3Smrg    assert(const_i);
2657ec681f3Smrg    assert(const_b);
2667ec681f3Smrg
2677ec681f3Smrg    while (current) {
2687ec681f3Smrg        index++; /* start at 1. 0 is for the variant without constant replacement */
2697ec681f3Smrg        match = TRUE;
2707ec681f3Smrg        for (i = 0; i < NINE_MAX_CONST_I; ++i) {
2717ec681f3Smrg            if (int_slots_used[i])
2727ec681f3Smrg                match &= !memcmp(const_i + 4*i, current->const_i[i], sizeof(current->const_i[0]));
2737ec681f3Smrg        }
2747ec681f3Smrg        for (i = 0; i < NINE_MAX_CONST_B; ++i) {
2757ec681f3Smrg            if (bool_slots_used[i])
2767ec681f3Smrg                match &= const_b[i] == current->const_b[i];
2777ec681f3Smrg        }
2787ec681f3Smrg        if (match)
2797ec681f3Smrg            return index;
2807ec681f3Smrg        next_allocate = &current->next;
2817ec681f3Smrg        current = current->next;
2827ec681f3Smrg    }
2837ec681f3Smrg
2847ec681f3Smrg    if (index < NINE_MAX_CONSTANT_COMBINATION_VARIANTS) {
2857ec681f3Smrg        *next_allocate = MALLOC_STRUCT(nine_shader_constant_combination);
2867ec681f3Smrg        current = *next_allocate;
2877ec681f3Smrg        index++;
2887ec681f3Smrg        current->next = NULL;
2897ec681f3Smrg        memcpy(current->const_i, const_i, sizeof(current->const_i));
2907ec681f3Smrg        memcpy(current->const_b, const_b, sizeof(current->const_b));
2917ec681f3Smrg        return index;
2927ec681f3Smrg    }
2937ec681f3Smrg
2947ec681f3Smrg    return 0; /* Too many variants, revert to no replacement */
2957ec681f3Smrg}
2967ec681f3Smrg
2977ec681f3Smrgstatic inline struct nine_shader_constant_combination *
2987ec681f3Smrgnine_shader_constant_combination_get(struct nine_shader_constant_combination *list, uint8_t index)
2997ec681f3Smrg{
3007ec681f3Smrg    if (index == 0)
3017ec681f3Smrg        return NULL;
3027ec681f3Smrg    while (index) {
3037ec681f3Smrg        assert(list != NULL);
3047ec681f3Smrg        index--;
3057ec681f3Smrg        if (index == 0)
3067ec681f3Smrg            return list;
3077ec681f3Smrg        list = list->next;
3087ec681f3Smrg    }
3097ec681f3Smrg    assert(FALSE);
3107ec681f3Smrg    return NULL;
3117ec681f3Smrg}
3127ec681f3Smrg
3137ec681f3Smrgstatic inline void
3147ec681f3Smrgnine_shader_constant_combination_free(struct nine_shader_constant_combination *list)
3157ec681f3Smrg{
3167ec681f3Smrg    if (!list)
3177ec681f3Smrg        return;
3187ec681f3Smrg
3197ec681f3Smrg    while (list->next) {
3207ec681f3Smrg        struct nine_shader_constant_combination *ptr = list->next;
3217ec681f3Smrg        list->next = ptr->next;
3227ec681f3Smrg        FREE(ptr);
3237ec681f3Smrg    }
3247ec681f3Smrg
3257ec681f3Smrg    FREE(list);
3267ec681f3Smrg}
3277ec681f3Smrg
3287ec681f3Smrg#endif /* _NINE_SHADER_H_ */
329