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; 36struct ureg_program; 37 38struct nine_lconstf /* NOTE: both pointers should be FREE'd by the user */ 39{ 40 struct nine_range *ranges; /* single MALLOC, but next-pointers valid */ 41 float *data; 42}; 43 44struct nine_shader_constant_combination; 45 46struct nine_shader_info 47{ 48 unsigned type; /* in, PIPE_SHADER_x */ 49 50 uint8_t version; /* (major << 4) | minor */ 51 52 const DWORD *byte_code; /* in, pointer to shader tokens */ 53 DWORD byte_size; /* out, size of data at byte_code */ 54 55 void *cso; /* out, pipe cso for bind_vs,fs_state */ 56 57 uint16_t input_map[PIPE_MAX_ATTRIBS]; /* VS input -> NINE_DECLUSAGE_x */ 58 uint8_t num_inputs; /* there may be unused inputs (NINE_DECLUSAGE_NONE) */ 59 60 boolean position_t; /* out, true if VP writes pre-transformed position */ 61 boolean point_size; /* out, true if VP writes point size */ 62 float point_size_min; 63 float point_size_max; 64 65 uint32_t sampler_ps1xtypes; /* 2 bits per sampler */ 66 uint16_t sampler_mask; /* out, which samplers are being used */ 67 uint16_t sampler_mask_shadow; /* in, which samplers use depth compare */ 68 uint8_t rt_mask; /* out, which render targets are being written */ 69 70 uint8_t fog_enable; 71 uint8_t fog_mode; 72 uint8_t force_color_in_centroid; 73 uint8_t projected; /* ps 1.1 to 1.3 */ 74 uint16_t fetch4; 75 76 unsigned const_i_base; /* in vec4 (16 byte) units */ 77 unsigned const_b_base; /* in vec4 (16 byte) units */ 78 unsigned const_used_size; 79 80 boolean int_slots_used[NINE_MAX_CONST_I]; 81 boolean bool_slots_used[NINE_MAX_CONST_B]; 82 83 unsigned const_float_slots; 84 unsigned const_int_slots; 85 unsigned const_bool_slots; 86 87 unsigned *const_ranges; 88 89 struct nine_lconstf lconstf; /* out, NOTE: members to be free'd by user */ 90 uint8_t bumpenvmat_needed; 91 92 struct { 93 struct nine_shader_constant_combination* c_combination; 94 boolean (*int_const_added)[NINE_MAX_CONST_I]; 95 boolean (*bool_const_added)[NINE_MAX_CONST_B]; 96 } add_constants_defs; 97 98 boolean swvp_on; 99 100 boolean process_vertices; 101 struct NineVertexDeclaration9 *vdecl_out; 102 struct pipe_stream_output_info so; 103}; 104 105struct nine_vs_output_info 106{ 107 BYTE output_semantic; 108 int output_semantic_index; 109 int mask; 110 int output_index; 111}; 112 113void * 114nine_create_shader_with_so_and_destroy(struct ureg_program *p, 115 struct pipe_context *pipe, 116 const struct pipe_stream_output_info *so); 117 118HRESULT 119nine_translate_shader(struct NineDevice9 *device, 120 struct nine_shader_info *, 121 struct pipe_context *); 122 123 124struct nine_shader_variant 125{ 126 struct nine_shader_variant *next; 127 void *cso; 128 unsigned *const_ranges; 129 unsigned const_used_size; 130 uint64_t key; 131}; 132 133static inline void * 134nine_shader_variant_get(struct nine_shader_variant *list, 135 unsigned **const_ranges, 136 unsigned *const_used_size, 137 uint64_t key) 138{ 139 while (list->key != key && list->next) 140 list = list->next; 141 if (list->key == key) { 142 *const_ranges = list->const_ranges; 143 *const_used_size = list->const_used_size; 144 return list->cso; 145 } 146 return NULL; 147} 148 149static inline boolean 150nine_shader_variant_add(struct nine_shader_variant *list, 151 uint64_t key, void *cso, 152 unsigned *const_ranges, 153 unsigned const_used_size) 154{ 155 while (list->next) { 156 assert(list->key != key); 157 list = list->next; 158 } 159 list->next = MALLOC_STRUCT(nine_shader_variant); 160 if (!list->next) 161 return FALSE; 162 list->next->next = NULL; 163 list->next->key = key; 164 list->next->cso = cso; 165 list->next->const_ranges = const_ranges; 166 list->next->const_used_size = const_used_size; 167 return TRUE; 168} 169 170static inline void 171nine_shader_variants_free(struct nine_shader_variant *list) 172{ 173 while (list->next) { 174 struct nine_shader_variant *ptr = list->next; 175 list->next = ptr->next; 176 FREE(ptr); 177 } 178} 179 180struct nine_shader_variant_so 181{ 182 struct nine_shader_variant_so *next; 183 struct NineVertexDeclaration9 *vdecl; 184 struct pipe_stream_output_info so; 185 void *cso; 186}; 187 188static inline void * 189nine_shader_variant_so_get(struct nine_shader_variant_so *list, 190 struct NineVertexDeclaration9 *vdecl, 191 struct pipe_stream_output_info *so) 192{ 193 while (list->vdecl != vdecl && list->next) 194 list = list->next; 195 if (list->vdecl == vdecl) { 196 *so = list->so; 197 return list->cso; 198 } 199 return NULL; 200} 201 202static inline boolean 203nine_shader_variant_so_add(struct nine_shader_variant_so *list, 204 struct NineVertexDeclaration9 *vdecl, 205 struct pipe_stream_output_info *so, void *cso) 206{ 207 if (list->vdecl == NULL) { /* first shader */ 208 list->next = NULL; 209 nine_bind(&list->vdecl, vdecl); 210 list->so = *so; 211 list->cso = cso; 212 return TRUE; 213 } 214 while (list->next) { 215 assert(list->vdecl != vdecl); 216 list = list->next; 217 } 218 list->next = MALLOC_STRUCT(nine_shader_variant_so); 219 if (!list->next) 220 return FALSE; 221 list->next->next = NULL; 222 nine_bind(&list->vdecl, vdecl); 223 list->next->so = *so; 224 list->next->cso = cso; 225 return TRUE; 226} 227 228static inline void 229nine_shader_variants_so_free(struct nine_shader_variant_so *list) 230{ 231 while (list->next) { 232 struct nine_shader_variant_so *ptr = list->next; 233 list->next = ptr->next; 234 nine_bind(&ptr->vdecl, NULL); 235 FREE(ptr); 236 } 237 if (list->vdecl) 238 nine_bind(&list->vdecl, NULL); 239} 240 241struct nine_shader_constant_combination 242{ 243 struct nine_shader_constant_combination *next; 244 int const_i[NINE_MAX_CONST_I][4]; 245 BOOL const_b[NINE_MAX_CONST_B]; 246}; 247 248#define NINE_MAX_CONSTANT_COMBINATION_VARIANTS 32 249 250static inline uint8_t 251nine_shader_constant_combination_key(struct nine_shader_constant_combination **list, 252 boolean *int_slots_used, 253 boolean *bool_slots_used, 254 int *const_i, 255 BOOL *const_b) 256{ 257 int i; 258 uint8_t index = 0; 259 boolean match; 260 struct nine_shader_constant_combination **next_allocate = list, *current = *list; 261 262 assert(int_slots_used); 263 assert(bool_slots_used); 264 assert(const_i); 265 assert(const_b); 266 267 while (current) { 268 index++; /* start at 1. 0 is for the variant without constant replacement */ 269 match = TRUE; 270 for (i = 0; i < NINE_MAX_CONST_I; ++i) { 271 if (int_slots_used[i]) 272 match &= !memcmp(const_i + 4*i, current->const_i[i], sizeof(current->const_i[0])); 273 } 274 for (i = 0; i < NINE_MAX_CONST_B; ++i) { 275 if (bool_slots_used[i]) 276 match &= const_b[i] == current->const_b[i]; 277 } 278 if (match) 279 return index; 280 next_allocate = ¤t->next; 281 current = current->next; 282 } 283 284 if (index < NINE_MAX_CONSTANT_COMBINATION_VARIANTS) { 285 *next_allocate = MALLOC_STRUCT(nine_shader_constant_combination); 286 current = *next_allocate; 287 index++; 288 current->next = NULL; 289 memcpy(current->const_i, const_i, sizeof(current->const_i)); 290 memcpy(current->const_b, const_b, sizeof(current->const_b)); 291 return index; 292 } 293 294 return 0; /* Too many variants, revert to no replacement */ 295} 296 297static inline struct nine_shader_constant_combination * 298nine_shader_constant_combination_get(struct nine_shader_constant_combination *list, uint8_t index) 299{ 300 if (index == 0) 301 return NULL; 302 while (index) { 303 assert(list != NULL); 304 index--; 305 if (index == 0) 306 return list; 307 list = list->next; 308 } 309 assert(FALSE); 310 return NULL; 311} 312 313static inline void 314nine_shader_constant_combination_free(struct nine_shader_constant_combination *list) 315{ 316 if (!list) 317 return; 318 319 while (list->next) { 320 struct nine_shader_constant_combination *ptr = list->next; 321 list->next = ptr->next; 322 FREE(ptr); 323 } 324 325 FREE(list); 326} 327 328#endif /* _NINE_SHADER_H_ */ 329