14a49301eSmrg/* 24a49301eSmrg * Copyright 2009 Corbin Simpson <MostAwesomeDude@gmail.com> 3cdc920a0Smrg * Copyright 2009 Marek Olšák <maraeo@gmail.com> 44a49301eSmrg * 54a49301eSmrg * Permission is hereby granted, free of charge, to any person obtaining a 64a49301eSmrg * copy of this software and associated documentation files (the "Software"), 74a49301eSmrg * to deal in the Software without restriction, including without limitation 84a49301eSmrg * on the rights to use, copy, modify, merge, publish, distribute, sub 94a49301eSmrg * license, and/or sell copies of the Software, and to permit persons to whom 104a49301eSmrg * the Software is furnished to do so, subject to the following conditions: 114a49301eSmrg * 124a49301eSmrg * The above copyright notice and this permission notice (including the next 134a49301eSmrg * paragraph) shall be included in all copies or substantial portions of the 144a49301eSmrg * Software. 154a49301eSmrg * 164a49301eSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 174a49301eSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 184a49301eSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 194a49301eSmrg * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 204a49301eSmrg * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 214a49301eSmrg * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 224a49301eSmrg * USE OR OTHER DEALINGS IN THE SOFTWARE. */ 234a49301eSmrg 244a49301eSmrg#include "r300_vs.h" 254a49301eSmrg 264a49301eSmrg#include "r300_context.h" 27cdc920a0Smrg#include "r300_screen.h" 284a49301eSmrg#include "r300_tgsi_to_rc.h" 29cdc920a0Smrg#include "r300_reg.h" 304a49301eSmrg 314a49301eSmrg#include "tgsi/tgsi_dump.h" 324a49301eSmrg#include "tgsi/tgsi_parse.h" 333464ebd5Sriastradh#include "tgsi/tgsi_ureg.h" 344a49301eSmrg 35af69d88dSmrg#include "compiler/radeon_compiler.h" 364a49301eSmrg 37cdc920a0Smrg/* Convert info about VS output semantics into r300_shader_semantics. */ 38cdc920a0Smrgstatic void r300_shader_read_vs_outputs( 39af69d88dSmrg struct r300_context *r300, 40cdc920a0Smrg struct tgsi_shader_info* info, 41cdc920a0Smrg struct r300_shader_semantics* vs_outputs) 424a49301eSmrg{ 434a49301eSmrg int i; 44cdc920a0Smrg unsigned index; 454a49301eSmrg 46cdc920a0Smrg r300_shader_semantics_reset(vs_outputs); 474a49301eSmrg 484a49301eSmrg for (i = 0; i < info->num_outputs; i++) { 49cdc920a0Smrg index = info->output_semantic_index[i]; 50cdc920a0Smrg 514a49301eSmrg switch (info->output_semantic_name[i]) { 52cdc920a0Smrg case TGSI_SEMANTIC_POSITION: 53cdc920a0Smrg assert(index == 0); 54cdc920a0Smrg vs_outputs->pos = i; 55cdc920a0Smrg break; 56cdc920a0Smrg 574a49301eSmrg case TGSI_SEMANTIC_PSIZE: 58cdc920a0Smrg assert(index == 0); 59cdc920a0Smrg vs_outputs->psize = i; 604a49301eSmrg break; 61cdc920a0Smrg 624a49301eSmrg case TGSI_SEMANTIC_COLOR: 63cdc920a0Smrg assert(index < ATTR_COLOR_COUNT); 64cdc920a0Smrg vs_outputs->color[index] = i; 654a49301eSmrg break; 66cdc920a0Smrg 67cdc920a0Smrg case TGSI_SEMANTIC_BCOLOR: 68cdc920a0Smrg assert(index < ATTR_COLOR_COUNT); 69cdc920a0Smrg vs_outputs->bcolor[index] = i; 70cdc920a0Smrg break; 71cdc920a0Smrg 724a49301eSmrg case TGSI_SEMANTIC_GENERIC: 73cdc920a0Smrg assert(index < ATTR_GENERIC_COUNT); 74cdc920a0Smrg vs_outputs->generic[index] = i; 75af69d88dSmrg vs_outputs->num_generic++; 76cdc920a0Smrg break; 77cdc920a0Smrg 78cdc920a0Smrg case TGSI_SEMANTIC_FOG: 79cdc920a0Smrg assert(index == 0); 80cdc920a0Smrg vs_outputs->fog = i; 814a49301eSmrg break; 82cdc920a0Smrg 83cdc920a0Smrg case TGSI_SEMANTIC_EDGEFLAG: 84cdc920a0Smrg assert(index == 0); 853464ebd5Sriastradh fprintf(stderr, "r300 VP: cannot handle edgeflag output.\n"); 86cdc920a0Smrg break; 87cdc920a0Smrg 88af69d88dSmrg case TGSI_SEMANTIC_CLIPVERTEX: 89af69d88dSmrg assert(index == 0); 90af69d88dSmrg /* Draw does clip vertex for us. */ 91af69d88dSmrg if (r300->screen->caps.has_tcl) { 92af69d88dSmrg fprintf(stderr, "r300 VP: cannot handle clip vertex output.\n"); 93af69d88dSmrg } 94af69d88dSmrg break; 95af69d88dSmrg 963464ebd5Sriastradh default: 973464ebd5Sriastradh fprintf(stderr, "r300 VP: unknown vertex output semantic: %i.\n", 983464ebd5Sriastradh info->output_semantic_name[i]); 99cdc920a0Smrg } 100cdc920a0Smrg } 101cdc920a0Smrg 1023464ebd5Sriastradh /* WPOS is a straight copy of POSITION and it's always emitted. */ 1033464ebd5Sriastradh vs_outputs->wpos = i; 104cdc920a0Smrg} 105cdc920a0Smrg 106cdc920a0Smrgstatic void set_vertex_inputs_outputs(struct r300_vertex_program_compiler * c) 107cdc920a0Smrg{ 108cdc920a0Smrg struct r300_vertex_shader * vs = c->UserData; 109cdc920a0Smrg struct r300_shader_semantics* outputs = &vs->outputs; 110cdc920a0Smrg struct tgsi_shader_info* info = &vs->info; 111cdc920a0Smrg int i, reg = 0; 112cdc920a0Smrg boolean any_bcolor_used = outputs->bcolor[0] != ATTR_UNUSED || 113cdc920a0Smrg outputs->bcolor[1] != ATTR_UNUSED; 114cdc920a0Smrg 115cdc920a0Smrg /* Fill in the input mapping */ 116cdc920a0Smrg for (i = 0; i < info->num_inputs; i++) 117cdc920a0Smrg c->code->inputs[i] = i; 118cdc920a0Smrg 119cdc920a0Smrg /* Position. */ 120cdc920a0Smrg if (outputs->pos != ATTR_UNUSED) { 121cdc920a0Smrg c->code->outputs[outputs->pos] = reg++; 122cdc920a0Smrg } else { 123cdc920a0Smrg assert(0); 124cdc920a0Smrg } 125cdc920a0Smrg 126cdc920a0Smrg /* Point size. */ 127cdc920a0Smrg if (outputs->psize != ATTR_UNUSED) { 128cdc920a0Smrg c->code->outputs[outputs->psize] = reg++; 129cdc920a0Smrg } 130cdc920a0Smrg 131cdc920a0Smrg /* If we're writing back facing colors we need to send 132cdc920a0Smrg * four colors to make front/back face colors selection work. 133cdc920a0Smrg * If the vertex program doesn't write all 4 colors, lets 134cdc920a0Smrg * pretend it does by skipping output index reg so the colors 135cdc920a0Smrg * get written into appropriate output vectors. 136cdc920a0Smrg */ 137cdc920a0Smrg 138cdc920a0Smrg /* Colors. */ 139cdc920a0Smrg for (i = 0; i < ATTR_COLOR_COUNT; i++) { 140cdc920a0Smrg if (outputs->color[i] != ATTR_UNUSED) { 141cdc920a0Smrg c->code->outputs[outputs->color[i]] = reg++; 142cdc920a0Smrg } else if (any_bcolor_used || 143cdc920a0Smrg outputs->color[1] != ATTR_UNUSED) { 144cdc920a0Smrg reg++; 145cdc920a0Smrg } 146cdc920a0Smrg } 147cdc920a0Smrg 148cdc920a0Smrg /* Back-face colors. */ 149cdc920a0Smrg for (i = 0; i < ATTR_COLOR_COUNT; i++) { 150cdc920a0Smrg if (outputs->bcolor[i] != ATTR_UNUSED) { 151cdc920a0Smrg c->code->outputs[outputs->bcolor[i]] = reg++; 152cdc920a0Smrg } else if (any_bcolor_used) { 153cdc920a0Smrg reg++; 154cdc920a0Smrg } 155cdc920a0Smrg } 156cdc920a0Smrg 157cdc920a0Smrg /* Texture coordinates. */ 158cdc920a0Smrg for (i = 0; i < ATTR_GENERIC_COUNT; i++) { 159cdc920a0Smrg if (outputs->generic[i] != ATTR_UNUSED) { 160cdc920a0Smrg c->code->outputs[outputs->generic[i]] = reg++; 161cdc920a0Smrg } 162cdc920a0Smrg } 163cdc920a0Smrg 164cdc920a0Smrg /* Fog coordinates. */ 165cdc920a0Smrg if (outputs->fog != ATTR_UNUSED) { 166cdc920a0Smrg c->code->outputs[outputs->fog] = reg++; 167cdc920a0Smrg } 168cdc920a0Smrg 169cdc920a0Smrg /* WPOS. */ 1703464ebd5Sriastradh c->code->outputs[outputs->wpos] = reg++; 1713464ebd5Sriastradh} 1723464ebd5Sriastradh 173af69d88dSmrgvoid r300_init_vs_outputs(struct r300_context *r300, 174af69d88dSmrg struct r300_vertex_shader *vs) 1753464ebd5Sriastradh{ 1763464ebd5Sriastradh tgsi_scan_shader(vs->state.tokens, &vs->info); 177af69d88dSmrg r300_shader_read_vs_outputs(r300, &vs->info, &vs->outputs); 178cdc920a0Smrg} 179cdc920a0Smrg 1803464ebd5Sriastradhstatic void r300_dummy_vertex_shader( 1813464ebd5Sriastradh struct r300_context* r300, 1823464ebd5Sriastradh struct r300_vertex_shader* shader) 183cdc920a0Smrg{ 1843464ebd5Sriastradh struct ureg_program *ureg; 1853464ebd5Sriastradh struct ureg_dst dst; 1863464ebd5Sriastradh struct ureg_src imm; 187cdc920a0Smrg 1883464ebd5Sriastradh /* Make a simple vertex shader which outputs (0, 0, 0, 1), 1893464ebd5Sriastradh * effectively rendering nothing. */ 19001e04c3fSmrg ureg = ureg_create(PIPE_SHADER_VERTEX); 1913464ebd5Sriastradh dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0); 1923464ebd5Sriastradh imm = ureg_imm4f(ureg, 0, 0, 0, 1); 193cdc920a0Smrg 1943464ebd5Sriastradh ureg_MOV(ureg, dst, imm); 1953464ebd5Sriastradh ureg_END(ureg); 1963464ebd5Sriastradh 1973464ebd5Sriastradh shader->state.tokens = tgsi_dup_tokens(ureg_finalize(ureg)); 1983464ebd5Sriastradh ureg_destroy(ureg); 1993464ebd5Sriastradh 2003464ebd5Sriastradh shader->dummy = TRUE; 201af69d88dSmrg r300_init_vs_outputs(r300, shader); 2023464ebd5Sriastradh r300_translate_vertex_shader(r300, shader); 203cdc920a0Smrg} 2044a49301eSmrg 2053464ebd5Sriastradhvoid r300_translate_vertex_shader(struct r300_context *r300, 2063464ebd5Sriastradh struct r300_vertex_shader *vs) 2074a49301eSmrg{ 2084a49301eSmrg struct r300_vertex_program_compiler compiler; 2094a49301eSmrg struct tgsi_to_rc ttr; 2103464ebd5Sriastradh unsigned i; 211cdc920a0Smrg 2124a49301eSmrg /* Setup the compiler */ 2133464ebd5Sriastradh memset(&compiler, 0, sizeof(compiler)); 214af69d88dSmrg rc_init(&compiler.Base, NULL); 2154a49301eSmrg 2163464ebd5Sriastradh DBG_ON(r300, DBG_VP) ? compiler.Base.Debug |= RC_DBG_LOG : 0; 2173464ebd5Sriastradh DBG_ON(r300, DBG_P_STAT) ? compiler.Base.Debug |= RC_DBG_STATS : 0; 2184a49301eSmrg compiler.code = &vs->code; 2194a49301eSmrg compiler.UserData = vs; 2203464ebd5Sriastradh compiler.Base.is_r500 = r300->screen->caps.is_r500; 2213464ebd5Sriastradh compiler.Base.disable_optimizations = DBG_ON(r300, DBG_NO_OPT); 2223464ebd5Sriastradh compiler.Base.has_half_swizzles = FALSE; 2233464ebd5Sriastradh compiler.Base.has_presub = FALSE; 224af69d88dSmrg compiler.Base.has_omod = FALSE; 2253464ebd5Sriastradh compiler.Base.max_temp_regs = 32; 2263464ebd5Sriastradh compiler.Base.max_constants = 256; 2273464ebd5Sriastradh compiler.Base.max_alu_insts = r300->screen->caps.is_r500 ? 1024 : 256; 2283464ebd5Sriastradh 2293464ebd5Sriastradh if (compiler.Base.Debug & RC_DBG_LOG) { 2303464ebd5Sriastradh DBG(r300, DBG_VP, "r300: Initial vertex program\n"); 2314a49301eSmrg tgsi_dump(vs->state.tokens, 0); 2324a49301eSmrg } 2334a49301eSmrg 2344a49301eSmrg /* Translate TGSI to our internal representation */ 2354a49301eSmrg ttr.compiler = &compiler.Base; 2364a49301eSmrg ttr.info = &vs->info; 237cdc920a0Smrg ttr.use_half_swizzles = FALSE; 2384a49301eSmrg 2394a49301eSmrg r300_tgsi_to_rc(&ttr, vs->state.tokens); 2404a49301eSmrg 2413464ebd5Sriastradh if (ttr.error) { 2423464ebd5Sriastradh fprintf(stderr, "r300 VP: Cannot translate a shader. " 2433464ebd5Sriastradh "Using a dummy shader instead.\n"); 2443464ebd5Sriastradh r300_dummy_vertex_shader(r300, vs); 2453464ebd5Sriastradh return; 2463464ebd5Sriastradh } 2473464ebd5Sriastradh 2483464ebd5Sriastradh if (compiler.Base.Program.Constants.Count > 200) { 2493464ebd5Sriastradh compiler.Base.remove_unused_constants = TRUE; 2503464ebd5Sriastradh } 2513464ebd5Sriastradh 2527ec681f3Smrg compiler.RequiredOutputs = ~(~0U << (vs->info.num_outputs + 1)); 2534a49301eSmrg compiler.SetHwInputOutput = &set_vertex_inputs_outputs; 2544a49301eSmrg 255cdc920a0Smrg /* Insert the WPOS output. */ 2563464ebd5Sriastradh rc_copy_output(&compiler.Base, 0, vs->outputs.wpos); 257cdc920a0Smrg 2584a49301eSmrg /* Invoke the compiler */ 2594a49301eSmrg r3xx_compile_vertex_program(&compiler); 2604a49301eSmrg if (compiler.Base.Error) { 2613464ebd5Sriastradh fprintf(stderr, "r300 VP: Compiler error:\n%sUsing a dummy shader" 2623464ebd5Sriastradh " instead.\n", compiler.Base.ErrorMsg); 2633464ebd5Sriastradh 2643464ebd5Sriastradh if (vs->dummy) { 2653464ebd5Sriastradh fprintf(stderr, "r300 VP: Cannot compile the dummy shader! " 2663464ebd5Sriastradh "Giving up...\n"); 2673464ebd5Sriastradh abort(); 2683464ebd5Sriastradh } 2693464ebd5Sriastradh 2703464ebd5Sriastradh rc_destroy(&compiler.Base); 2713464ebd5Sriastradh r300_dummy_vertex_shader(r300, vs); 2723464ebd5Sriastradh return; 2733464ebd5Sriastradh } 2743464ebd5Sriastradh 2753464ebd5Sriastradh /* Initialize numbers of constants for each type. */ 2763464ebd5Sriastradh vs->externals_count = 0; 2773464ebd5Sriastradh for (i = 0; 2783464ebd5Sriastradh i < vs->code.constants.Count && 2793464ebd5Sriastradh vs->code.constants.Constants[i].Type == RC_CONSTANT_EXTERNAL; i++) { 2803464ebd5Sriastradh vs->externals_count = i+1; 2814a49301eSmrg } 2823464ebd5Sriastradh for (; i < vs->code.constants.Count; i++) { 2833464ebd5Sriastradh assert(vs->code.constants.Constants[i].Type == RC_CONSTANT_IMMEDIATE); 2843464ebd5Sriastradh } 2853464ebd5Sriastradh vs->immediates_count = vs->code.constants.Count - vs->externals_count; 2864a49301eSmrg 2874a49301eSmrg /* And, finally... */ 2884a49301eSmrg rc_destroy(&compiler.Base); 289cdc920a0Smrg} 290