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 35static void 36update_bound_stage(struct fd_context *ctx, enum pipe_shader_type shader, 37 bool bound) assert_dt 38{ 39 if (bound) { 40 ctx->bound_shader_stages |= BIT(shader); 41 } else { 42 ctx->bound_shader_stages &= ~BIT(shader); 43 } 44} 45 46static void 47fd_set_patch_vertices(struct pipe_context *pctx, uint8_t patch_vertices) in_dt 48{ 49 struct fd_context *ctx = fd_context(pctx); 50 51 ctx->patch_vertices = patch_vertices; 52} 53 54static void 55fd_vs_state_bind(struct pipe_context *pctx, void *hwcso) in_dt 56{ 57 struct fd_context *ctx = fd_context(pctx); 58 ctx->prog.vs = hwcso; 59 fd_context_dirty_shader(ctx, PIPE_SHADER_VERTEX, FD_DIRTY_SHADER_PROG); 60 update_bound_stage(ctx, PIPE_SHADER_VERTEX, !!hwcso); 61} 62 63static void 64fd_tcs_state_bind(struct pipe_context *pctx, void *hwcso) in_dt 65{ 66 struct fd_context *ctx = fd_context(pctx); 67 ctx->prog.hs = hwcso; 68 fd_context_dirty_shader(ctx, PIPE_SHADER_TESS_CTRL, FD_DIRTY_SHADER_PROG); 69 update_bound_stage(ctx, PIPE_SHADER_TESS_CTRL, !!hwcso); 70} 71 72static void 73fd_tes_state_bind(struct pipe_context *pctx, void *hwcso) in_dt 74{ 75 struct fd_context *ctx = fd_context(pctx); 76 ctx->prog.ds = hwcso; 77 fd_context_dirty_shader(ctx, PIPE_SHADER_TESS_EVAL, FD_DIRTY_SHADER_PROG); 78 update_bound_stage(ctx, PIPE_SHADER_TESS_EVAL, !!hwcso); 79} 80 81static void 82fd_gs_state_bind(struct pipe_context *pctx, void *hwcso) in_dt 83{ 84 struct fd_context *ctx = fd_context(pctx); 85 ctx->prog.gs = hwcso; 86 fd_context_dirty_shader(ctx, PIPE_SHADER_GEOMETRY, FD_DIRTY_SHADER_PROG); 87 update_bound_stage(ctx, PIPE_SHADER_GEOMETRY, !!hwcso); 88} 89 90static void 91fd_fs_state_bind(struct pipe_context *pctx, void *hwcso) in_dt 92{ 93 struct fd_context *ctx = fd_context(pctx); 94 ctx->prog.fs = hwcso; 95 fd_context_dirty_shader(ctx, PIPE_SHADER_FRAGMENT, FD_DIRTY_SHADER_PROG); 96 update_bound_stage(ctx, PIPE_SHADER_FRAGMENT, !!hwcso); 97} 98 99static const char *solid_fs = "FRAG \n" 100 "PROPERTY FS_COLOR0_WRITES_ALL_CBUFS 1 \n" 101 "DCL CONST[0] \n" 102 "DCL OUT[0], COLOR \n" 103 " 0: MOV OUT[0], CONST[0] \n" 104 " 1: END \n"; 105 106static const char *solid_vs = "VERT \n" 107 "DCL IN[0] \n" 108 "DCL OUT[0], POSITION \n" 109 " 0: MOV OUT[0], IN[0] \n" 110 " 1: END \n"; 111 112static void * 113assemble_tgsi(struct pipe_context *pctx, const char *src, bool frag) 114{ 115 struct tgsi_token toks[32]; 116 struct pipe_shader_state cso = { 117 .tokens = toks, 118 }; 119 120 bool ret = tgsi_text_translate(src, toks, ARRAY_SIZE(toks)); 121 assume(ret); 122 123 if (frag) 124 return pctx->create_fs_state(pctx, &cso); 125 else 126 return pctx->create_vs_state(pctx, &cso); 127} 128 129/* the correct semantic to use for the texcoord varying depends on pipe-cap: */ 130static enum tgsi_semantic 131texcoord_semantic(struct pipe_context *pctx) 132{ 133 struct pipe_screen *pscreen = pctx->screen; 134 135 if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_TEXCOORD)) { 136 return TGSI_SEMANTIC_TEXCOORD; 137 } else { 138 return TGSI_SEMANTIC_GENERIC; 139 } 140} 141 142static void * 143fd_prog_blit_vs(struct pipe_context *pctx) 144{ 145 struct ureg_program *ureg; 146 147 ureg = ureg_create(PIPE_SHADER_VERTEX); 148 if (!ureg) 149 return NULL; 150 151 struct ureg_src in0 = ureg_DECL_vs_input(ureg, 0); 152 struct ureg_src in1 = ureg_DECL_vs_input(ureg, 1); 153 154 struct ureg_dst out0 = ureg_DECL_output(ureg, texcoord_semantic(pctx), 0); 155 struct ureg_dst out1 = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 1); 156 157 ureg_MOV(ureg, out0, in0); 158 ureg_MOV(ureg, out1, in1); 159 160 ureg_END(ureg); 161 162 return ureg_create_shader_and_destroy(ureg, pctx); 163} 164 165static void * 166fd_prog_blit_fs(struct pipe_context *pctx, int rts, bool depth) 167{ 168 int i; 169 struct ureg_src tc; 170 struct ureg_program *ureg; 171 172 assert(rts <= MAX_RENDER_TARGETS); 173 174 ureg = ureg_create(PIPE_SHADER_FRAGMENT); 175 if (!ureg) 176 return NULL; 177 178 tc = ureg_DECL_fs_input(ureg, texcoord_semantic(pctx), 0, 179 TGSI_INTERPOLATE_PERSPECTIVE); 180 for (i = 0; i < rts; i++) 181 ureg_TEX(ureg, ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, i), 182 TGSI_TEXTURE_2D, tc, ureg_DECL_sampler(ureg, i)); 183 if (depth) 184 ureg_TEX(ureg, 185 ureg_writemask(ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0), 186 TGSI_WRITEMASK_Z), 187 TGSI_TEXTURE_2D, tc, ureg_DECL_sampler(ureg, rts)); 188 189 ureg_END(ureg); 190 191 return ureg_create_shader_and_destroy(ureg, pctx); 192} 193 194void 195fd_prog_init(struct pipe_context *pctx) 196{ 197 struct fd_context *ctx = fd_context(pctx); 198 int i; 199 200 pctx->bind_vs_state = fd_vs_state_bind; 201 pctx->bind_tcs_state = fd_tcs_state_bind; 202 pctx->bind_tes_state = fd_tes_state_bind; 203 pctx->bind_gs_state = fd_gs_state_bind; 204 pctx->bind_fs_state = fd_fs_state_bind; 205 pctx->set_patch_vertices = fd_set_patch_vertices; 206 207 if (ctx->flags & PIPE_CONTEXT_COMPUTE_ONLY) 208 return; 209 210 ctx->solid_prog.fs = assemble_tgsi(pctx, solid_fs, true); 211 ctx->solid_prog.vs = assemble_tgsi(pctx, solid_vs, false); 212 213 if (ctx->screen->gen >= 6) { 214 ctx->solid_layered_prog.fs = assemble_tgsi(pctx, solid_fs, true); 215 ctx->solid_layered_prog.vs = util_make_layered_clear_vertex_shader(pctx); 216 } 217 218 if (ctx->screen->gen >= 5) 219 return; 220 221 ctx->blit_prog[0].vs = fd_prog_blit_vs(pctx); 222 ctx->blit_prog[0].fs = fd_prog_blit_fs(pctx, 1, false); 223 224 if (ctx->screen->gen < 3) 225 return; 226 227 for (i = 1; i < ctx->screen->max_rts; i++) { 228 ctx->blit_prog[i].vs = ctx->blit_prog[0].vs; 229 ctx->blit_prog[i].fs = fd_prog_blit_fs(pctx, i + 1, false); 230 } 231 232 ctx->blit_z.vs = ctx->blit_prog[0].vs; 233 ctx->blit_z.fs = fd_prog_blit_fs(pctx, 0, true); 234 ctx->blit_zs.vs = ctx->blit_prog[0].vs; 235 ctx->blit_zs.fs = fd_prog_blit_fs(pctx, 1, true); 236} 237 238void 239fd_prog_fini(struct pipe_context *pctx) 240{ 241 struct fd_context *ctx = fd_context(pctx); 242 int i; 243 244 if (ctx->flags & PIPE_CONTEXT_COMPUTE_ONLY) 245 return; 246 247 pctx->delete_vs_state(pctx, ctx->solid_prog.vs); 248 pctx->delete_fs_state(pctx, ctx->solid_prog.fs); 249 250 if (ctx->screen->gen >= 6) { 251 pctx->delete_vs_state(pctx, ctx->solid_layered_prog.vs); 252 pctx->delete_fs_state(pctx, ctx->solid_layered_prog.fs); 253 } 254 255 if (ctx->screen->gen >= 5) 256 return; 257 258 pctx->delete_vs_state(pctx, ctx->blit_prog[0].vs); 259 pctx->delete_fs_state(pctx, ctx->blit_prog[0].fs); 260 261 if (ctx->screen->gen < 3) 262 return; 263 264 for (i = 1; i < ctx->screen->max_rts; i++) 265 pctx->delete_fs_state(pctx, ctx->blit_prog[i].fs); 266 pctx->delete_fs_state(pctx, ctx->blit_z.fs); 267 pctx->delete_fs_state(pctx, ctx->blit_zs.fs); 268} 269