r300_vs.c 8.07 KB
Newer Older
1
2
/*
 * Copyright 2009 Corbin Simpson <MostAwesomeDude@gmail.com>
Marek Olšák's avatar
Marek Olšák committed
3
 * Copyright 2009 Marek Olšák <maraeo@gmail.com>
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * on the rights to use, copy, modify, merge, publish, distribute, sub
 * license, and/or sell copies of the Software, and to permit persons to whom
 * the Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
 * USE OR OTHER DEALINGS IN THE SOFTWARE. */

24
#include "r300_vs.h"
25

26
#include "r300_context.h"
Marek Olšák's avatar
Marek Olšák committed
27
#include "r300_screen.h"
28
#include "r300_tgsi_to_rc.h"
Marek Olšák's avatar
Marek Olšák committed
29
#include "r300_reg.h"
30

31
32
#include "tgsi/tgsi_dump.h"
#include "tgsi/tgsi_parse.h"
33
#include "tgsi/tgsi_ureg.h"
34

35
#include "radeon_compiler.h"
36

Marek Olšák's avatar
Marek Olšák committed
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
/* Convert info about VS output semantics into r300_shader_semantics. */
static void r300_shader_read_vs_outputs(
    struct tgsi_shader_info* info,
    struct r300_shader_semantics* vs_outputs)
{
    int i;
    unsigned index;

    r300_shader_semantics_reset(vs_outputs);

    for (i = 0; i < info->num_outputs; i++) {
        index = info->output_semantic_index[i];

        switch (info->output_semantic_name[i]) {
            case TGSI_SEMANTIC_POSITION:
                assert(index == 0);
                vs_outputs->pos = i;
                break;

            case TGSI_SEMANTIC_PSIZE:
                assert(index == 0);
                vs_outputs->psize = i;
                break;

            case TGSI_SEMANTIC_COLOR:
62
                assert(index < ATTR_COLOR_COUNT);
Marek Olšák's avatar
Marek Olšák committed
63
64
65
66
                vs_outputs->color[index] = i;
                break;

            case TGSI_SEMANTIC_BCOLOR:
67
                assert(index < ATTR_COLOR_COUNT);
Marek Olšák's avatar
Marek Olšák committed
68
69
70
71
                vs_outputs->bcolor[index] = i;
                break;

            case TGSI_SEMANTIC_GENERIC:
72
                assert(index < ATTR_GENERIC_COUNT);
Marek Olšák's avatar
Marek Olšák committed
73
74
75
76
77
78
79
80
                vs_outputs->generic[index] = i;
                break;

            case TGSI_SEMANTIC_FOG:
                assert(index == 0);
                vs_outputs->fog = i;
                break;

81
82
            case TGSI_SEMANTIC_EDGEFLAG:
                assert(index == 0);
83
                fprintf(stderr, "r300 VP: cannot handle edgeflag output.\n");
84
                break;
85

Marek Olšák's avatar
Marek Olšák committed
86
            default:
87
88
                fprintf(stderr, "r300 VP: unknown vertex output semantic: %i.\n",
                        info->output_semantic_name[i]);
Marek Olšák's avatar
Marek Olšák committed
89
90
        }
    }
91
92
93

    /* WPOS is a straight copy of POSITION and it's always emitted. */
    vs_outputs->wpos = i;
Marek Olšák's avatar
Marek Olšák committed
94
95
}

96
static void set_vertex_inputs_outputs(struct r300_vertex_program_compiler * c)
97
{
98
    struct r300_vertex_shader * vs = c->UserData;
99
    struct r300_shader_semantics* outputs = &vs->outputs;
100
    struct tgsi_shader_info* info = &vs->info;
101
    int i, reg = 0;
102
103
    boolean any_bcolor_used = outputs->bcolor[0] != ATTR_UNUSED ||
                              outputs->bcolor[1] != ATTR_UNUSED;
104

105
106
107
108
    /* Fill in the input mapping */
    for (i = 0; i < info->num_inputs; i++)
        c->code->inputs[i] = i;

109
110
111
112
113
    /* Position. */
    if (outputs->pos != ATTR_UNUSED) {
        c->code->outputs[outputs->pos] = reg++;
    } else {
        assert(0);
114
    }
115

116
117
118
119
    /* Point size. */
    if (outputs->psize != ATTR_UNUSED) {
        c->code->outputs[outputs->psize] = reg++;
    }
120

121
122
123
124
125
126
127
    /* If we're writing back facing colors we need to send
     * four colors to make front/back face colors selection work.
     * If the vertex program doesn't write all 4 colors, lets
     * pretend it does by skipping output index reg so the colors
     * get written into appropriate output vectors.
     */

128
129
130
131
    /* Colors. */
    for (i = 0; i < ATTR_COLOR_COUNT; i++) {
        if (outputs->color[i] != ATTR_UNUSED) {
            c->code->outputs[outputs->color[i]] = reg++;
132
133
        } else if (any_bcolor_used ||
                   outputs->color[1] != ATTR_UNUSED) {
134
            reg++;
135
136
        }
    }
137

138
139
140
141
142
143
144
145
    /* Back-face colors. */
    for (i = 0; i < ATTR_COLOR_COUNT; i++) {
        if (outputs->bcolor[i] != ATTR_UNUSED) {
            c->code->outputs[outputs->bcolor[i]] = reg++;
        } else if (any_bcolor_used) {
            reg++;
        }
    }
146

147
148
149
150
    /* Texture coordinates. */
    for (i = 0; i < ATTR_GENERIC_COUNT; i++) {
        if (outputs->generic[i] != ATTR_UNUSED) {
            c->code->outputs[outputs->generic[i]] = reg++;
151
152
153
        }
    }

154
155
156
157
    /* Fog coordinates. */
    if (outputs->fog != ATTR_UNUSED) {
        c->code->outputs[outputs->fog] = reg++;
    }
Marek Olšák's avatar
Marek Olšák committed
158
159

    /* WPOS. */
160
    c->code->outputs[outputs->wpos] = reg++;
Marek Olšák's avatar
Marek Olšák committed
161
162
}

