1848b8605Smrg/*
2848b8605Smrg * Copyright 2009 Corbin Simpson <MostAwesomeDude@gmail.com>
3848b8605Smrg * Copyright 2009 Marek Olšák <maraeo@gmail.com>
4848b8605Smrg *
5848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a
6848b8605Smrg * copy of this software and associated documentation files (the "Software"),
7848b8605Smrg * to deal in the Software without restriction, including without limitation
8848b8605Smrg * on the rights to use, copy, modify, merge, publish, distribute, sub
9848b8605Smrg * license, and/or sell copies of the Software, and to permit persons to whom
10848b8605Smrg * the Software is furnished to do so, subject to the following conditions:
11848b8605Smrg *
12848b8605Smrg * The above copyright notice and this permission notice (including the next
13848b8605Smrg * paragraph) shall be included in all copies or substantial portions of the
14848b8605Smrg * Software.
15848b8605Smrg *
16848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17848b8605Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19848b8605Smrg * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
20848b8605Smrg * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21848b8605Smrg * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
22848b8605Smrg * USE OR OTHER DEALINGS IN THE SOFTWARE. */
23848b8605Smrg
24848b8605Smrg#include "r300_vs.h"
25848b8605Smrg
26848b8605Smrg#include "r300_context.h"
27848b8605Smrg#include "r300_screen.h"
28848b8605Smrg#include "r300_tgsi_to_rc.h"
29848b8605Smrg#include "r300_reg.h"
30848b8605Smrg
31848b8605Smrg#include "tgsi/tgsi_dump.h"
32848b8605Smrg#include "tgsi/tgsi_parse.h"
33848b8605Smrg#include "tgsi/tgsi_ureg.h"
34848b8605Smrg
35848b8605Smrg#include "compiler/radeon_compiler.h"
36848b8605Smrg
37848b8605Smrg/* Convert info about VS output semantics into r300_shader_semantics. */
38848b8605Smrgstatic void r300_shader_read_vs_outputs(
39848b8605Smrg    struct r300_context *r300,
40848b8605Smrg    struct tgsi_shader_info* info,
41848b8605Smrg    struct r300_shader_semantics* vs_outputs)
42848b8605Smrg{
43848b8605Smrg    int i;
44848b8605Smrg    unsigned index;
45848b8605Smrg
46848b8605Smrg    r300_shader_semantics_reset(vs_outputs);
47848b8605Smrg
48848b8605Smrg    for (i = 0; i < info->num_outputs; i++) {
49848b8605Smrg        index = info->output_semantic_index[i];
50848b8605Smrg
51848b8605Smrg        switch (info->output_semantic_name[i]) {
52848b8605Smrg            case TGSI_SEMANTIC_POSITION:
53848b8605Smrg                assert(index == 0);
54848b8605Smrg                vs_outputs->pos = i;
55848b8605Smrg                break;
56848b8605Smrg
57848b8605Smrg            case TGSI_SEMANTIC_PSIZE:
58848b8605Smrg                assert(index == 0);
59848b8605Smrg                vs_outputs->psize = i;
60848b8605Smrg                break;
61848b8605Smrg
62848b8605Smrg            case TGSI_SEMANTIC_COLOR:
63848b8605Smrg                assert(index < ATTR_COLOR_COUNT);
64848b8605Smrg                vs_outputs->color[index] = i;
65848b8605Smrg                break;
66848b8605Smrg
67848b8605Smrg            case TGSI_SEMANTIC_BCOLOR:
68848b8605Smrg                assert(index < ATTR_COLOR_COUNT);
69848b8605Smrg                vs_outputs->bcolor[index] = i;
70848b8605Smrg                break;
71848b8605Smrg
72848b8605Smrg            case TGSI_SEMANTIC_GENERIC:
73848b8605Smrg                assert(index < ATTR_GENERIC_COUNT);
74848b8605Smrg                vs_outputs->generic[index] = i;
75848b8605Smrg                vs_outputs->num_generic++;
76848b8605Smrg                break;
77848b8605Smrg
78848b8605Smrg            case TGSI_SEMANTIC_FOG:
79848b8605Smrg                assert(index == 0);
80848b8605Smrg                vs_outputs->fog = i;
81848b8605Smrg                break;
82848b8605Smrg
83848b8605Smrg            case TGSI_SEMANTIC_EDGEFLAG:
84848b8605Smrg                assert(index == 0);
85848b8605Smrg                fprintf(stderr, "r300 VP: cannot handle edgeflag output.\n");
86848b8605Smrg                break;
87848b8605Smrg
88848b8605Smrg            case TGSI_SEMANTIC_CLIPVERTEX:
89848b8605Smrg                assert(index == 0);
90848b8605Smrg                /* Draw does clip vertex for us. */
91848b8605Smrg                if (r300->screen->caps.has_tcl) {
92848b8605Smrg                    fprintf(stderr, "r300 VP: cannot handle clip vertex output.\n");
93848b8605Smrg                }
94848b8605Smrg                break;
95848b8605Smrg
96848b8605Smrg            default:
97848b8605Smrg                fprintf(stderr, "r300 VP: unknown vertex output semantic: %i.\n",
98848b8605Smrg                        info->output_semantic_name[i]);
99848b8605Smrg        }
100848b8605Smrg    }
101848b8605Smrg
102848b8605Smrg    /* WPOS is a straight copy of POSITION and it's always emitted. */
103848b8605Smrg    vs_outputs->wpos = i;
104848b8605Smrg}
105848b8605Smrg
106848b8605Smrgstatic void set_vertex_inputs_outputs(struct r300_vertex_program_compiler * c)
107848b8605Smrg{
108848b8605Smrg    struct r300_vertex_shader * vs = c->UserData;
109848b8605Smrg    struct r300_shader_semantics* outputs = &vs->outputs;
110848b8605Smrg    struct tgsi_shader_info* info = &vs->info;
111848b8605Smrg    int i, reg = 0;
112848b8605Smrg    boolean any_bcolor_used = outputs->bcolor[0] != ATTR_UNUSED ||
113848b8605Smrg                              outputs->bcolor[1] != ATTR_UNUSED;
114848b8605Smrg
115848b8605Smrg    /* Fill in the input mapping */
116848b8605Smrg    for (i = 0; i < info->num_inputs; i++)
117848b8605Smrg        c->code->inputs[i] = i;
118848b8605Smrg
119848b8605Smrg    /* Position. */
120848b8605Smrg    if (outputs->pos != ATTR_UNUSED) {
121848b8605Smrg        c->code->outputs[outputs->pos] = reg++;
122848b8605Smrg    } else {
123848b8605Smrg        assert(0);
124848b8605Smrg    }
125848b8605Smrg
126848b8605Smrg    /* Point size. */
127848b8605Smrg    if (outputs->psize != ATTR_UNUSED) {
128848b8605Smrg        c->code->outputs[outputs->psize] = reg++;
129848b8605Smrg    }
130848b8605Smrg
131848b8605Smrg    /* If we're writing back facing colors we need to send
132848b8605Smrg     * four colors to make front/back face colors selection work.
133848b8605Smrg     * If the vertex program doesn't write all 4 colors, lets
134848b8605Smrg     * pretend it does by skipping output index reg so the colors
135848b8605Smrg     * get written into appropriate output vectors.
136848b8605Smrg     */
137848b8605Smrg
138848b8605Smrg    /* Colors. */
139848b8605Smrg    for (i = 0; i < ATTR_COLOR_COUNT; i++) {
140848b8605Smrg        if (outputs->color[i] != ATTR_UNUSED) {
141848b8605Smrg            c->code->outputs[outputs->color[i]] = reg++;
142848b8605Smrg        } else if (any_bcolor_used ||
143848b8605Smrg                   outputs->color[1] != ATTR_UNUSED) {
144848b8605Smrg            reg++;
145848b8605Smrg        }
146848b8605Smrg    }
147848b8605Smrg
148848b8605Smrg    /* Back-face colors. */
149848b8605Smrg    for (i = 0; i < ATTR_COLOR_COUNT; i++) {
150848b8605Smrg        if (outputs->bcolor[i] != ATTR_UNUSED) {
151848b8605Smrg            c->code->outputs[outputs->bcolor[i]] = reg++;
152848b8605Smrg        } else if (any_bcolor_used) {
153848b8605Smrg            reg++;
154848b8605Smrg        }
155848b8605Smrg    }
156848b8605Smrg
157848b8605Smrg    /* Texture coordinates. */
158848b8605Smrg    for (i = 0; i < ATTR_GENERIC_COUNT; i++) {
159848b8605Smrg        if (outputs->generic[i] != ATTR_UNUSED) {
160848b8605Smrg            c->code->outputs[outputs->generic[i]] = reg++;
161848b8605Smrg        }
162848b8605Smrg    }
163848b8605Smrg
164848b8605Smrg    /* Fog coordinates. */
165848b8605Smrg    if (outputs->fog != ATTR_UNUSED) {
166848b8605Smrg        c->code->outputs[outputs->fog] = reg++;
167848b8605Smrg    }
168848b8605Smrg
169848b8605Smrg    /* WPOS. */
170848b8605Smrg    c->code->outputs[outputs->wpos] = reg++;
171848b8605Smrg}
172848b8605Smrg
173848b8605Smrgvoid r300_init_vs_outputs(struct r300_context *r300,
174848b8605Smrg                          struct r300_vertex_shader *vs)
175848b8605Smrg{
176848b8605Smrg    tgsi_scan_shader(vs->state.tokens, &vs->info);
177848b8605Smrg    r300_shader_read_vs_outputs(r300, &vs->info, &vs->outputs);
178848b8605Smrg}
179848b8605Smrg
180848b8605Smrgstatic void r300_dummy_vertex_shader(
181848b8605Smrg    struct r300_context* r300,
182848b8605Smrg    struct r300_vertex_shader* shader)
183848b8605Smrg{
184848b8605Smrg    struct ureg_program *ureg;
185848b8605Smrg    struct ureg_dst dst;
186848b8605Smrg    struct ureg_src imm;
187848b8605Smrg
188848b8605Smrg    /* Make a simple vertex shader which outputs (0, 0, 0, 1),
189848b8605Smrg     * effectively rendering nothing. */
190b8e80941Smrg    ureg = ureg_create(PIPE_SHADER_VERTEX);
191848b8605Smrg    dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0);
192848b8605Smrg    imm = ureg_imm4f(ureg, 0, 0, 0, 1);
193848b8605Smrg
194848b8605Smrg    ureg_MOV(ureg, dst, imm);
195848b8605Smrg    ureg_END(ureg);
196848b8605Smrg
197848b8605Smrg    shader->state.tokens = tgsi_dup_tokens(ureg_finalize(ureg));
198848b8605Smrg    ureg_destroy(ureg);
199848b8605Smrg
200848b8605Smrg    shader->dummy = TRUE;
201848b8605Smrg    r300_init_vs_outputs(r300, shader);
202848b8605Smrg    r300_translate_vertex_shader(r300, shader);
203848b8605Smrg}
204848b8605Smrg
205848b8605Smrgvoid r300_translate_vertex_shader(struct r300_context *r300,
206848b8605Smrg                                  struct r300_vertex_shader *vs)
207848b8605Smrg{
208848b8605Smrg    struct r300_vertex_program_compiler compiler;
209848b8605Smrg    struct tgsi_to_rc ttr;
210848b8605Smrg    unsigned i;
211848b8605Smrg
212848b8605Smrg    /* Setup the compiler */
213848b8605Smrg    memset(&compiler, 0, sizeof(compiler));
214848b8605Smrg    rc_init(&compiler.Base, NULL);
215848b8605Smrg
216848b8605Smrg    DBG_ON(r300, DBG_VP) ? compiler.Base.Debug |= RC_DBG_LOG : 0;
217848b8605Smrg    DBG_ON(r300, DBG_P_STAT) ? compiler.Base.Debug |= RC_DBG_STATS : 0;
218848b8605Smrg    compiler.code = &vs->code;
219848b8605Smrg    compiler.UserData = vs;
220848b8605Smrg    compiler.Base.is_r500 = r300->screen->caps.is_r500;
221848b8605Smrg    compiler.Base.disable_optimizations = DBG_ON(r300, DBG_NO_OPT);
222848b8605Smrg    compiler.Base.has_half_swizzles = FALSE;
223848b8605Smrg    compiler.Base.has_presub = FALSE;
224848b8605Smrg    compiler.Base.has_omod = FALSE;
225848b8605Smrg    compiler.Base.max_temp_regs = 32;
226848b8605Smrg    compiler.Base.max_constants = 256;
227848b8605Smrg    compiler.Base.max_alu_insts = r300->screen->caps.is_r500 ? 1024 : 256;
228848b8605Smrg
229848b8605Smrg    if (compiler.Base.Debug & RC_DBG_LOG) {
230848b8605Smrg        DBG(r300, DBG_VP, "r300: Initial vertex program\n");
231848b8605Smrg        tgsi_dump(vs->state.tokens, 0);
232848b8605Smrg    }
233848b8605Smrg
234848b8605Smrg    /* Translate TGSI to our internal representation */
235848b8605Smrg    ttr.compiler = &compiler.Base;
236848b8605Smrg    ttr.info = &vs->info;
237848b8605Smrg    ttr.use_half_swizzles = FALSE;
238848b8605Smrg
239848b8605Smrg    r300_tgsi_to_rc(&ttr, vs->state.tokens);
240848b8605Smrg
241848b8605Smrg    if (ttr.error) {
242848b8605Smrg        fprintf(stderr, "r300 VP: Cannot translate a shader. "
243848b8605Smrg                "Using a dummy shader instead.\n");
244848b8605Smrg        r300_dummy_vertex_shader(r300, vs);
245848b8605Smrg        return;
246848b8605Smrg    }
247848b8605Smrg
248848b8605Smrg    if (compiler.Base.Program.Constants.Count > 200) {
249848b8605Smrg        compiler.Base.remove_unused_constants = TRUE;
250848b8605Smrg    }
251848b8605Smrg
252848b8605Smrg    compiler.RequiredOutputs = ~(~0 << (vs->info.num_outputs + 1));
253848b8605Smrg    compiler.SetHwInputOutput = &set_vertex_inputs_outputs;
254848b8605Smrg
255848b8605Smrg    /* Insert the WPOS output. */
256848b8605Smrg    rc_copy_output(&compiler.Base, 0, vs->outputs.wpos);
257848b8605Smrg
258848b8605Smrg    /* Invoke the compiler */
259848b8605Smrg    r3xx_compile_vertex_program(&compiler);
260848b8605Smrg    if (compiler.Base.Error) {
261848b8605Smrg        fprintf(stderr, "r300 VP: Compiler error:\n%sUsing a dummy shader"
262848b8605Smrg                " instead.\n", compiler.Base.ErrorMsg);
263848b8605Smrg
264848b8605Smrg        if (vs->dummy) {
265848b8605Smrg            fprintf(stderr, "r300 VP: Cannot compile the dummy shader! "
266848b8605Smrg                    "Giving up...\n");
267848b8605Smrg            abort();
268848b8605Smrg        }
269848b8605Smrg
270848b8605Smrg        rc_destroy(&compiler.Base);
271848b8605Smrg        r300_dummy_vertex_shader(r300, vs);
272848b8605Smrg        return;
273848b8605Smrg    }
274848b8605Smrg
275848b8605Smrg    /* Initialize numbers of constants for each type. */
276848b8605Smrg    vs->externals_count = 0;
277848b8605Smrg    for (i = 0;
278848b8605Smrg         i < vs->code.constants.Count &&
279848b8605Smrg         vs->code.constants.Constants[i].Type == RC_CONSTANT_EXTERNAL; i++) {
280848b8605Smrg        vs->externals_count = i+1;
281848b8605Smrg    }
282848b8605Smrg    for (; i < vs->code.constants.Count; i++) {
283848b8605Smrg        assert(vs->code.constants.Constants[i].Type == RC_CONSTANT_IMMEDIATE);
284848b8605Smrg    }
285848b8605Smrg    vs->immediates_count = vs->code.constants.Count - vs->externals_count;
286848b8605Smrg
287848b8605Smrg    /* And, finally... */
288848b8605Smrg    rc_destroy(&compiler.Base);
289848b8605Smrg}
290