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 = ¤t->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