1af69d88dSmrg/* 2af69d88dSmrg * Copyright (C) 2014 Rob Clark <robclark@freedesktop.org> 3af69d88dSmrg * 4af69d88dSmrg * Permission is hereby granted, free of charge, to any person obtaining a 5af69d88dSmrg * copy of this software and associated documentation files (the "Software"), 6af69d88dSmrg * to deal in the Software without restriction, including without limitation 7af69d88dSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8af69d88dSmrg * and/or sell copies of the Software, and to permit persons to whom the 9af69d88dSmrg * Software is furnished to do so, subject to the following conditions: 10af69d88dSmrg * 11af69d88dSmrg * The above copyright notice and this permission notice (including the next 12af69d88dSmrg * paragraph) shall be included in all copies or substantial portions of the 13af69d88dSmrg * Software. 14af69d88dSmrg * 15af69d88dSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16af69d88dSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17af69d88dSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18af69d88dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19af69d88dSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20af69d88dSmrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21af69d88dSmrg * SOFTWARE. 22af69d88dSmrg * 23af69d88dSmrg * Authors: 24af69d88dSmrg * Rob Clark <robclark@freedesktop.org> 25af69d88dSmrg */ 26af69d88dSmrg 27af69d88dSmrg#include "tgsi/tgsi_text.h" 2801e04c3fSmrg#include "tgsi/tgsi_ureg.h" 29af69d88dSmrg 307ec681f3Smrg#include "util/u_simple_shaders.h" 317ec681f3Smrg 32af69d88dSmrg#include "freedreno_context.h" 337ec681f3Smrg#include "freedreno_program.h" 347ec681f3Smrg 357ec681f3Smrgstatic void 367ec681f3Smrgupdate_bound_stage(struct fd_context *ctx, enum pipe_shader_type shader, 377ec681f3Smrg bool bound) assert_dt 387ec681f3Smrg{ 397ec681f3Smrg if (bound) { 407ec681f3Smrg ctx->bound_shader_stages |= BIT(shader); 417ec681f3Smrg } else { 427ec681f3Smrg ctx->bound_shader_stages &= ~BIT(shader); 437ec681f3Smrg } 447ec681f3Smrg} 457ec681f3Smrg 467ec681f3Smrgstatic void 477ec681f3Smrgfd_set_patch_vertices(struct pipe_context *pctx, uint8_t patch_vertices) in_dt 487ec681f3Smrg{ 497ec681f3Smrg struct fd_context *ctx = fd_context(pctx); 507ec681f3Smrg 517ec681f3Smrg ctx->patch_vertices = patch_vertices; 527ec681f3Smrg} 537ec681f3Smrg 547ec681f3Smrgstatic void 557ec681f3Smrgfd_vs_state_bind(struct pipe_context *pctx, void *hwcso) in_dt 567ec681f3Smrg{ 577ec681f3Smrg struct fd_context *ctx = fd_context(pctx); 587ec681f3Smrg ctx->prog.vs = hwcso; 597ec681f3Smrg fd_context_dirty_shader(ctx, PIPE_SHADER_VERTEX, FD_DIRTY_SHADER_PROG); 607ec681f3Smrg update_bound_stage(ctx, PIPE_SHADER_VERTEX, !!hwcso); 617ec681f3Smrg} 627ec681f3Smrg 637ec681f3Smrgstatic void 647ec681f3Smrgfd_tcs_state_bind(struct pipe_context *pctx, void *hwcso) in_dt 657ec681f3Smrg{ 667ec681f3Smrg struct fd_context *ctx = fd_context(pctx); 677ec681f3Smrg ctx->prog.hs = hwcso; 687ec681f3Smrg fd_context_dirty_shader(ctx, PIPE_SHADER_TESS_CTRL, FD_DIRTY_SHADER_PROG); 697ec681f3Smrg update_bound_stage(ctx, PIPE_SHADER_TESS_CTRL, !!hwcso); 707ec681f3Smrg} 717ec681f3Smrg 727ec681f3Smrgstatic void 737ec681f3Smrgfd_tes_state_bind(struct pipe_context *pctx, void *hwcso) in_dt 747ec681f3Smrg{ 757ec681f3Smrg struct fd_context *ctx = fd_context(pctx); 767ec681f3Smrg ctx->prog.ds = hwcso; 777ec681f3Smrg fd_context_dirty_shader(ctx, PIPE_SHADER_TESS_EVAL, FD_DIRTY_SHADER_PROG); 787ec681f3Smrg update_bound_stage(ctx, PIPE_SHADER_TESS_EVAL, !!hwcso); 797ec681f3Smrg} 80af69d88dSmrg 81af69d88dSmrgstatic void 827ec681f3Smrgfd_gs_state_bind(struct pipe_context *pctx, void *hwcso) in_dt 83af69d88dSmrg{ 847ec681f3Smrg struct fd_context *ctx = fd_context(pctx); 857ec681f3Smrg ctx->prog.gs = hwcso; 867ec681f3Smrg fd_context_dirty_shader(ctx, PIPE_SHADER_GEOMETRY, FD_DIRTY_SHADER_PROG); 877ec681f3Smrg update_bound_stage(ctx, PIPE_SHADER_GEOMETRY, !!hwcso); 88af69d88dSmrg} 89af69d88dSmrg 90af69d88dSmrgstatic void 917ec681f3Smrgfd_fs_state_bind(struct pipe_context *pctx, void *hwcso) in_dt 927ec681f3Smrg{ 937ec681f3Smrg struct fd_context *ctx = fd_context(pctx); 947ec681f3Smrg ctx->prog.fs = hwcso; 957ec681f3Smrg fd_context_dirty_shader(ctx, PIPE_SHADER_FRAGMENT, FD_DIRTY_SHADER_PROG); 967ec681f3Smrg update_bound_stage(ctx, PIPE_SHADER_FRAGMENT, !!hwcso); 977ec681f3Smrg} 987ec681f3Smrg 997ec681f3Smrgstatic const char *solid_fs = "FRAG \n" 1007ec681f3Smrg "PROPERTY FS_COLOR0_WRITES_ALL_CBUFS 1 \n" 1017ec681f3Smrg "DCL CONST[0] \n" 1027ec681f3Smrg "DCL OUT[0], COLOR \n" 1037ec681f3Smrg " 0: MOV OUT[0], CONST[0] \n" 1047ec681f3Smrg " 1: END \n"; 1057ec681f3Smrg 1067ec681f3Smrgstatic const char *solid_vs = "VERT \n" 1077ec681f3Smrg "DCL IN[0] \n" 1087ec681f3Smrg "DCL OUT[0], POSITION \n" 1097ec681f3Smrg " 0: MOV OUT[0], IN[0] \n" 1107ec681f3Smrg " 1: END \n"; 1117ec681f3Smrg 1127ec681f3Smrgstatic void * 1137ec681f3Smrgassemble_tgsi(struct pipe_context *pctx, const char *src, bool frag) 114af69d88dSmrg{ 1157ec681f3Smrg struct tgsi_token toks[32]; 1167ec681f3Smrg struct pipe_shader_state cso = { 1177ec681f3Smrg .tokens = toks, 1187ec681f3Smrg }; 1197ec681f3Smrg 1207ec681f3Smrg bool ret = tgsi_text_translate(src, toks, ARRAY_SIZE(toks)); 1217ec681f3Smrg assume(ret); 1227ec681f3Smrg 1237ec681f3Smrg if (frag) 1247ec681f3Smrg return pctx->create_fs_state(pctx, &cso); 1257ec681f3Smrg else 1267ec681f3Smrg return pctx->create_vs_state(pctx, &cso); 127af69d88dSmrg} 128af69d88dSmrg 1297ec681f3Smrg/* the correct semantic to use for the texcoord varying depends on pipe-cap: */ 1307ec681f3Smrgstatic enum tgsi_semantic 1317ec681f3Smrgtexcoord_semantic(struct pipe_context *pctx) 132af69d88dSmrg{ 1337ec681f3Smrg struct pipe_screen *pscreen = pctx->screen; 1347ec681f3Smrg 1357ec681f3Smrg if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_TEXCOORD)) { 1367ec681f3Smrg return TGSI_SEMANTIC_TEXCOORD; 1377ec681f3Smrg } else { 1387ec681f3Smrg return TGSI_SEMANTIC_GENERIC; 1397ec681f3Smrg } 140af69d88dSmrg} 141af69d88dSmrg 14201e04c3fSmrgstatic void * 1437ec681f3Smrgfd_prog_blit_vs(struct pipe_context *pctx) 14401e04c3fSmrg{ 1457ec681f3Smrg struct ureg_program *ureg; 1467ec681f3Smrg 1477ec681f3Smrg ureg = ureg_create(PIPE_SHADER_VERTEX); 1487ec681f3Smrg if (!ureg) 1497ec681f3Smrg return NULL; 1507ec681f3Smrg 1517ec681f3Smrg struct ureg_src in0 = ureg_DECL_vs_input(ureg, 0); 1527ec681f3Smrg struct ureg_src in1 = ureg_DECL_vs_input(ureg, 1); 1537ec681f3Smrg 1547ec681f3Smrg struct ureg_dst out0 = ureg_DECL_output(ureg, texcoord_semantic(pctx), 0); 1557ec681f3Smrg struct ureg_dst out1 = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 1); 1567ec681f3Smrg 1577ec681f3Smrg ureg_MOV(ureg, out0, in0); 1587ec681f3Smrg ureg_MOV(ureg, out1, in1); 1597ec681f3Smrg 1607ec681f3Smrg ureg_END(ureg); 1617ec681f3Smrg 1627ec681f3Smrg return ureg_create_shader_and_destroy(ureg, pctx); 16301e04c3fSmrg} 16401e04c3fSmrg 1657ec681f3Smrgstatic void * 1667ec681f3Smrgfd_prog_blit_fs(struct pipe_context *pctx, int rts, bool depth) 1677ec681f3Smrg{ 1687ec681f3Smrg int i; 1697ec681f3Smrg struct ureg_src tc; 1707ec681f3Smrg struct ureg_program *ureg; 1717ec681f3Smrg 1727ec681f3Smrg debug_assert(rts <= MAX_RENDER_TARGETS); 17301e04c3fSmrg 1747ec681f3Smrg ureg = ureg_create(PIPE_SHADER_FRAGMENT); 1757ec681f3Smrg if (!ureg) 1767ec681f3Smrg return NULL; 1777ec681f3Smrg 1787ec681f3Smrg tc = ureg_DECL_fs_input(ureg, texcoord_semantic(pctx), 0, 1797ec681f3Smrg TGSI_INTERPOLATE_PERSPECTIVE); 1807ec681f3Smrg for (i = 0; i < rts; i++) 1817ec681f3Smrg ureg_TEX(ureg, ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, i), 1827ec681f3Smrg TGSI_TEXTURE_2D, tc, ureg_DECL_sampler(ureg, i)); 1837ec681f3Smrg if (depth) 1847ec681f3Smrg ureg_TEX(ureg, 1857ec681f3Smrg ureg_writemask(ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0), 1867ec681f3Smrg TGSI_WRITEMASK_Z), 1877ec681f3Smrg TGSI_TEXTURE_2D, tc, ureg_DECL_sampler(ureg, rts)); 1887ec681f3Smrg 1897ec681f3Smrg ureg_END(ureg); 1907ec681f3Smrg 1917ec681f3Smrg return ureg_create_shader_and_destroy(ureg, pctx); 1927ec681f3Smrg} 1937ec681f3Smrg 1947ec681f3Smrgvoid 1957ec681f3Smrgfd_prog_init(struct pipe_context *pctx) 196af69d88dSmrg{ 1977ec681f3Smrg struct fd_context *ctx = fd_context(pctx); 1987ec681f3Smrg int i; 1997ec681f3Smrg 2007ec681f3Smrg pctx->bind_vs_state = fd_vs_state_bind; 2017ec681f3Smrg pctx->bind_tcs_state = fd_tcs_state_bind; 2027ec681f3Smrg pctx->bind_tes_state = fd_tes_state_bind; 2037ec681f3Smrg pctx->bind_gs_state = fd_gs_state_bind; 2047ec681f3Smrg pctx->bind_fs_state = fd_fs_state_bind; 2057ec681f3Smrg pctx->set_patch_vertices = fd_set_patch_vertices; 2067ec681f3Smrg 2077ec681f3Smrg ctx->solid_prog.fs = assemble_tgsi(pctx, solid_fs, true); 2087ec681f3Smrg ctx->solid_prog.vs = assemble_tgsi(pctx, solid_vs, false); 209af69d88dSmrg 2107ec681f3Smrg if (ctx->screen->gen >= 6) { 2117ec681f3Smrg ctx->solid_layered_prog.fs = assemble_tgsi(pctx, solid_fs, true); 2127ec681f3Smrg ctx->solid_layered_prog.vs = util_make_layered_clear_vertex_shader(pctx); 2137ec681f3Smrg } 214af69d88dSmrg 2157ec681f3Smrg if (ctx->screen->gen >= 5) 2167ec681f3Smrg return; 2179f464c52Smaya 2187ec681f3Smrg ctx->blit_prog[0].vs = fd_prog_blit_vs(pctx); 2197ec681f3Smrg ctx->blit_prog[0].fs = fd_prog_blit_fs(pctx, 1, false); 2209f464c52Smaya 2217ec681f3Smrg if (ctx->screen->gen < 3) 2227ec681f3Smrg return; 22301e04c3fSmrg 2247ec681f3Smrg for (i = 1; i < ctx->screen->max_rts; i++) { 2257ec681f3Smrg ctx->blit_prog[i].vs = ctx->blit_prog[0].vs; 2267ec681f3Smrg ctx->blit_prog[i].fs = fd_prog_blit_fs(pctx, i + 1, false); 2277ec681f3Smrg } 2287ec681f3Smrg 2297ec681f3Smrg ctx->blit_z.vs = ctx->blit_prog[0].vs; 2307ec681f3Smrg ctx->blit_z.fs = fd_prog_blit_fs(pctx, 0, true); 2317ec681f3Smrg ctx->blit_zs.vs = ctx->blit_prog[0].vs; 2327ec681f3Smrg ctx->blit_zs.fs = fd_prog_blit_fs(pctx, 1, true); 233af69d88dSmrg} 234af69d88dSmrg 2357ec681f3Smrgvoid 2367ec681f3Smrgfd_prog_fini(struct pipe_context *pctx) 237af69d88dSmrg{ 2387ec681f3Smrg struct fd_context *ctx = fd_context(pctx); 2397ec681f3Smrg int i; 2407ec681f3Smrg 2417ec681f3Smrg pctx->delete_vs_state(pctx, ctx->solid_prog.vs); 2427ec681f3Smrg pctx->delete_fs_state(pctx, ctx->solid_prog.fs); 2437ec681f3Smrg 2447ec681f3Smrg if (ctx->screen->gen >= 6) { 2457ec681f3Smrg pctx->delete_vs_state(pctx, ctx->solid_layered_prog.vs); 2467ec681f3Smrg pctx->delete_fs_state(pctx, ctx->solid_layered_prog.fs); 2477ec681f3Smrg } 2487ec681f3Smrg 2497ec681f3Smrg if (ctx->screen->gen >= 5) 2507ec681f3Smrg return; 2517ec681f3Smrg 2527ec681f3Smrg pctx->delete_vs_state(pctx, ctx->blit_prog[0].vs); 2537ec681f3Smrg pctx->delete_fs_state(pctx, ctx->blit_prog[0].fs); 2547ec681f3Smrg 2557ec681f3Smrg if (ctx->screen->gen < 3) 2567ec681f3Smrg return; 2577ec681f3Smrg 2587ec681f3Smrg for (i = 1; i < ctx->screen->max_rts; i++) 2597ec681f3Smrg pctx->delete_fs_state(pctx, ctx->blit_prog[i].fs); 2607ec681f3Smrg pctx->delete_fs_state(pctx, ctx->blit_z.fs); 2617ec681f3Smrg pctx->delete_fs_state(pctx, ctx->blit_zs.fs); 262af69d88dSmrg} 263