r300_fs.c revision 36e0100e9e6afe7a00846514daffb8993dcc173e
1/* 2 * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com> 3 * Joakim Sindholt <opensource@zhasha.com> 4 * Copyright 2009 Marek Olšák <maraeo@gmail.com> 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * on the rights to use, copy, modify, merge, publish, distribute, sub 10 * license, and/or sell copies of the Software, and to permit persons to whom 11 * the Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the next 14 * paragraph) shall be included in all copies or substantial portions of the 15 * Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 20 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 21 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 22 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 23 * USE OR OTHER DEALINGS IN THE SOFTWARE. */ 24 25#include "util/u_math.h" 26#include "util/u_memory.h" 27 28#include "tgsi/tgsi_dump.h" 29#include "tgsi/tgsi_ureg.h" 30 31#include "r300_context.h" 32#include "r300_screen.h" 33#include "r300_fs.h" 34#include "r300_tgsi_to_rc.h" 35 36#include "radeon_code.h" 37#include "radeon_compiler.h" 38 39/* Convert info about FS input semantics to r300_shader_semantics. */ 40void r300_shader_read_fs_inputs(struct tgsi_shader_info* info, 41 struct r300_shader_semantics* fs_inputs) 42{ 43 int i; 44 unsigned index; 45 46 r300_shader_semantics_reset(fs_inputs); 47 48 for (i = 0; i < info->num_inputs; i++) { 49 index = info->input_semantic_index[i]; 50 51 switch (info->input_semantic_name[i]) { 52 case TGSI_SEMANTIC_COLOR: 53 assert(index < ATTR_COLOR_COUNT); 54 fs_inputs->color[index] = i; 55 break; 56 57 case TGSI_SEMANTIC_GENERIC: 58 assert(index < ATTR_GENERIC_COUNT); 59 fs_inputs->generic[index] = i; 60 break; 61 62 case TGSI_SEMANTIC_FOG: 63 assert(index == 0); 64 fs_inputs->fog = i; 65 break; 66 67 case TGSI_SEMANTIC_POSITION: 68 assert(index == 0); 69 fs_inputs->wpos = i; 70 break; 71 72 default: 73 fprintf(stderr, "r300: FP: Unknown input semantic: %i\n", 74 info->input_semantic_name[i]); 75 } 76 } 77} 78 79static void find_output_registers(struct r300_fragment_program_compiler * compiler, 80 struct r300_fragment_shader_code *shader) 81{ 82 unsigned i, colorbuf_count = 0; 83 84 /* Mark the outputs as not present initially */ 85 compiler->OutputColor[0] = shader->info.num_outputs; 86 compiler->OutputColor[1] = shader->info.num_outputs; 87 compiler->OutputColor[2] = shader->info.num_outputs; 88 compiler->OutputColor[3] = shader->info.num_outputs; 89 compiler->OutputDepth = shader->info.num_outputs; 90 91 /* Now see where they really are. */ 92 for(i = 0; i < shader->info.num_outputs; ++i) { 93 switch(shader->info.output_semantic_name[i]) { 94 case TGSI_SEMANTIC_COLOR: 95 compiler->OutputColor[colorbuf_count] = i; 96 colorbuf_count++; 97 break; 98 case TGSI_SEMANTIC_POSITION: 99 compiler->OutputDepth = i; 100 break; 101 } 102 } 103} 104 105static void allocate_hardware_inputs( 106 struct r300_fragment_program_compiler * c, 107 void (*allocate)(void * data, unsigned input, unsigned hwreg), 108 void * mydata) 109{ 110 struct r300_shader_semantics* inputs = 111 (struct r300_shader_semantics*)c->UserData; 112 int i, reg = 0; 113 114 /* Allocate input registers. */ 115 for (i = 0; i < ATTR_COLOR_COUNT; i++) { 116 if (inputs->color[i] != ATTR_UNUSED) { 117 allocate(mydata, inputs->color[i], reg++); 118 } 119 } 120 for (i = 0; i < ATTR_GENERIC_COUNT; i++) { 121 if (inputs->generic[i] != ATTR_UNUSED) { 122 allocate(mydata, inputs->generic[i], reg++); 123 } 124 } 125 if (inputs->fog != ATTR_UNUSED) { 126 allocate(mydata, inputs->fog, reg++); 127 } 128 if (inputs->wpos != ATTR_UNUSED) { 129 allocate(mydata, inputs->wpos, reg++); 130 } 131} 132 133static void get_external_state( 134 struct r300_context* r300, 135 struct r300_fragment_program_external_state* state) 136{ 137 struct r300_textures_state *texstate = r300->textures_state.state; 138 unsigned i; 139 140 for (i = 0; i < texstate->sampler_state_count; i++) { 141 struct r300_sampler_state* s = texstate->sampler_states[i]; 142 struct r300_texture *t; 143 144 if (!s || !texstate->sampler_views[i]) { 145 continue; 146 } 147 148 t = (struct r300_texture*)texstate->sampler_views[i]->base.texture; 149 150 if (s->state.compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { 151 /* XXX Gallium doesn't provide us with any information regarding 152 * this mode, so we are screwed. I'm setting 0 = LUMINANCE. */ 153 state->unit[i].depth_texture_mode = 0; 154 155 /* Fortunately, no need to translate this. */ 156 state->unit[i].texture_compare_func = s->state.compare_func; 157 } 158 159 state->unit[i].fake_npot = t->uses_pitch; 160 state->unit[i].non_normalized_coords = !s->state.normalized_coords; 161 162 /* XXX this should probably take into account STR, not just S. */ 163 switch (s->state.wrap_s) { 164 case PIPE_TEX_WRAP_REPEAT: 165 state->unit[i].wrap_mode = RC_WRAP_REPEAT; 166 break; 167 case PIPE_TEX_WRAP_CLAMP: 168 case PIPE_TEX_WRAP_CLAMP_TO_EDGE: 169 case PIPE_TEX_WRAP_CLAMP_TO_BORDER: 170 state->unit[i].wrap_mode = RC_WRAP_CLAMP; 171 break; 172 case PIPE_TEX_WRAP_MIRROR_REPEAT: 173 case PIPE_TEX_WRAP_MIRROR_CLAMP: 174 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: 175 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: 176 state->unit[i].wrap_mode = RC_WRAP_MIRROR; 177 break; 178 default: 179 state->unit[i].wrap_mode = RC_WRAP_NONE; 180 break; 181 } 182 } 183} 184 185static void r300_translate_fragment_shader( 186 struct r300_context* r300, 187 struct r300_fragment_shader_code* shader, 188 const struct tgsi_token *tokens); 189 190static void r300_dummy_fragment_shader( 191 struct r300_context* r300, 192 struct r300_fragment_shader_code* shader) 193{ 194 struct pipe_shader_state state; 195 struct ureg_program *ureg; 196 struct ureg_dst out; 197 struct ureg_src imm; 198 199 /* Make a simple fragment shader which outputs (0, 0, 0, 1) */ 200 ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT); 201 out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0); 202 imm = ureg_imm4f(ureg, 0, 0, 0, 1); 203 204 ureg_MOV(ureg, out, imm); 205 ureg_END(ureg); 206 207 state.tokens = ureg_finalize(ureg); 208 209 shader->dummy = TRUE; 210 r300_translate_fragment_shader(r300, shader, state.tokens); 211 212 ureg_destroy(ureg); 213} 214 215static void r300_translate_fragment_shader( 216 struct r300_context* r300, 217 struct r300_fragment_shader_code* shader, 218 const struct tgsi_token *tokens) 219{ 220 struct r300_fragment_program_compiler compiler; 221 struct tgsi_to_rc ttr; 222 int wpos; 223 unsigned i; 224 225 tgsi_scan_shader(tokens, &shader->info); 226 r300_shader_read_fs_inputs(&shader->info, &shader->inputs); 227 228 wpos = shader->inputs.wpos; 229 230 /* Setup the compiler. */ 231 memset(&compiler, 0, sizeof(compiler)); 232 rc_init(&compiler.Base); 233 compiler.Base.Debug = DBG_ON(r300, DBG_FP); 234 235 compiler.code = &shader->code; 236 compiler.state = shader->compare_state; 237 compiler.is_r500 = r300->screen->caps.is_r500; 238 compiler.max_temp_regs = compiler.is_r500 ? 128 : 32; 239 compiler.AllocateHwInputs = &allocate_hardware_inputs; 240 compiler.UserData = &shader->inputs; 241 242 find_output_registers(&compiler, shader); 243 244 if (compiler.Base.Debug) { 245 debug_printf("r300: Initial fragment program\n"); 246 tgsi_dump(tokens, 0); 247 } 248 249 /* Translate TGSI to our internal representation */ 250 ttr.compiler = &compiler.Base; 251 ttr.info = &shader->info; 252 ttr.use_half_swizzles = TRUE; 253 254 r300_tgsi_to_rc(&ttr, tokens); 255 256 /** 257 * Transform the program to support WPOS. 258 * 259 * Introduce a small fragment at the start of the program that will be 260 * the only code that directly reads the WPOS input. 261 * All other code pieces that reference that input will be rewritten 262 * to read from a newly allocated temporary. */ 263 if (wpos != ATTR_UNUSED) { 264 /* Moving the input to some other reg is not really necessary. */ 265 rc_transform_fragment_wpos(&compiler.Base, wpos, wpos, TRUE); 266 } 267 268 /* Invoke the compiler */ 269 r3xx_compile_fragment_program(&compiler); 270 271 if (compiler.Base.Error) { 272 fprintf(stderr, "r300 FP: Compiler Error:\n%sUsing a dummy shader" 273 " instead.\n", compiler.Base.ErrorMsg); 274 275 if (shader->dummy) { 276 fprintf(stderr, "r300 FP: Cannot compile the dummy shader! " 277 "Giving up...\n"); 278 abort(); 279 } 280 r300_dummy_fragment_shader(r300, shader); 281 } 282 283 /* Initialize numbers of constants for each type. */ 284 shader->externals_count = ttr.immediate_offset; 285 shader->immediates_count = 0; 286 shader->rc_state_count = 0; 287 288 for (i = shader->externals_count; i < shader->code.constants.Count; i++) { 289 switch (shader->code.constants.Constants[i].Type) { 290 case RC_CONSTANT_IMMEDIATE: 291 ++shader->immediates_count; 292 break; 293 case RC_CONSTANT_STATE: 294 ++shader->rc_state_count; 295 break; 296 default: 297 assert(0); 298 } 299 } 300 301 /* And, finally... */ 302 rc_destroy(&compiler.Base); 303} 304 305boolean r300_pick_fragment_shader(struct r300_context* r300) 306{ 307 struct r300_fragment_shader* fs = r300_fs(r300); 308 struct r300_fragment_program_external_state state = {{{ 0 }}}; 309 struct r300_fragment_shader_code* ptr; 310 311 get_external_state(r300, &state); 312 313 if (!fs->first) { 314 /* Build the fragment shader for the first time. */ 315 fs->first = fs->shader = CALLOC_STRUCT(r300_fragment_shader_code); 316 317 memcpy(&fs->shader->compare_state, &state, 318 sizeof(struct r300_fragment_program_external_state)); 319 r300_translate_fragment_shader(r300, fs->shader, fs->state.tokens); 320 return TRUE; 321 322 } else { 323 /* Check if the currently-bound shader has been compiled 324 * with the texture-compare state we need. */ 325 if (memcmp(&fs->shader->compare_state, &state, sizeof(state)) != 0) { 326 /* Search for the right shader. */ 327 ptr = fs->first; 328 while (ptr) { 329 if (memcmp(&ptr->compare_state, &state, sizeof(state)) == 0) { 330 fs->shader = ptr; 331 return TRUE; 332 } 333 ptr = ptr->next; 334 } 335 336 /* Not found, gotta compile a new one. */ 337 ptr = CALLOC_STRUCT(r300_fragment_shader_code); 338 ptr->next = fs->first; 339 fs->first = fs->shader = ptr; 340 341 ptr->compare_state = state; 342 r300_translate_fragment_shader(r300, ptr, fs->state.tokens); 343 return TRUE; 344 } 345 } 346 347 return FALSE; 348} 349