1 /*
2 * Copyright (C) 2014 Rob Clark <robclark@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 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * 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 NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 *
23 * Authors:
24 * Rob Clark <robclark@freedesktop.org>
25 */
26
27 #include "tgsi/tgsi_text.h"
28 #include "tgsi/tgsi_ureg.h"
29
30 #include "util/u_simple_shaders.h"
31
32 #include "freedreno_context.h"
33 #include "freedreno_program.h"
34
35 static void
update_bound_stage(struct fd_context * ctx,enum pipe_shader_type shader,bool bound)36 update_bound_stage(struct fd_context *ctx, enum pipe_shader_type shader,
37 bool bound) assert_dt
38 {
39 uint32_t bound_shader_stages = ctx->bound_shader_stages;
40 if (bound) {
41 ctx->bound_shader_stages |= BIT(shader);
42 } else {
43 ctx->bound_shader_stages &= ~BIT(shader);
44 }
45 if (ctx->update_draw && (bound_shader_stages != ctx->bound_shader_stages))
46 ctx->update_draw(ctx);
47 }
48
49 static void
fd_set_tess_state(struct pipe_context * pctx,const float default_outer_level[4],const float default_inner_level[2])50 fd_set_tess_state(struct pipe_context *pctx,
51 const float default_outer_level[4],
52 const float default_inner_level[2])
53 in_dt
54 {
55 struct fd_context *ctx = fd_context(pctx);
56
57 /* These turn into driver-params where are emitted on every draw if
58 * needed by the shader (they will only be needed by pass-through
59 * TCS shader)
60 */
61 memcpy(ctx->default_outer_level,
62 default_outer_level,
63 sizeof(ctx->default_outer_level));
64
65 memcpy(ctx->default_inner_level,
66 default_inner_level,
67 sizeof(ctx->default_inner_level));
68 }
69
70 static void
fd_set_patch_vertices(struct pipe_context * pctx,uint8_t patch_vertices)71 fd_set_patch_vertices(struct pipe_context *pctx, uint8_t patch_vertices) in_dt
72 {
73 struct fd_context *ctx = fd_context(pctx);
74
75 if (ctx->patch_vertices == patch_vertices)
76 return;
77
78 ctx->patch_vertices = patch_vertices;
79
80 /* If we have tessellation this dirties the TCS state. Check for TES
81 * stage as TCS could be NULL (passthrough)
82 */
83 if (ctx->prog.ds || ctx->prog.hs) {
84 fd_context_dirty_shader(ctx, PIPE_SHADER_TESS_CTRL, FD_DIRTY_SHADER_PROG);
85 }
86 }
87
88 static void
fd_vs_state_bind(struct pipe_context * pctx,void * hwcso)89 fd_vs_state_bind(struct pipe_context *pctx, void *hwcso) in_dt
90 {
91 struct fd_context *ctx = fd_context(pctx);
92 ctx->prog.vs = hwcso;
93 fd_context_dirty_shader(ctx, PIPE_SHADER_VERTEX, FD_DIRTY_SHADER_PROG);
94 update_bound_stage(ctx, PIPE_SHADER_VERTEX, !!hwcso);
95 }
96
97 static void
fd_tcs_state_bind(struct pipe_context * pctx,void * hwcso)98 fd_tcs_state_bind(struct pipe_context *pctx, void *hwcso) in_dt
99 {
100 struct fd_context *ctx = fd_context(pctx);
101 ctx->prog.hs = hwcso;
102 fd_context_dirty_shader(ctx, PIPE_SHADER_TESS_CTRL, FD_DIRTY_SHADER_PROG);
103 update_bound_stage(ctx, PIPE_SHADER_TESS_CTRL, !!hwcso);
104 }
105
106 static void
fd_tes_state_bind(struct pipe_context * pctx,void * hwcso)107 fd_tes_state_bind(struct pipe_context *pctx, void *hwcso) in_dt
108 {
109 struct fd_context *ctx = fd_context(pctx);
110 ctx->prog.ds = hwcso;
111 fd_context_dirty_shader(ctx, PIPE_SHADER_TESS_EVAL, FD_DIRTY_SHADER_PROG);
112 update_bound_stage(ctx, PIPE_SHADER_TESS_EVAL, !!hwcso);
113 }
114
115 static void
fd_gs_state_bind(struct pipe_context * pctx,void * hwcso)116 fd_gs_state_bind(struct pipe_context *pctx, void *hwcso) in_dt
117 {
118 struct fd_context *ctx = fd_context(pctx);
119 ctx->prog.gs = hwcso;
120 fd_context_dirty_shader(ctx, PIPE_SHADER_GEOMETRY, FD_DIRTY_SHADER_PROG);
121 update_bound_stage(ctx, PIPE_SHADER_GEOMETRY, !!hwcso);
122 }
123
124 static void
fd_fs_state_bind(struct pipe_context * pctx,void * hwcso)125 fd_fs_state_bind(struct pipe_context *pctx, void *hwcso) in_dt
126 {
127 struct fd_context *ctx = fd_context(pctx);
128 ctx->prog.fs = hwcso;
129 fd_context_dirty_shader(ctx, PIPE_SHADER_FRAGMENT, FD_DIRTY_SHADER_PROG);
130 update_bound_stage(ctx, PIPE_SHADER_FRAGMENT, !!hwcso);
131 }
132
133 static const char *solid_fs = "FRAG \n"
134 "PROPERTY FS_COLOR0_WRITES_ALL_CBUFS 1 \n"
135 "DCL CONST[0] \n"
136 "DCL OUT[0], COLOR \n"
137 " 0: MOV OUT[0], CONST[0] \n"
138 " 1: END \n";
139
140 static const char *solid_vs = "VERT \n"
141 "DCL IN[0] \n"
142 "DCL OUT[0], POSITION \n"
143 " 0: MOV OUT[0], IN[0] \n"
144 " 1: END \n";
145
146 static void *
assemble_tgsi(struct pipe_context * pctx,const char * src,bool frag)147 assemble_tgsi(struct pipe_context *pctx, const char *src, bool frag)
148 {
149 struct tgsi_token toks[32];
150 struct pipe_shader_state cso = {
151 .tokens = toks,
152 };
153
154 bool ret = tgsi_text_translate(src, toks, ARRAY_SIZE(toks));
155 assume(ret);
156
157 if (frag)
158 return pctx->create_fs_state(pctx, &cso);
159 else
160 return pctx->create_vs_state(pctx, &cso);
161 }
162
163 /* the correct semantic to use for the texcoord varying depends on pipe-cap: */
164 static enum tgsi_semantic
texcoord_semantic(struct pipe_context * pctx)165 texcoord_semantic(struct pipe_context *pctx)
166 {
167 struct pipe_screen *pscreen = pctx->screen;
168
169 if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_TEXCOORD)) {
170 return TGSI_SEMANTIC_TEXCOORD;
171 } else {
172 return TGSI_SEMANTIC_GENERIC;
173 }
174 }
175
176 static void *
fd_prog_blit_vs(struct pipe_context * pctx)177 fd_prog_blit_vs(struct pipe_context *pctx)
178 {
179 struct ureg_program *ureg;
180
181 ureg = ureg_create(PIPE_SHADER_VERTEX);
182 if (!ureg)
183 return NULL;
184
185 struct ureg_src in0 = ureg_DECL_vs_input(ureg, 0);
186 struct ureg_src in1 = ureg_DECL_vs_input(ureg, 1);
187
188 struct ureg_dst out0 = ureg_DECL_output(ureg, texcoord_semantic(pctx), 0);
189 struct ureg_dst out1 = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 1);
190
191 ureg_MOV(ureg, out0, in0);
192 ureg_MOV(ureg, out1, in1);
193
194 ureg_END(ureg);
195
196 return ureg_create_shader_and_destroy(ureg, pctx);
197 }
198
199 static void *
fd_prog_blit_fs(struct pipe_context * pctx,int rts,bool depth)200 fd_prog_blit_fs(struct pipe_context *pctx, int rts, bool depth)
201 {
202 int i;
203 struct ureg_src tc;
204 struct ureg_program *ureg;
205
206 assert(rts <= MAX_RENDER_TARGETS);
207
208 ureg = ureg_create(PIPE_SHADER_FRAGMENT);
209 if (!ureg)
210 return NULL;
211
212 tc = ureg_DECL_fs_input(ureg, texcoord_semantic(pctx), 0,
213 TGSI_INTERPOLATE_PERSPECTIVE);
214 for (i = 0; i < rts; i++)
215 ureg_TEX(ureg, ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, i),
216 TGSI_TEXTURE_2D, tc, ureg_DECL_sampler(ureg, i));
217 if (depth)
218 ureg_TEX(ureg,
219 ureg_writemask(ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0),
220 TGSI_WRITEMASK_Z),
221 TGSI_TEXTURE_2D, tc, ureg_DECL_sampler(ureg, rts));
222
223 ureg_END(ureg);
224
225 return ureg_create_shader_and_destroy(ureg, pctx);
226 }
227
228 void
fd_prog_init(struct pipe_context * pctx)229 fd_prog_init(struct pipe_context *pctx)
230 {
231 struct fd_context *ctx = fd_context(pctx);
232 int i;
233
234 pctx->bind_vs_state = fd_vs_state_bind;
235 pctx->bind_tcs_state = fd_tcs_state_bind;
236 pctx->bind_tes_state = fd_tes_state_bind;
237 pctx->bind_gs_state = fd_gs_state_bind;
238 pctx->bind_fs_state = fd_fs_state_bind;
239 pctx->set_tess_state = fd_set_tess_state;
240 pctx->set_patch_vertices = fd_set_patch_vertices;
241
242 if (ctx->flags & PIPE_CONTEXT_COMPUTE_ONLY)
243 return;
244
245 ctx->solid_prog.fs = assemble_tgsi(pctx, solid_fs, true);
246 ctx->solid_prog.vs = assemble_tgsi(pctx, solid_vs, false);
247
248 if (ctx->screen->gen >= 6) {
249 ctx->solid_layered_prog.fs = assemble_tgsi(pctx, solid_fs, true);
250 ctx->solid_layered_prog.vs = util_make_layered_clear_vertex_shader(pctx);
251 }
252
253 if (ctx->screen->gen >= 5)
254 return;
255
256 ctx->blit_prog[0].vs = fd_prog_blit_vs(pctx);
257 ctx->blit_prog[0].fs = fd_prog_blit_fs(pctx, 1, false);
258
259 if (ctx->screen->gen < 3)
260 return;
261
262 for (i = 1; i < ctx->screen->max_rts; i++) {
263 ctx->blit_prog[i].vs = ctx->blit_prog[0].vs;
264 ctx->blit_prog[i].fs = fd_prog_blit_fs(pctx, i + 1, false);
265 }
266
267 ctx->blit_z.vs = ctx->blit_prog[0].vs;
268 ctx->blit_z.fs = fd_prog_blit_fs(pctx, 0, true);
269 ctx->blit_zs.vs = ctx->blit_prog[0].vs;
270 ctx->blit_zs.fs = fd_prog_blit_fs(pctx, 1, true);
271 }
272
273 void
fd_prog_fini(struct pipe_context * pctx)274 fd_prog_fini(struct pipe_context *pctx)
275 {
276 struct fd_context *ctx = fd_context(pctx);
277 int i;
278
279 if (ctx->flags & PIPE_CONTEXT_COMPUTE_ONLY)
280 return;
281
282 pctx->delete_vs_state(pctx, ctx->solid_prog.vs);
283 pctx->delete_fs_state(pctx, ctx->solid_prog.fs);
284
285 if (ctx->screen->gen >= 6) {
286 pctx->delete_vs_state(pctx, ctx->solid_layered_prog.vs);
287 pctx->delete_fs_state(pctx, ctx->solid_layered_prog.fs);
288 }
289
290 if (ctx->screen->gen >= 5)
291 return;
292
293 pctx->delete_vs_state(pctx, ctx->blit_prog[0].vs);
294 pctx->delete_fs_state(pctx, ctx->blit_prog[0].fs);
295
296 if (ctx->screen->gen < 3)
297 return;
298
299 for (i = 1; i < ctx->screen->max_rts; i++)
300 pctx->delete_fs_state(pctx, ctx->blit_prog[i].fs);
301 pctx->delete_fs_state(pctx, ctx->blit_z.fs);
302 pctx->delete_fs_state(pctx, ctx->blit_zs.fs);
303 }
304