1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright (C) 2014 Rob Clark <robclark@freedesktop.org> 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20bf215546Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21bf215546Sopenharmony_ci * SOFTWARE. 22bf215546Sopenharmony_ci * 23bf215546Sopenharmony_ci * Authors: 24bf215546Sopenharmony_ci * Rob Clark <robclark@freedesktop.org> 25bf215546Sopenharmony_ci */ 26bf215546Sopenharmony_ci 27bf215546Sopenharmony_ci#include "tgsi/tgsi_text.h" 28bf215546Sopenharmony_ci#include "tgsi/tgsi_ureg.h" 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_ci#include "util/u_simple_shaders.h" 31bf215546Sopenharmony_ci 32bf215546Sopenharmony_ci#include "freedreno_context.h" 33bf215546Sopenharmony_ci#include "freedreno_program.h" 34bf215546Sopenharmony_ci 35bf215546Sopenharmony_cistatic void 36bf215546Sopenharmony_ciupdate_bound_stage(struct fd_context *ctx, enum pipe_shader_type shader, 37bf215546Sopenharmony_ci bool bound) assert_dt 38bf215546Sopenharmony_ci{ 39bf215546Sopenharmony_ci if (bound) { 40bf215546Sopenharmony_ci ctx->bound_shader_stages |= BIT(shader); 41bf215546Sopenharmony_ci } else { 42bf215546Sopenharmony_ci ctx->bound_shader_stages &= ~BIT(shader); 43bf215546Sopenharmony_ci } 44bf215546Sopenharmony_ci} 45bf215546Sopenharmony_ci 46bf215546Sopenharmony_cistatic void 47bf215546Sopenharmony_cifd_set_patch_vertices(struct pipe_context *pctx, uint8_t patch_vertices) in_dt 48bf215546Sopenharmony_ci{ 49bf215546Sopenharmony_ci struct fd_context *ctx = fd_context(pctx); 50bf215546Sopenharmony_ci 51bf215546Sopenharmony_ci ctx->patch_vertices = patch_vertices; 52bf215546Sopenharmony_ci} 53bf215546Sopenharmony_ci 54bf215546Sopenharmony_cistatic void 55bf215546Sopenharmony_cifd_vs_state_bind(struct pipe_context *pctx, void *hwcso) in_dt 56bf215546Sopenharmony_ci{ 57bf215546Sopenharmony_ci struct fd_context *ctx = fd_context(pctx); 58bf215546Sopenharmony_ci ctx->prog.vs = hwcso; 59bf215546Sopenharmony_ci fd_context_dirty_shader(ctx, PIPE_SHADER_VERTEX, FD_DIRTY_SHADER_PROG); 60bf215546Sopenharmony_ci update_bound_stage(ctx, PIPE_SHADER_VERTEX, !!hwcso); 61bf215546Sopenharmony_ci} 62bf215546Sopenharmony_ci 63bf215546Sopenharmony_cistatic void 64bf215546Sopenharmony_cifd_tcs_state_bind(struct pipe_context *pctx, void *hwcso) in_dt 65bf215546Sopenharmony_ci{ 66bf215546Sopenharmony_ci struct fd_context *ctx = fd_context(pctx); 67bf215546Sopenharmony_ci ctx->prog.hs = hwcso; 68bf215546Sopenharmony_ci fd_context_dirty_shader(ctx, PIPE_SHADER_TESS_CTRL, FD_DIRTY_SHADER_PROG); 69bf215546Sopenharmony_ci update_bound_stage(ctx, PIPE_SHADER_TESS_CTRL, !!hwcso); 70bf215546Sopenharmony_ci} 71bf215546Sopenharmony_ci 72bf215546Sopenharmony_cistatic void 73bf215546Sopenharmony_cifd_tes_state_bind(struct pipe_context *pctx, void *hwcso) in_dt 74bf215546Sopenharmony_ci{ 75bf215546Sopenharmony_ci struct fd_context *ctx = fd_context(pctx); 76bf215546Sopenharmony_ci ctx->prog.ds = hwcso; 77bf215546Sopenharmony_ci fd_context_dirty_shader(ctx, PIPE_SHADER_TESS_EVAL, FD_DIRTY_SHADER_PROG); 78bf215546Sopenharmony_ci update_bound_stage(ctx, PIPE_SHADER_TESS_EVAL, !!hwcso); 79bf215546Sopenharmony_ci} 80bf215546Sopenharmony_ci 81bf215546Sopenharmony_cistatic void 82bf215546Sopenharmony_cifd_gs_state_bind(struct pipe_context *pctx, void *hwcso) in_dt 83bf215546Sopenharmony_ci{ 84bf215546Sopenharmony_ci struct fd_context *ctx = fd_context(pctx); 85bf215546Sopenharmony_ci ctx->prog.gs = hwcso; 86bf215546Sopenharmony_ci fd_context_dirty_shader(ctx, PIPE_SHADER_GEOMETRY, FD_DIRTY_SHADER_PROG); 87bf215546Sopenharmony_ci update_bound_stage(ctx, PIPE_SHADER_GEOMETRY, !!hwcso); 88bf215546Sopenharmony_ci} 89bf215546Sopenharmony_ci 90bf215546Sopenharmony_cistatic void 91bf215546Sopenharmony_cifd_fs_state_bind(struct pipe_context *pctx, void *hwcso) in_dt 92bf215546Sopenharmony_ci{ 93bf215546Sopenharmony_ci struct fd_context *ctx = fd_context(pctx); 94bf215546Sopenharmony_ci ctx->prog.fs = hwcso; 95bf215546Sopenharmony_ci fd_context_dirty_shader(ctx, PIPE_SHADER_FRAGMENT, FD_DIRTY_SHADER_PROG); 96bf215546Sopenharmony_ci update_bound_stage(ctx, PIPE_SHADER_FRAGMENT, !!hwcso); 97bf215546Sopenharmony_ci} 98bf215546Sopenharmony_ci 99bf215546Sopenharmony_cistatic const char *solid_fs = "FRAG \n" 100bf215546Sopenharmony_ci "PROPERTY FS_COLOR0_WRITES_ALL_CBUFS 1 \n" 101bf215546Sopenharmony_ci "DCL CONST[0] \n" 102bf215546Sopenharmony_ci "DCL OUT[0], COLOR \n" 103bf215546Sopenharmony_ci " 0: MOV OUT[0], CONST[0] \n" 104bf215546Sopenharmony_ci " 1: END \n"; 105bf215546Sopenharmony_ci 106bf215546Sopenharmony_cistatic const char *solid_vs = "VERT \n" 107bf215546Sopenharmony_ci "DCL IN[0] \n" 108bf215546Sopenharmony_ci "DCL OUT[0], POSITION \n" 109bf215546Sopenharmony_ci " 0: MOV OUT[0], IN[0] \n" 110bf215546Sopenharmony_ci " 1: END \n"; 111bf215546Sopenharmony_ci 112bf215546Sopenharmony_cistatic void * 113bf215546Sopenharmony_ciassemble_tgsi(struct pipe_context *pctx, const char *src, bool frag) 114bf215546Sopenharmony_ci{ 115bf215546Sopenharmony_ci struct tgsi_token toks[32]; 116bf215546Sopenharmony_ci struct pipe_shader_state cso = { 117bf215546Sopenharmony_ci .tokens = toks, 118bf215546Sopenharmony_ci }; 119bf215546Sopenharmony_ci 120bf215546Sopenharmony_ci bool ret = tgsi_text_translate(src, toks, ARRAY_SIZE(toks)); 121bf215546Sopenharmony_ci assume(ret); 122bf215546Sopenharmony_ci 123bf215546Sopenharmony_ci if (frag) 124bf215546Sopenharmony_ci return pctx->create_fs_state(pctx, &cso); 125bf215546Sopenharmony_ci else 126bf215546Sopenharmony_ci return pctx->create_vs_state(pctx, &cso); 127bf215546Sopenharmony_ci} 128bf215546Sopenharmony_ci 129bf215546Sopenharmony_ci/* the correct semantic to use for the texcoord varying depends on pipe-cap: */ 130bf215546Sopenharmony_cistatic enum tgsi_semantic 131bf215546Sopenharmony_citexcoord_semantic(struct pipe_context *pctx) 132bf215546Sopenharmony_ci{ 133bf215546Sopenharmony_ci struct pipe_screen *pscreen = pctx->screen; 134bf215546Sopenharmony_ci 135bf215546Sopenharmony_ci if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_TEXCOORD)) { 136bf215546Sopenharmony_ci return TGSI_SEMANTIC_TEXCOORD; 137bf215546Sopenharmony_ci } else { 138bf215546Sopenharmony_ci return TGSI_SEMANTIC_GENERIC; 139bf215546Sopenharmony_ci } 140bf215546Sopenharmony_ci} 141bf215546Sopenharmony_ci 142bf215546Sopenharmony_cistatic void * 143bf215546Sopenharmony_cifd_prog_blit_vs(struct pipe_context *pctx) 144bf215546Sopenharmony_ci{ 145bf215546Sopenharmony_ci struct ureg_program *ureg; 146bf215546Sopenharmony_ci 147bf215546Sopenharmony_ci ureg = ureg_create(PIPE_SHADER_VERTEX); 148bf215546Sopenharmony_ci if (!ureg) 149bf215546Sopenharmony_ci return NULL; 150bf215546Sopenharmony_ci 151bf215546Sopenharmony_ci struct ureg_src in0 = ureg_DECL_vs_input(ureg, 0); 152bf215546Sopenharmony_ci struct ureg_src in1 = ureg_DECL_vs_input(ureg, 1); 153bf215546Sopenharmony_ci 154bf215546Sopenharmony_ci struct ureg_dst out0 = ureg_DECL_output(ureg, texcoord_semantic(pctx), 0); 155bf215546Sopenharmony_ci struct ureg_dst out1 = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 1); 156bf215546Sopenharmony_ci 157bf215546Sopenharmony_ci ureg_MOV(ureg, out0, in0); 158bf215546Sopenharmony_ci ureg_MOV(ureg, out1, in1); 159bf215546Sopenharmony_ci 160bf215546Sopenharmony_ci ureg_END(ureg); 161bf215546Sopenharmony_ci 162bf215546Sopenharmony_ci return ureg_create_shader_and_destroy(ureg, pctx); 163bf215546Sopenharmony_ci} 164bf215546Sopenharmony_ci 165bf215546Sopenharmony_cistatic void * 166bf215546Sopenharmony_cifd_prog_blit_fs(struct pipe_context *pctx, int rts, bool depth) 167bf215546Sopenharmony_ci{ 168bf215546Sopenharmony_ci int i; 169bf215546Sopenharmony_ci struct ureg_src tc; 170bf215546Sopenharmony_ci struct ureg_program *ureg; 171bf215546Sopenharmony_ci 172bf215546Sopenharmony_ci assert(rts <= MAX_RENDER_TARGETS); 173bf215546Sopenharmony_ci 174bf215546Sopenharmony_ci ureg = ureg_create(PIPE_SHADER_FRAGMENT); 175bf215546Sopenharmony_ci if (!ureg) 176bf215546Sopenharmony_ci return NULL; 177bf215546Sopenharmony_ci 178bf215546Sopenharmony_ci tc = ureg_DECL_fs_input(ureg, texcoord_semantic(pctx), 0, 179bf215546Sopenharmony_ci TGSI_INTERPOLATE_PERSPECTIVE); 180bf215546Sopenharmony_ci for (i = 0; i < rts; i++) 181bf215546Sopenharmony_ci ureg_TEX(ureg, ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, i), 182bf215546Sopenharmony_ci TGSI_TEXTURE_2D, tc, ureg_DECL_sampler(ureg, i)); 183bf215546Sopenharmony_ci if (depth) 184bf215546Sopenharmony_ci ureg_TEX(ureg, 185bf215546Sopenharmony_ci ureg_writemask(ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0), 186bf215546Sopenharmony_ci TGSI_WRITEMASK_Z), 187bf215546Sopenharmony_ci TGSI_TEXTURE_2D, tc, ureg_DECL_sampler(ureg, rts)); 188bf215546Sopenharmony_ci 189bf215546Sopenharmony_ci ureg_END(ureg); 190bf215546Sopenharmony_ci 191bf215546Sopenharmony_ci return ureg_create_shader_and_destroy(ureg, pctx); 192bf215546Sopenharmony_ci} 193bf215546Sopenharmony_ci 194bf215546Sopenharmony_civoid 195bf215546Sopenharmony_cifd_prog_init(struct pipe_context *pctx) 196bf215546Sopenharmony_ci{ 197bf215546Sopenharmony_ci struct fd_context *ctx = fd_context(pctx); 198bf215546Sopenharmony_ci int i; 199bf215546Sopenharmony_ci 200bf215546Sopenharmony_ci pctx->bind_vs_state = fd_vs_state_bind; 201bf215546Sopenharmony_ci pctx->bind_tcs_state = fd_tcs_state_bind; 202bf215546Sopenharmony_ci pctx->bind_tes_state = fd_tes_state_bind; 203bf215546Sopenharmony_ci pctx->bind_gs_state = fd_gs_state_bind; 204bf215546Sopenharmony_ci pctx->bind_fs_state = fd_fs_state_bind; 205bf215546Sopenharmony_ci pctx->set_patch_vertices = fd_set_patch_vertices; 206bf215546Sopenharmony_ci 207bf215546Sopenharmony_ci if (ctx->flags & PIPE_CONTEXT_COMPUTE_ONLY) 208bf215546Sopenharmony_ci return; 209bf215546Sopenharmony_ci 210bf215546Sopenharmony_ci ctx->solid_prog.fs = assemble_tgsi(pctx, solid_fs, true); 211bf215546Sopenharmony_ci ctx->solid_prog.vs = assemble_tgsi(pctx, solid_vs, false); 212bf215546Sopenharmony_ci 213bf215546Sopenharmony_ci if (ctx->screen->gen >= 6) { 214bf215546Sopenharmony_ci ctx->solid_layered_prog.fs = assemble_tgsi(pctx, solid_fs, true); 215bf215546Sopenharmony_ci ctx->solid_layered_prog.vs = util_make_layered_clear_vertex_shader(pctx); 216bf215546Sopenharmony_ci } 217bf215546Sopenharmony_ci 218bf215546Sopenharmony_ci if (ctx->screen->gen >= 5) 219bf215546Sopenharmony_ci return; 220bf215546Sopenharmony_ci 221bf215546Sopenharmony_ci ctx->blit_prog[0].vs = fd_prog_blit_vs(pctx); 222bf215546Sopenharmony_ci ctx->blit_prog[0].fs = fd_prog_blit_fs(pctx, 1, false); 223bf215546Sopenharmony_ci 224bf215546Sopenharmony_ci if (ctx->screen->gen < 3) 225bf215546Sopenharmony_ci return; 226bf215546Sopenharmony_ci 227bf215546Sopenharmony_ci for (i = 1; i < ctx->screen->max_rts; i++) { 228bf215546Sopenharmony_ci ctx->blit_prog[i].vs = ctx->blit_prog[0].vs; 229bf215546Sopenharmony_ci ctx->blit_prog[i].fs = fd_prog_blit_fs(pctx, i + 1, false); 230bf215546Sopenharmony_ci } 231bf215546Sopenharmony_ci 232bf215546Sopenharmony_ci ctx->blit_z.vs = ctx->blit_prog[0].vs; 233bf215546Sopenharmony_ci ctx->blit_z.fs = fd_prog_blit_fs(pctx, 0, true); 234bf215546Sopenharmony_ci ctx->blit_zs.vs = ctx->blit_prog[0].vs; 235bf215546Sopenharmony_ci ctx->blit_zs.fs = fd_prog_blit_fs(pctx, 1, true); 236bf215546Sopenharmony_ci} 237bf215546Sopenharmony_ci 238bf215546Sopenharmony_civoid 239bf215546Sopenharmony_cifd_prog_fini(struct pipe_context *pctx) 240bf215546Sopenharmony_ci{ 241bf215546Sopenharmony_ci struct fd_context *ctx = fd_context(pctx); 242bf215546Sopenharmony_ci int i; 243bf215546Sopenharmony_ci 244bf215546Sopenharmony_ci if (ctx->flags & PIPE_CONTEXT_COMPUTE_ONLY) 245bf215546Sopenharmony_ci return; 246bf215546Sopenharmony_ci 247bf215546Sopenharmony_ci pctx->delete_vs_state(pctx, ctx->solid_prog.vs); 248bf215546Sopenharmony_ci pctx->delete_fs_state(pctx, ctx->solid_prog.fs); 249bf215546Sopenharmony_ci 250bf215546Sopenharmony_ci if (ctx->screen->gen >= 6) { 251bf215546Sopenharmony_ci pctx->delete_vs_state(pctx, ctx->solid_layered_prog.vs); 252bf215546Sopenharmony_ci pctx->delete_fs_state(pctx, ctx->solid_layered_prog.fs); 253bf215546Sopenharmony_ci } 254bf215546Sopenharmony_ci 255bf215546Sopenharmony_ci if (ctx->screen->gen >= 5) 256bf215546Sopenharmony_ci return; 257bf215546Sopenharmony_ci 258bf215546Sopenharmony_ci pctx->delete_vs_state(pctx, ctx->blit_prog[0].vs); 259bf215546Sopenharmony_ci pctx->delete_fs_state(pctx, ctx->blit_prog[0].fs); 260bf215546Sopenharmony_ci 261bf215546Sopenharmony_ci if (ctx->screen->gen < 3) 262bf215546Sopenharmony_ci return; 263bf215546Sopenharmony_ci 264bf215546Sopenharmony_ci for (i = 1; i < ctx->screen->max_rts; i++) 265bf215546Sopenharmony_ci pctx->delete_fs_state(pctx, ctx->blit_prog[i].fs); 266bf215546Sopenharmony_ci pctx->delete_fs_state(pctx, ctx->blit_z.fs); 267bf215546Sopenharmony_ci pctx->delete_fs_state(pctx, ctx->blit_zs.fs); 268bf215546Sopenharmony_ci} 269