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