r600_shader.c revision 8556b77c56f3f1f0e75ce46d6b5c0d84c7b4eabd
1/*
2 * Copyright 2010 Jerome Glisse <glisse@freedesktop.org>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * on the rights to use, copy, modify, merge, publish, distribute, sub
8 * license, and/or sell copies of the Software, and to permit persons to whom
9 * the Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE.
22 *
23 * Authors:
24 *      Jerome Glisse
25 */
26#include <stdio.h>
27#include <errno.h>
28#include <util/u_inlines.h>
29#include <util/u_format.h>
30#include <util/u_memory.h>
31#include <tgsi/tgsi_dump.h>
32#include "r600_screen.h"
33#include "r600_context.h"
34#include "r600d.h"
35
36static int r600_pipe_shader_vs(struct pipe_context *ctx, struct r600_pipe_shader *rpshader)
37{
38	struct r600_screen *rscreen = r600_screen(ctx->screen);
39	struct r600_shader *rshader = &rpshader->shader;
40	struct radeon_state *state;
41	unsigned i, tmp;
42
43	rpshader->state = radeon_state_decref(rpshader->state);
44	state = radeon_state(rscreen->rw, R600_VS_SHADER_TYPE, R600_VS_SHADER);
45	if (state == NULL)
46		return -ENOMEM;
47	for (i = 0; i < rshader->noutput; i += 4) {
48		tmp = rshader->output[i].sid;
49		tmp |= rshader->output[i + 1].sid << 8;
50		tmp |= rshader->output[i + 2].sid << 16;
51		tmp |= rshader->output[i + 3].sid << 24;
52		state->states[R600_VS_SHADER__SPI_VS_OUT_ID_0 + i / 4] = tmp;
53	}
54	state->states[R600_VS_SHADER__SPI_VS_OUT_CONFIG] = S_0286C4_VS_EXPORT_COUNT(rshader->noutput - 1);
55	state->states[R600_VS_SHADER__SQ_PGM_RESOURCES_VS] = S_028868_NUM_GPRS(rshader->ngpr);
56	rpshader->state = state;
57	rpshader->state->bo[0] = radeon_bo_incref(rscreen->rw, rpshader->bo);
58	rpshader->state->bo[1] = radeon_bo_incref(rscreen->rw, rpshader->bo);
59	rpshader->state->nbo = 2;
60	rpshader->state->placement[0] = RADEON_GEM_DOMAIN_GTT;
61	return radeon_state_pm4(state);
62}
63
64static int r600_pipe_shader_ps(struct pipe_context *ctx, struct r600_pipe_shader *rpshader)
65{
66	struct r600_screen *rscreen = r600_screen(ctx->screen);
67	struct r600_shader *rshader = &rpshader->shader;
68	struct radeon_state *state;
69	unsigned i, tmp;
70
71	rpshader->state = radeon_state_decref(rpshader->state);
72	state = radeon_state(rscreen->rw, R600_PS_SHADER_TYPE, R600_PS_SHADER);
73	if (state == NULL)
74		return -ENOMEM;
75	for (i = 0; i < rshader->ninput; i++) {
76		tmp = S_028644_SEMANTIC(rshader->input[i].sid);
77		tmp |= S_028644_SEL_CENTROID(1);
78		tmp |= S_028644_FLAT_SHADE(rshader->flat_shade);
79		state->states[R600_PS_SHADER__SPI_PS_INPUT_CNTL_0 + i] = tmp;
80	}
81	state->states[R600_PS_SHADER__SPI_PS_IN_CONTROL_0] = S_0286CC_NUM_INTERP(rshader->ninput) |
82							S_0286CC_PERSP_GRADIENT_ENA(1);
83	state->states[R600_PS_SHADER__SPI_PS_IN_CONTROL_1] = 0x00000000;
84	state->states[R600_PS_SHADER__SQ_PGM_RESOURCES_PS] = S_028868_NUM_GPRS(rshader->ngpr);
85	state->states[R600_PS_SHADER__SQ_PGM_EXPORTS_PS] = 0x00000002;
86	rpshader->state = state;
87	rpshader->state->bo[0] = radeon_bo_incref(rscreen->rw, rpshader->bo);
88	rpshader->state->nbo = 1;
89	rpshader->state->placement[0] = RADEON_GEM_DOMAIN_GTT;
90	return radeon_state_pm4(state);
91}
92
93static int r600_pipe_shader(struct pipe_context *ctx, struct r600_pipe_shader *rpshader)
94{
95	struct r600_screen *rscreen = r600_screen(ctx->screen);
96	struct r600_context *rctx = r600_context(ctx);
97	struct r600_shader *rshader = &rpshader->shader;
98	int r;
99
100	/* copy new shader */
101	radeon_bo_decref(rscreen->rw, rpshader->bo);
102	rpshader->bo = NULL;
103	rpshader->bo = radeon_bo(rscreen->rw, 0, rshader->ndw * 4,
104				4096, NULL);
105	if (rpshader->bo == NULL) {
106		return -ENOMEM;
107	}
108	radeon_bo_map(rscreen->rw, rpshader->bo);
109	memcpy(rpshader->bo->data, rshader->bcode, rshader->ndw * 4);
110	radeon_bo_unmap(rscreen->rw, rpshader->bo);
111	/* build state */
112	rshader->flat_shade = rctx->flat_shade;
113	switch (rpshader->type) {
114	case C_PROGRAM_TYPE_VS:
115		r = r600_pipe_shader_vs(ctx, rpshader);
116		break;
117	case C_PROGRAM_TYPE_FS:
118		r = r600_pipe_shader_ps(ctx, rpshader);
119		break;
120	default:
121		r = -EINVAL;
122		break;
123	}
124	return r;
125}
126
127struct r600_pipe_shader *r600_pipe_shader_create(struct pipe_context *ctx, unsigned type, const struct tgsi_token *tokens)
128{
129	struct r600_pipe_shader *rpshader = CALLOC_STRUCT(r600_pipe_shader);
130	struct r600_shader *rshader = &rpshader->shader;
131	int r;
132
133	if (rpshader == NULL)
134		return NULL;
135	rpshader->type = type;
136	LIST_INITHEAD(&rshader->nodes);
137	fprintf(stderr, "<<\n");
138	tgsi_dump(tokens, 0);
139	fprintf(stderr, "--------------------------------------------------------------\n");
140	r = c_shader_from_tgsi(&rshader->cshader, type, tokens);
141	if (r) {
142		r600_pipe_shader_destroy(ctx, rpshader);
143		fprintf(stderr, "ERROR(%s %d)>>\n\n", __func__, __LINE__);
144		return NULL;
145	}
146	r = r600_shader_insert_fetch(&rshader->cshader);
147	if (r) {
148		r600_pipe_shader_destroy(ctx, rpshader);
149		fprintf(stderr, "ERROR(%s %d)>>\n\n", __func__, __LINE__);
150		return NULL;
151	}
152	r = c_shader_build_dominator_tree(&rshader->cshader);
153	if (r) {
154		r600_pipe_shader_destroy(ctx, rpshader);
155		fprintf(stderr, "ERROR(%s %d)>>\n\n", __func__, __LINE__);
156		return NULL;
157	}
158	c_shader_dump(&rshader->cshader);
159	r = r600_cshader_legalize(&rshader->cshader);
160	if (r) {
161		r600_pipe_shader_destroy(ctx, rpshader);
162		fprintf(stderr, "ERROR(%s %d)>>\n\n", __func__, __LINE__);
163		return NULL;
164	}
165	r = r700_shader_translate(rshader);
166	if (r) {
167		r600_pipe_shader_destroy(ctx, rpshader);
168		fprintf(stderr, "ERROR(%s %d)>>\n\n", __func__, __LINE__);
169		return NULL;
170	}
171#if 1
172#if 0
173	fprintf(stderr, "--------------------------------------------------------------\n");
174	for (int i = 0; i < rshader->ndw; i++) {
175		fprintf(stderr, "0x%08X\n", rshader->bcode[i]);
176	}
177#endif
178	fprintf(stderr, ">>\n\n");
179#endif
180	return rpshader;
181}
182
183void r600_pipe_shader_destroy(struct pipe_context *ctx, struct r600_pipe_shader *rpshader)
184{
185	struct r600_screen *rscreen = r600_screen(ctx->screen);
186
187	if (rpshader == NULL)
188		return;
189	radeon_bo_decref(rscreen->rw, rpshader->bo);
190	rpshader->bo = NULL;
191	r600_shader_cleanup(&rpshader->shader);
192	FREE(rpshader);
193}
194
195int r600_pipe_shader_update(struct pipe_context *ctx, struct r600_pipe_shader *rpshader)
196{
197	struct r600_context *rctx = r600_context(ctx);
198	struct r600_shader *rshader;
199	enum pipe_format resource_format[160];
200	unsigned i, nresources = 0;
201	int r;
202
203	if (rpshader == NULL)
204		return -EINVAL;
205	rshader = &rpshader->shader;
206	switch (rpshader->type) {
207	case C_PROGRAM_TYPE_VS:
208		for (i = 0; i < rctx->vertex_elements->count; i++) {
209			resource_format[nresources++] = rctx->vertex_elements->elements[i].src_format;
210		}
211		break;
212	default:
213		break;
214	}
215	/* there should be enough input */
216	if (nresources < rshader->nresource)
217		return -EINVAL;
218	/* FIXME compare resources */
219	r = r600_shader_update(rshader, resource_format);
220	if (r)
221		return r;
222	return r600_pipe_shader(ctx, rpshader);
223}
224