1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright 2009 Corbin Simpson <MostAwesomeDude@gmail.com> 3bf215546Sopenharmony_ci * Copyright 2009 Marek Olšák <maraeo@gmail.com> 4bf215546Sopenharmony_ci * 5bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 6bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 7bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 8bf215546Sopenharmony_ci * on the rights to use, copy, modify, merge, publish, distribute, sub 9bf215546Sopenharmony_ci * license, and/or sell copies of the Software, and to permit persons to whom 10bf215546Sopenharmony_ci * the Software is furnished to do so, subject to the following conditions: 11bf215546Sopenharmony_ci * 12bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 13bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 14bf215546Sopenharmony_ci * Software. 15bf215546Sopenharmony_ci * 16bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 19bf215546Sopenharmony_ci * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 20bf215546Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 21bf215546Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 22bf215546Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE. */ 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci#include "r300_vs.h" 25bf215546Sopenharmony_ci 26bf215546Sopenharmony_ci#include "r300_context.h" 27bf215546Sopenharmony_ci#include "r300_screen.h" 28bf215546Sopenharmony_ci#include "r300_tgsi_to_rc.h" 29bf215546Sopenharmony_ci#include "r300_reg.h" 30bf215546Sopenharmony_ci 31bf215546Sopenharmony_ci#include "tgsi/tgsi_dump.h" 32bf215546Sopenharmony_ci#include "tgsi/tgsi_parse.h" 33bf215546Sopenharmony_ci#include "tgsi/tgsi_ureg.h" 34bf215546Sopenharmony_ci 35bf215546Sopenharmony_ci#include "compiler/radeon_compiler.h" 36bf215546Sopenharmony_ci 37bf215546Sopenharmony_ci/* Convert info about VS output semantics into r300_shader_semantics. */ 38bf215546Sopenharmony_cistatic void r300_shader_read_vs_outputs( 39bf215546Sopenharmony_ci struct r300_context *r300, 40bf215546Sopenharmony_ci struct tgsi_shader_info* info, 41bf215546Sopenharmony_ci struct r300_shader_semantics* vs_outputs) 42bf215546Sopenharmony_ci{ 43bf215546Sopenharmony_ci int i; 44bf215546Sopenharmony_ci unsigned index; 45bf215546Sopenharmony_ci 46bf215546Sopenharmony_ci r300_shader_semantics_reset(vs_outputs); 47bf215546Sopenharmony_ci 48bf215546Sopenharmony_ci for (i = 0; i < info->num_outputs; i++) { 49bf215546Sopenharmony_ci index = info->output_semantic_index[i]; 50bf215546Sopenharmony_ci 51bf215546Sopenharmony_ci switch (info->output_semantic_name[i]) { 52bf215546Sopenharmony_ci case TGSI_SEMANTIC_POSITION: 53bf215546Sopenharmony_ci assert(index == 0); 54bf215546Sopenharmony_ci vs_outputs->pos = i; 55bf215546Sopenharmony_ci break; 56bf215546Sopenharmony_ci 57bf215546Sopenharmony_ci case TGSI_SEMANTIC_PSIZE: 58bf215546Sopenharmony_ci assert(index == 0); 59bf215546Sopenharmony_ci vs_outputs->psize = i; 60bf215546Sopenharmony_ci break; 61bf215546Sopenharmony_ci 62bf215546Sopenharmony_ci case TGSI_SEMANTIC_COLOR: 63bf215546Sopenharmony_ci assert(index < ATTR_COLOR_COUNT); 64bf215546Sopenharmony_ci vs_outputs->color[index] = i; 65bf215546Sopenharmony_ci break; 66bf215546Sopenharmony_ci 67bf215546Sopenharmony_ci case TGSI_SEMANTIC_BCOLOR: 68bf215546Sopenharmony_ci assert(index < ATTR_COLOR_COUNT); 69bf215546Sopenharmony_ci vs_outputs->bcolor[index] = i; 70bf215546Sopenharmony_ci break; 71bf215546Sopenharmony_ci 72bf215546Sopenharmony_ci case TGSI_SEMANTIC_GENERIC: 73bf215546Sopenharmony_ci assert(index < ATTR_GENERIC_COUNT); 74bf215546Sopenharmony_ci vs_outputs->generic[index] = i; 75bf215546Sopenharmony_ci vs_outputs->num_generic++; 76bf215546Sopenharmony_ci break; 77bf215546Sopenharmony_ci 78bf215546Sopenharmony_ci case TGSI_SEMANTIC_FOG: 79bf215546Sopenharmony_ci assert(index == 0); 80bf215546Sopenharmony_ci vs_outputs->fog = i; 81bf215546Sopenharmony_ci break; 82bf215546Sopenharmony_ci 83bf215546Sopenharmony_ci case TGSI_SEMANTIC_EDGEFLAG: 84bf215546Sopenharmony_ci assert(index == 0); 85bf215546Sopenharmony_ci fprintf(stderr, "r300 VP: cannot handle edgeflag output.\n"); 86bf215546Sopenharmony_ci break; 87bf215546Sopenharmony_ci 88bf215546Sopenharmony_ci case TGSI_SEMANTIC_CLIPVERTEX: 89bf215546Sopenharmony_ci assert(index == 0); 90bf215546Sopenharmony_ci /* Draw does clip vertex for us. */ 91bf215546Sopenharmony_ci if (r300->screen->caps.has_tcl) { 92bf215546Sopenharmony_ci fprintf(stderr, "r300 VP: cannot handle clip vertex output.\n"); 93bf215546Sopenharmony_ci } 94bf215546Sopenharmony_ci break; 95bf215546Sopenharmony_ci 96bf215546Sopenharmony_ci default: 97bf215546Sopenharmony_ci fprintf(stderr, "r300 VP: unknown vertex output semantic: %i.\n", 98bf215546Sopenharmony_ci info->output_semantic_name[i]); 99bf215546Sopenharmony_ci } 100bf215546Sopenharmony_ci } 101bf215546Sopenharmony_ci 102bf215546Sopenharmony_ci /* WPOS is a straight copy of POSITION */ 103bf215546Sopenharmony_ci vs_outputs->wpos = i; 104bf215546Sopenharmony_ci} 105bf215546Sopenharmony_ci 106bf215546Sopenharmony_cistatic void set_vertex_inputs_outputs(struct r300_vertex_program_compiler * c) 107bf215546Sopenharmony_ci{ 108bf215546Sopenharmony_ci struct r300_vertex_shader_code * vs = c->UserData; 109bf215546Sopenharmony_ci struct r300_shader_semantics* outputs = &vs->outputs; 110bf215546Sopenharmony_ci struct tgsi_shader_info* info = &vs->info; 111bf215546Sopenharmony_ci int i, reg = 0; 112bf215546Sopenharmony_ci boolean any_bcolor_used = outputs->bcolor[0] != ATTR_UNUSED || 113bf215546Sopenharmony_ci outputs->bcolor[1] != ATTR_UNUSED; 114bf215546Sopenharmony_ci 115bf215546Sopenharmony_ci /* Fill in the input mapping */ 116bf215546Sopenharmony_ci for (i = 0; i < info->num_inputs; i++) 117bf215546Sopenharmony_ci c->code->inputs[i] = i; 118bf215546Sopenharmony_ci 119bf215546Sopenharmony_ci /* Position. */ 120bf215546Sopenharmony_ci if (outputs->pos != ATTR_UNUSED) { 121bf215546Sopenharmony_ci c->code->outputs[outputs->pos] = reg++; 122bf215546Sopenharmony_ci } else { 123bf215546Sopenharmony_ci assert(0); 124bf215546Sopenharmony_ci } 125bf215546Sopenharmony_ci 126bf215546Sopenharmony_ci /* Point size. */ 127bf215546Sopenharmony_ci if (outputs->psize != ATTR_UNUSED) { 128bf215546Sopenharmony_ci c->code->outputs[outputs->psize] = reg++; 129bf215546Sopenharmony_ci } 130bf215546Sopenharmony_ci 131bf215546Sopenharmony_ci /* If we're writing back facing colors we need to send 132bf215546Sopenharmony_ci * four colors to make front/back face colors selection work. 133bf215546Sopenharmony_ci * If the vertex program doesn't write all 4 colors, lets 134bf215546Sopenharmony_ci * pretend it does by skipping output index reg so the colors 135bf215546Sopenharmony_ci * get written into appropriate output vectors. 136bf215546Sopenharmony_ci */ 137bf215546Sopenharmony_ci 138bf215546Sopenharmony_ci /* Colors. */ 139bf215546Sopenharmony_ci for (i = 0; i < ATTR_COLOR_COUNT; i++) { 140bf215546Sopenharmony_ci if (outputs->color[i] != ATTR_UNUSED) { 141bf215546Sopenharmony_ci c->code->outputs[outputs->color[i]] = reg++; 142bf215546Sopenharmony_ci } else if (any_bcolor_used || 143bf215546Sopenharmony_ci outputs->color[1] != ATTR_UNUSED) { 144bf215546Sopenharmony_ci reg++; 145bf215546Sopenharmony_ci } 146bf215546Sopenharmony_ci } 147bf215546Sopenharmony_ci 148bf215546Sopenharmony_ci /* Back-face colors. */ 149bf215546Sopenharmony_ci for (i = 0; i < ATTR_COLOR_COUNT; i++) { 150bf215546Sopenharmony_ci if (outputs->bcolor[i] != ATTR_UNUSED) { 151bf215546Sopenharmony_ci c->code->outputs[outputs->bcolor[i]] = reg++; 152bf215546Sopenharmony_ci } else if (any_bcolor_used) { 153bf215546Sopenharmony_ci reg++; 154bf215546Sopenharmony_ci } 155bf215546Sopenharmony_ci } 156bf215546Sopenharmony_ci 157bf215546Sopenharmony_ci /* Texture coordinates. */ 158bf215546Sopenharmony_ci for (i = 0; i < ATTR_GENERIC_COUNT; i++) { 159bf215546Sopenharmony_ci if (outputs->generic[i] != ATTR_UNUSED) { 160bf215546Sopenharmony_ci c->code->outputs[outputs->generic[i]] = reg++; 161bf215546Sopenharmony_ci } 162bf215546Sopenharmony_ci } 163bf215546Sopenharmony_ci 164bf215546Sopenharmony_ci /* Fog coordinates. */ 165bf215546Sopenharmony_ci if (outputs->fog != ATTR_UNUSED) { 166bf215546Sopenharmony_ci c->code->outputs[outputs->fog] = reg++; 167bf215546Sopenharmony_ci } 168bf215546Sopenharmony_ci 169bf215546Sopenharmony_ci /* WPOS. */ 170bf215546Sopenharmony_ci if (vs->wpos) 171bf215546Sopenharmony_ci c->code->outputs[outputs->wpos] = reg++; 172bf215546Sopenharmony_ci} 173bf215546Sopenharmony_ci 174bf215546Sopenharmony_civoid r300_init_vs_outputs(struct r300_context *r300, 175bf215546Sopenharmony_ci struct r300_vertex_shader *vs) 176bf215546Sopenharmony_ci{ 177bf215546Sopenharmony_ci tgsi_scan_shader(vs->state.tokens, &vs->shader->info); 178bf215546Sopenharmony_ci r300_shader_read_vs_outputs(r300, &vs->shader->info, &vs->shader->outputs); 179bf215546Sopenharmony_ci} 180bf215546Sopenharmony_ci 181bf215546Sopenharmony_civoid r300_translate_vertex_shader(struct r300_context *r300, 182bf215546Sopenharmony_ci struct r300_vertex_shader *shader) 183bf215546Sopenharmony_ci{ 184bf215546Sopenharmony_ci struct r300_vertex_program_compiler compiler; 185bf215546Sopenharmony_ci struct tgsi_to_rc ttr; 186bf215546Sopenharmony_ci unsigned i; 187bf215546Sopenharmony_ci struct r300_vertex_shader_code *vs = shader->shader; 188bf215546Sopenharmony_ci 189bf215546Sopenharmony_ci r300_init_vs_outputs(r300, shader); 190bf215546Sopenharmony_ci 191bf215546Sopenharmony_ci /* Setup the compiler */ 192bf215546Sopenharmony_ci memset(&compiler, 0, sizeof(compiler)); 193bf215546Sopenharmony_ci rc_init(&compiler.Base, NULL); 194bf215546Sopenharmony_ci 195bf215546Sopenharmony_ci DBG_ON(r300, DBG_VP) ? compiler.Base.Debug |= RC_DBG_LOG : 0; 196bf215546Sopenharmony_ci compiler.code = &vs->code; 197bf215546Sopenharmony_ci compiler.UserData = vs; 198bf215546Sopenharmony_ci compiler.Base.debug = &r300->debug; 199bf215546Sopenharmony_ci compiler.Base.is_r500 = r300->screen->caps.is_r500; 200bf215546Sopenharmony_ci compiler.Base.disable_optimizations = DBG_ON(r300, DBG_NO_OPT); 201bf215546Sopenharmony_ci compiler.Base.has_half_swizzles = FALSE; 202bf215546Sopenharmony_ci compiler.Base.has_presub = FALSE; 203bf215546Sopenharmony_ci compiler.Base.has_omod = FALSE; 204bf215546Sopenharmony_ci compiler.Base.needs_trig_input_transform = DBG_ON(r300, DBG_USE_TGSI); 205bf215546Sopenharmony_ci compiler.Base.max_temp_regs = 32; 206bf215546Sopenharmony_ci compiler.Base.max_constants = 256; 207bf215546Sopenharmony_ci compiler.Base.max_alu_insts = r300->screen->caps.is_r500 ? 1024 : 256; 208bf215546Sopenharmony_ci 209bf215546Sopenharmony_ci if (compiler.Base.Debug & RC_DBG_LOG) { 210bf215546Sopenharmony_ci DBG(r300, DBG_VP, "r300: Initial vertex program\n"); 211bf215546Sopenharmony_ci tgsi_dump(shader->state.tokens, 0); 212bf215546Sopenharmony_ci } 213bf215546Sopenharmony_ci 214bf215546Sopenharmony_ci /* Translate TGSI to our internal representation */ 215bf215546Sopenharmony_ci ttr.compiler = &compiler.Base; 216bf215546Sopenharmony_ci ttr.info = &vs->info; 217bf215546Sopenharmony_ci ttr.use_half_swizzles = FALSE; 218bf215546Sopenharmony_ci 219bf215546Sopenharmony_ci r300_tgsi_to_rc(&ttr, shader->state.tokens); 220bf215546Sopenharmony_ci 221bf215546Sopenharmony_ci if (ttr.error) { 222bf215546Sopenharmony_ci fprintf(stderr, "r300 VP: Cannot translate a shader. " 223bf215546Sopenharmony_ci "Corresponding draws will be skipped.\n"); 224bf215546Sopenharmony_ci vs->dummy = TRUE; 225bf215546Sopenharmony_ci return; 226bf215546Sopenharmony_ci } 227bf215546Sopenharmony_ci 228bf215546Sopenharmony_ci if (compiler.Base.Program.Constants.Count > 200) { 229bf215546Sopenharmony_ci compiler.Base.remove_unused_constants = TRUE; 230bf215546Sopenharmony_ci } 231bf215546Sopenharmony_ci 232bf215546Sopenharmony_ci compiler.RequiredOutputs = ~(~0U << (vs->info.num_outputs + (vs->wpos ? 1 : 0))); 233bf215546Sopenharmony_ci compiler.SetHwInputOutput = &set_vertex_inputs_outputs; 234bf215546Sopenharmony_ci 235bf215546Sopenharmony_ci /* Insert the WPOS output. */ 236bf215546Sopenharmony_ci if (vs->wpos) 237bf215546Sopenharmony_ci rc_copy_output(&compiler.Base, vs->outputs.pos, vs->outputs.wpos); 238bf215546Sopenharmony_ci 239bf215546Sopenharmony_ci /* Invoke the compiler */ 240bf215546Sopenharmony_ci r3xx_compile_vertex_program(&compiler); 241bf215546Sopenharmony_ci if (compiler.Base.Error) { 242bf215546Sopenharmony_ci fprintf(stderr, "r300 VP: Compiler error:\n%sCorresponding draws will be" 243bf215546Sopenharmony_ci " skipped.\n", compiler.Base.ErrorMsg); 244bf215546Sopenharmony_ci 245bf215546Sopenharmony_ci rc_destroy(&compiler.Base); 246bf215546Sopenharmony_ci vs->dummy = TRUE; 247bf215546Sopenharmony_ci return; 248bf215546Sopenharmony_ci } 249bf215546Sopenharmony_ci 250bf215546Sopenharmony_ci /* Initialize numbers of constants for each type. */ 251bf215546Sopenharmony_ci vs->externals_count = 0; 252bf215546Sopenharmony_ci for (i = 0; 253bf215546Sopenharmony_ci i < vs->code.constants.Count && 254bf215546Sopenharmony_ci vs->code.constants.Constants[i].Type == RC_CONSTANT_EXTERNAL; i++) { 255bf215546Sopenharmony_ci vs->externals_count = i+1; 256bf215546Sopenharmony_ci } 257bf215546Sopenharmony_ci for (; i < vs->code.constants.Count; i++) { 258bf215546Sopenharmony_ci assert(vs->code.constants.Constants[i].Type == RC_CONSTANT_IMMEDIATE); 259bf215546Sopenharmony_ci } 260bf215546Sopenharmony_ci vs->immediates_count = vs->code.constants.Count - vs->externals_count; 261bf215546Sopenharmony_ci 262bf215546Sopenharmony_ci /* And, finally... */ 263bf215546Sopenharmony_ci rc_destroy(&compiler.Base); 264bf215546Sopenharmony_ci} 265