163
164
165
166
167
168
void r300_init_vs_outputs(struct r300_vertex_shader *vs)
{
    tgsi_scan_shader(vs->state.tokens, &vs->info);
    r300_shader_read_vs_outputs(&vs->info, &vs->outputs);
}

169
170
171
static void r300_dummy_vertex_shader(
    struct r300_context* r300,
    struct r300_vertex_shader* shader)
Marek Olšák's avatar
Marek Olšák committed
172
{
173
174
175
    struct ureg_program *ureg;
    struct ureg_dst dst;
    struct ureg_src imm;
Marek Olšák's avatar
Marek Olšák committed
176

177
178
179
180
181
182
183
184
185
    /* Make a simple vertex shader which outputs (0, 0, 0, 1),
     * effectively rendering nothing. */
    ureg = ureg_create(TGSI_PROCESSOR_VERTEX);
    dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0);
    imm = ureg_imm4f(ureg, 0, 0, 0, 1);

    ureg_MOV(ureg, dst, imm);
    ureg_END(ureg);

186
187
    shader->state.tokens = tgsi_dup_tokens(ureg_finalize(ureg));
    ureg_destroy(ureg);
188
189

    shader->dummy = TRUE;
190
    r300_init_vs_outputs(shader);
191
192
193
194
195
    r300_translate_vertex_shader(r300, shader);
}

void r300_translate_vertex_shader(struct r300_context *r300,
                                  struct r300_vertex_shader *vs)
196
197
198
{
    struct r300_vertex_program_compiler compiler;
    struct tgsi_to_rc ttr;
199
    unsigned i;
200

201
202
203
    /* Setup the compiler */
    rc_init(&compiler.Base);

204
    compiler.Base.Debug = DBG_ON(r300, DBG_VP);
205
206
    compiler.code = &vs->code;
    compiler.UserData = vs;
207
208
    compiler.Base.is_r500 = r300->screen->caps.is_r500;
    compiler.Base.max_temp_regs = 32;
209
    compiler.Base.remove_unused_constants = TRUE;
210
211

    if (compiler.Base.Debug) {
212
        DBG(r300, DBG_VP, "r300: Initial vertex program\n");
213
        tgsi_dump(vs->state.tokens, 0);
214
215
216
217
218
    }

    /* Translate TGSI to our internal representation */
    ttr.compiler = &compiler.Base;
    ttr.info = &vs->info;
219
    ttr.use_half_swizzles = FALSE;
220

221
    r300_tgsi_to_rc(&ttr, vs->state.tokens);
222

223
    compiler.RequiredOutputs = ~(~0 << (vs->info.num_outputs + 1));
224
225
    compiler.SetHwInputOutput = &set_vertex_inputs_outputs;

Marek Olšák's avatar
Marek Olšák committed
226
    /* Insert the WPOS output. */
227
    rc_copy_output(&compiler.Base, 0, vs->outputs.wpos);
Marek Olšák's avatar
Marek Olšák committed
228

229
230
231
    /* Invoke the compiler */
    r3xx_compile_vertex_program(&compiler);
    if (compiler.Base.Error) {
232
233
        fprintf(stderr, "r300 VP: Compiler error:\n%sUsing a dummy shader"
                " instead.\n", compiler.Base.ErrorMsg);
234
235
236
237
238
239

        if (vs->dummy) {
            fprintf(stderr, "r300 VP: Cannot compile the dummy shader! "
                    "Giving up...\n");
            abort();
        }
240
241

        rc_destroy(&compiler.Base);
242
        r300_dummy_vertex_shader(r300, vs);
243
        return;
244
    }
245

246
    /* Initialize numbers of constants for each type. */
247
248
249
250
251
252
253
254
255
    vs->externals_count = 0;
    for (i = 0;
         i < vs->code.constants.Count &&
         vs->code.constants.Constants[i].Type == RC_CONSTANT_EXTERNAL; i++) {
        vs->externals_count = i+1;
    }
    for (; i < vs->code.constants.Count; i++) {
        assert(vs->code.constants.Constants[i].Type == RC_CONSTANT_IMMEDIATE);
    }
256
257
    vs->immediates_count = vs->code.constants.Count - vs->externals_count;

258
    /* And, finally... */
259
    rc_destroy(&compiler.Base);
260
}