• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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