1/* 2 * Copyright (C) 2012 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 * Jonathan Marek <jonathan@marek.ca> 26 */ 27 28#include "nir/tgsi_to_nir.h" 29#include "pipe/p_state.h" 30#include "tgsi/tgsi_dump.h" 31#include "tgsi/tgsi_parse.h" 32#include "util/format/u_format.h" 33#include "util/u_inlines.h" 34#include "util/u_memory.h" 35#include "util/u_string.h" 36 37#include "freedreno_program.h" 38 39#include "ir2/instr-a2xx.h" 40#include "fd2_program.h" 41#include "fd2_texture.h" 42#include "fd2_util.h" 43#include "ir2.h" 44 45static struct fd2_shader_stateobj * 46create_shader(struct pipe_context *pctx, gl_shader_stage type) 47{ 48 struct fd2_shader_stateobj *so = CALLOC_STRUCT(fd2_shader_stateobj); 49 if (!so) 50 return NULL; 51 so->type = type; 52 so->is_a20x = is_a20x(fd_context(pctx)->screen); 53 return so; 54} 55 56static void 57delete_shader(struct fd2_shader_stateobj *so) 58{ 59 if (!so) 60 return; 61 ralloc_free(so->nir); 62 for (int i = 0; i < ARRAY_SIZE(so->variant); i++) 63 free(so->variant[i].info.dwords); 64 free(so); 65} 66 67static void 68emit(struct fd_ringbuffer *ring, gl_shader_stage type, 69 struct ir2_shader_info *info, struct util_dynarray *patches) 70{ 71 unsigned i; 72 73 assert(info->sizedwords); 74 75 OUT_PKT3(ring, CP_IM_LOAD_IMMEDIATE, 2 + info->sizedwords); 76 OUT_RING(ring, type == MESA_SHADER_FRAGMENT); 77 OUT_RING(ring, info->sizedwords); 78 79 if (patches) 80 util_dynarray_append(patches, uint32_t *, 81 &ring->cur[info->mem_export_ptr]); 82 83 for (i = 0; i < info->sizedwords; i++) 84 OUT_RING(ring, info->dwords[i]); 85} 86 87static int 88ir2_glsl_type_size(const struct glsl_type *type, bool bindless) 89{ 90 return glsl_count_attribute_slots(type, false); 91} 92 93static void * 94fd2_fp_state_create(struct pipe_context *pctx, 95 const struct pipe_shader_state *cso) 96{ 97 struct fd2_shader_stateobj *so = create_shader(pctx, MESA_SHADER_FRAGMENT); 98 if (!so) 99 return NULL; 100 101 so->nir = (cso->type == PIPE_SHADER_IR_NIR) 102 ? cso->ir.nir 103 : tgsi_to_nir(cso->tokens, pctx->screen, false); 104 105 NIR_PASS_V(so->nir, nir_lower_io, nir_var_shader_in | nir_var_shader_out, 106 ir2_glsl_type_size, (nir_lower_io_options)0); 107 108 if (ir2_optimize_nir(so->nir, true)) 109 goto fail; 110 111 so->first_immediate = so->nir->num_uniforms; 112 113 ir2_compile(so, 0, NULL); 114 115 ralloc_free(so->nir); 116 so->nir = NULL; 117 return so; 118 119fail: 120 delete_shader(so); 121 return NULL; 122} 123 124static void 125fd2_fp_state_delete(struct pipe_context *pctx, void *hwcso) 126{ 127 struct fd2_shader_stateobj *so = hwcso; 128 delete_shader(so); 129} 130 131static void * 132fd2_vp_state_create(struct pipe_context *pctx, 133 const struct pipe_shader_state *cso) 134{ 135 struct fd2_shader_stateobj *so = create_shader(pctx, MESA_SHADER_VERTEX); 136 if (!so) 137 return NULL; 138 139 so->nir = (cso->type == PIPE_SHADER_IR_NIR) 140 ? cso->ir.nir 141 : tgsi_to_nir(cso->tokens, pctx->screen, false); 142 143 NIR_PASS_V(so->nir, nir_lower_io, nir_var_shader_in | nir_var_shader_out, 144 ir2_glsl_type_size, (nir_lower_io_options)0); 145 146 if (ir2_optimize_nir(so->nir, true)) 147 goto fail; 148 149 so->first_immediate = so->nir->num_uniforms; 150 151 /* compile binning variant now */ 152 ir2_compile(so, 0, NULL); 153 154 return so; 155 156fail: 157 delete_shader(so); 158 return NULL; 159} 160 161static void 162fd2_vp_state_delete(struct pipe_context *pctx, void *hwcso) 163{ 164 struct fd2_shader_stateobj *so = hwcso; 165 delete_shader(so); 166} 167 168static void 169patch_vtx_fetch(struct fd_context *ctx, struct pipe_vertex_element *elem, 170 instr_fetch_vtx_t *instr, uint16_t dst_swiz) assert_dt 171{ 172 struct surface_format fmt = fd2_pipe2surface(elem->src_format); 173 174 instr->dst_swiz = fd2_vtx_swiz(elem->src_format, dst_swiz); 175 instr->format_comp_all = fmt.sign == SQ_TEX_SIGN_SIGNED; 176 instr->num_format_all = fmt.num_format; 177 instr->format = fmt.format; 178 instr->exp_adjust_all = fmt.exp_adjust; 179 instr->stride = ctx->vtx.vertexbuf.vb[elem->vertex_buffer_index].stride; 180 instr->offset = elem->src_offset; 181} 182 183static void 184patch_fetches(struct fd_context *ctx, struct ir2_shader_info *info, 185 struct fd_vertex_stateobj *vtx, 186 struct fd_texture_stateobj *tex) assert_dt 187{ 188 for (int i = 0; i < info->num_fetch_instrs; i++) { 189 struct ir2_fetch_info *fi = &info->fetch_info[i]; 190 191 instr_fetch_t *instr = (instr_fetch_t *)&info->dwords[fi->offset]; 192 if (instr->opc == VTX_FETCH) { 193 unsigned idx = 194 (instr->vtx.const_index - 20) * 3 + instr->vtx.const_index_sel; 195 patch_vtx_fetch(ctx, &vtx->pipe[idx], &instr->vtx, fi->vtx.dst_swiz); 196 continue; 197 } 198 199 assert(instr->opc == TEX_FETCH); 200 instr->tex.const_idx = fd2_get_const_idx(ctx, tex, fi->tex.samp_id); 201 instr->tex.src_swiz = fi->tex.src_swiz; 202 } 203} 204 205void 206fd2_program_emit(struct fd_context *ctx, struct fd_ringbuffer *ring, 207 struct fd_program_stateobj *prog) 208{ 209 struct fd2_shader_stateobj *fp = NULL, *vp; 210 struct ir2_shader_info *fpi, *vpi; 211 struct ir2_frag_linkage *f; 212 uint8_t vs_gprs, fs_gprs = 0, vs_export = 0; 213 enum a2xx_sq_ps_vtx_mode mode = POSITION_1_VECTOR; 214 bool binning = (ctx->batch && ring == ctx->batch->binning); 215 unsigned variant = 0; 216 217 vp = prog->vs; 218 219 /* find variant matching the linked fragment shader */ 220 if (!binning) { 221 fp = prog->fs; 222 for (variant = 1; variant < ARRAY_SIZE(vp->variant); variant++) { 223 /* if checked all variants, compile a new variant */ 224 if (!vp->variant[variant].info.sizedwords) { 225 ir2_compile(vp, variant, fp); 226 break; 227 } 228 229 /* check if fragment shader linkage matches */ 230 if (!memcmp(&vp->variant[variant].f, &fp->variant[0].f, 231 sizeof(struct ir2_frag_linkage))) 232 break; 233 } 234 assert(variant < ARRAY_SIZE(vp->variant)); 235 } 236 237 vpi = &vp->variant[variant].info; 238 fpi = &fp->variant[0].info; 239 f = &fp->variant[0].f; 240 241 /* clear/gmem2mem/mem2gmem need to be changed to remove this condition */ 242 if (prog != &ctx->solid_prog && prog != &ctx->blit_prog[0]) { 243 patch_fetches(ctx, vpi, ctx->vtx.vtx, &ctx->tex[PIPE_SHADER_VERTEX]); 244 if (fp) 245 patch_fetches(ctx, fpi, NULL, &ctx->tex[PIPE_SHADER_FRAGMENT]); 246 } 247 248 emit(ring, MESA_SHADER_VERTEX, vpi, 249 binning ? &ctx->batch->shader_patches : NULL); 250 251 if (fp) { 252 emit(ring, MESA_SHADER_FRAGMENT, fpi, NULL); 253 fs_gprs = (fpi->max_reg < 0) ? 0x80 : fpi->max_reg; 254 vs_export = MAX2(1, f->inputs_count) - 1; 255 } 256 257 vs_gprs = (vpi->max_reg < 0) ? 0x80 : vpi->max_reg; 258 259 if (vp->writes_psize && !binning) 260 mode = POSITION_2_VECTORS_SPRITE; 261 262 /* set register to use for param (fragcoord/pointcoord/frontfacing) */ 263 OUT_PKT3(ring, CP_SET_CONSTANT, 2); 264 OUT_RING(ring, CP_REG(REG_A2XX_SQ_CONTEXT_MISC)); 265 OUT_RING(ring, 266 A2XX_SQ_CONTEXT_MISC_SC_SAMPLE_CNTL(CENTERS_ONLY) | 267 COND(fp, A2XX_SQ_CONTEXT_MISC_PARAM_GEN_POS(f->inputs_count)) | 268 /* we need SCREEN_XY for both fragcoord and frontfacing */ 269 A2XX_SQ_CONTEXT_MISC_SC_OUTPUT_SCREEN_XY); 270 271 OUT_PKT3(ring, CP_SET_CONSTANT, 2); 272 OUT_RING(ring, CP_REG(REG_A2XX_SQ_PROGRAM_CNTL)); 273 OUT_RING(ring, 274 A2XX_SQ_PROGRAM_CNTL_PS_EXPORT_MODE(2) | 275 A2XX_SQ_PROGRAM_CNTL_VS_EXPORT_MODE(mode) | 276 A2XX_SQ_PROGRAM_CNTL_VS_RESOURCE | 277 A2XX_SQ_PROGRAM_CNTL_PS_RESOURCE | 278 A2XX_SQ_PROGRAM_CNTL_VS_EXPORT_COUNT(vs_export) | 279 A2XX_SQ_PROGRAM_CNTL_PS_REGS(fs_gprs) | 280 A2XX_SQ_PROGRAM_CNTL_VS_REGS(vs_gprs) | 281 COND(fp && fp->need_param, A2XX_SQ_PROGRAM_CNTL_PARAM_GEN) | 282 COND(!fp, A2XX_SQ_PROGRAM_CNTL_GEN_INDEX_VTX)); 283} 284 285void 286fd2_prog_init(struct pipe_context *pctx) 287{ 288 struct fd_context *ctx = fd_context(pctx); 289 struct fd_program_stateobj *prog; 290 struct fd2_shader_stateobj *so; 291 struct ir2_shader_info *info; 292 instr_fetch_vtx_t *instr; 293 294 pctx->create_fs_state = fd2_fp_state_create; 295 pctx->delete_fs_state = fd2_fp_state_delete; 296 297 pctx->create_vs_state = fd2_vp_state_create; 298 pctx->delete_vs_state = fd2_vp_state_delete; 299 300 fd_prog_init(pctx); 301 302 /* XXX maybe its possible to reuse patch_vtx_fetch somehow? */ 303 304 prog = &ctx->solid_prog; 305 so = prog->vs; 306 ir2_compile(prog->vs, 1, prog->fs); 307 308#define IR2_FETCH_SWIZ_XY01 0xb08 309#define IR2_FETCH_SWIZ_XYZ1 0xa88 310 311 info = &so->variant[1].info; 312 313 instr = (instr_fetch_vtx_t *)&info->dwords[info->fetch_info[0].offset]; 314 instr->const_index = 26; 315 instr->const_index_sel = 0; 316 instr->format = FMT_32_32_32_FLOAT; 317 instr->format_comp_all = false; 318 instr->stride = 12; 319 instr->num_format_all = true; 320 instr->dst_swiz = IR2_FETCH_SWIZ_XYZ1; 321 322 prog = &ctx->blit_prog[0]; 323 so = prog->vs; 324 ir2_compile(prog->vs, 1, prog->fs); 325 326 info = &so->variant[1].info; 327 328 instr = (instr_fetch_vtx_t *)&info->dwords[info->fetch_info[0].offset]; 329 instr->const_index = 26; 330 instr->const_index_sel = 1; 331 instr->format = FMT_32_32_FLOAT; 332 instr->format_comp_all = false; 333 instr->stride = 8; 334 instr->num_format_all = false; 335 instr->dst_swiz = IR2_FETCH_SWIZ_XY01; 336 337 instr = (instr_fetch_vtx_t *)&info->dwords[info->fetch_info[1].offset]; 338 instr->const_index = 26; 339 instr->const_index_sel = 0; 340 instr->format = FMT_32_32_32_FLOAT; 341 instr->format_comp_all = false; 342 instr->stride = 12; 343 instr->num_format_all = false; 344 instr->dst_swiz = IR2_FETCH_SWIZ_XYZ1; 345} 346