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 34struct NineDevice9; 35struct NineVertexDeclaration9; 36 37struct 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 43struct nine_shader_constant_combination; 44 45struct 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 unsigned *const_ranges; 86 87 struct nine_lconstf lconstf; /* out, NOTE: members to be free'd by user */ 88 uint8_t bumpenvmat_needed; 89 90 struct { 91 struct nine_shader_constant_combination* c_combination; 92 boolean (*int_const_added)[NINE_MAX_CONST_I]; 93 boolean (*bool_const_added)[NINE_MAX_CONST_B]; 94 } add_constants_defs; 95 96 boolean swvp_on; 97 98 boolean process_vertices; 99 struct NineVertexDeclaration9 *vdecl_out; 100 struct pipe_stream_output_info so; 101}; 102 103struct nine_vs_output_info 104{ 105 BYTE output_semantic; 106 int output_semantic_index; 107 int mask; 108 int output_index; 109}; 110 111HRESULT 112nine_translate_shader(struct NineDevice9 *device, 113 struct nine_shader_info *, 114 struct pipe_context *); 115 116 117struct nine_shader_variant 118{ 119 struct nine_shader_variant *next; 120 void *cso; 121 unsigned *const_ranges; 122 unsigned const_used_size; 123 uint64_t key; 124}; 125 126static inline void * 127nine_shader_variant_get(struct nine_shader_variant *list, 128 unsigned **const_ranges, 129 unsigned *const_used_size, 130 uint64_t key) 131{ 132 while (list->key != key && list->next) 133 list = list->next; 134 if (list->key == key) { 135 *const_ranges = list->const_ranges; 136 *const_used_size = list->const_used_size; 137 return list->cso; 138 } 139 return NULL; 140} 141 142static inline boolean 143nine_shader_variant_add(struct nine_shader_variant *list, 144 uint64_t key, void *cso, 145 unsigned *const_ranges, 146 unsigned const_used_size) 147{ 148 while (list->next) { 149 assert(list->key != key); 150 list = list->next; 151 } 152 list->next = MALLOC_STRUCT(nine_shader_variant); 153 if (!list->next) 154 return FALSE; 155 list->next->next = NULL; 156 list->next->key = key; 157 list->next->cso = cso; 158 list->next->const_ranges = const_ranges; 159 list->next->const_used_size = const_used_size; 160 return TRUE; 161} 162 163static inline void 164nine_shader_variants_free(struct nine_shader_variant *list) 165{ 166 while (list->next) { 167 struct nine_shader_variant *ptr = list->next; 168 list->next = ptr->next; 169 FREE(ptr); 170 } 171} 172 173struct nine_shader_variant_so 174{ 175 struct nine_shader_variant_so *next; 176 struct NineVertexDeclaration9 *vdecl; 177 struct pipe_stream_output_info so; 178 void *cso; 179}; 180 181static inline void * 182nine_shader_variant_so_get(struct nine_shader_variant_so *list, 183 struct NineVertexDeclaration9 *vdecl, 184 struct pipe_stream_output_info *so) 185{ 186 while (list->vdecl != vdecl && list->next) 187 list = list->next; 188 if (list->vdecl == vdecl) { 189 *so = list->so; 190 return list->cso; 191 } 192 return NULL; 193} 194 195static inline boolean 196nine_shader_variant_so_add(struct nine_shader_variant_so *list, 197 struct NineVertexDeclaration9 *vdecl, 198 struct pipe_stream_output_info *so, void *cso) 199{ 200 if (list->vdecl == NULL) { /* first shader */ 201 list->next = NULL; 202 nine_bind(&list->vdecl, vdecl); 203 list->so = *so; 204 list->cso = cso; 205 return TRUE; 206 } 207 while (list->next) { 208 assert(list->vdecl != vdecl); 209 list = list->next; 210 } 211 list->next = MALLOC_STRUCT(nine_shader_variant_so); 212 if (!list->next) 213 return FALSE; 214 list->next->next = NULL; 215 nine_bind(&list->vdecl, vdecl); 216 list->next->so = *so; 217 list->next->cso = cso; 218 return TRUE; 219} 220 221static inline void 222nine_shader_variants_so_free(struct nine_shader_variant_so *list) 223{ 224 while (list->next) { 225 struct nine_shader_variant_so *ptr = list->next; 226 list->next = ptr->next; 227 nine_bind(&ptr->vdecl, NULL); 228 FREE(ptr); 229 } 230 if (list->vdecl) 231 nine_bind(&list->vdecl, NULL); 232} 233 234struct nine_shader_constant_combination 235{ 236 struct nine_shader_constant_combination *next; 237 int const_i[NINE_MAX_CONST_I][4]; 238 BOOL const_b[NINE_MAX_CONST_B]; 239}; 240 241#define NINE_MAX_CONSTANT_COMBINATION_VARIANTS 32 242 243static inline uint8_t 244nine_shader_constant_combination_key(struct nine_shader_constant_combination **list, 245 boolean *int_slots_used, 246 boolean *bool_slots_used, 247 int *const_i, 248 BOOL *const_b) 249{ 250 int i; 251 uint8_t index = 0; 252 boolean match; 253 struct nine_shader_constant_combination **next_allocate = list, *current = *list; 254 255 assert(int_slots_used); 256 assert(bool_slots_used); 257 assert(const_i); 258 assert(const_b); 259 260 while (current) { 261 index++; /* start at 1. 0 is for the variant without constant replacement */ 262 match = TRUE; 263 for (i = 0; i < NINE_MAX_CONST_I; ++i) { 264 if (int_slots_used[i]) 265 match &= !memcmp(const_i + 4*i, current->const_i[i], sizeof(current->const_i[0])); 266 } 267 for (i = 0; i < NINE_MAX_CONST_B; ++i) { 268 if (bool_slots_used[i]) 269 match &= const_b[i] == current->const_b[i]; 270 } 271 if (match) 272 return index; 273 next_allocate = ¤t->next; 274 current = current->next; 275 } 276 277 if (index < NINE_MAX_CONSTANT_COMBINATION_VARIANTS) { 278 *next_allocate = MALLOC_STRUCT(nine_shader_constant_combination); 279 current = *next_allocate; 280 index++; 281 current->next = NULL; 282 memcpy(current->const_i, const_i, sizeof(current->const_i)); 283 memcpy(current->const_b, const_b, sizeof(current->const_b)); 284 return index; 285 } 286 287 return 0; /* Too many variants, revert to no replacement */ 288} 289 290static inline struct nine_shader_constant_combination * 291nine_shader_constant_combination_get(struct nine_shader_constant_combination *list, uint8_t index) 292{ 293 if (index == 0) 294 return NULL; 295 while (index) { 296 assert(list != NULL); 297 index--; 298 if (index == 0) 299 return list; 300 list = list->next; 301 } 302 assert(FALSE); 303 return NULL; 304} 305 306static inline void 307nine_shader_constant_combination_free(struct nine_shader_constant_combination *list) 308{ 309 if (!list) 310 return; 311 312 while (list->next) { 313 struct nine_shader_constant_combination *ptr = list->next; 314 list->next = ptr->next; 315 FREE(ptr); 316 } 317 318 FREE(list); 319} 320 321#endif /* _NINE_SHADER_H_ */ 322