const struct tgsi_token * tgsi_emulate(const struct tgsi_token *tokens, unsigned flags) { struct tgsi_emulation_context ctx; struct tgsi_token *newtoks; int newlen; if (!(flags & (TGSI_EMU_CLAMP_COLOR_OUTPUTS | TGSI_EMU_PASSTHROUGH_EDGEFLAG | TGSI_EMU_FORCE_PERSAMPLE_INTERP))) return NULL; memset(&ctx, 0, sizeof(ctx)); ctx.flags = flags; tgsi_scan_shader(tokens, &ctx.info); if (flags & TGSI_EMU_FORCE_PERSAMPLE_INTERP) ctx.base.transform_declaration = transform_decl; if (flags & (TGSI_EMU_CLAMP_COLOR_OUTPUTS | TGSI_EMU_PASSTHROUGH_EDGEFLAG)) ctx.base.transform_instruction = transform_instr; newlen = tgsi_num_tokens(tokens) + 20; newtoks = tgsi_alloc_tokens(newlen); if (!newtoks) return NULL; tgsi_transform_shader(tokens, newtoks, newlen, &ctx.base); return newtoks; }
/** * Create vertex shader state. * Called via pipe->create_vs_state() */ static void * cell_create_vs_state(struct pipe_context *pipe, const struct pipe_shader_state *templ) { struct cell_context *cell = cell_context(pipe); struct cell_vertex_shader_state *cvs; cvs = CALLOC_STRUCT(cell_vertex_shader_state); if (!cvs) return NULL; cvs->shader.tokens = tgsi_dup_tokens(templ->tokens); if (!cvs->shader.tokens) { FREE(cvs); return NULL; } tgsi_scan_shader(templ->tokens, &cvs->info); cvs->draw_data = draw_create_vertex_shader(cell->draw, &cvs->shader); if (cvs->draw_data == NULL) { FREE( (void *) cvs->shader.tokens ); FREE( cvs ); return NULL; } return cvs; }
static void * svga_create_gs_state(struct pipe_context *pipe, const struct pipe_shader_state *templ) { struct svga_context *svga = svga_context(pipe); struct svga_geometry_shader *gs = CALLOC_STRUCT(svga_geometry_shader); if (!gs) return NULL; SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_CREATEGS); gs->base.tokens = tgsi_dup_tokens(templ->tokens); /* Collect basic info that we'll need later: */ tgsi_scan_shader(gs->base.tokens, &gs->base.info); gs->draw_shader = draw_create_geometry_shader(svga->swtnl.draw, templ); gs->base.id = svga->debug.shader_id++; gs->generic_outputs = svga_get_generic_outputs_mask(&gs->base.info); /* check for any stream output declarations */ if (templ->stream_output.num_outputs) { gs->base.stream_output = svga_create_stream_output(svga, &gs->base, &templ->stream_output); } SVGA_STATS_TIME_POP(svga_sws(svga)); return gs; }
static void * svga_create_fs_state(struct pipe_context *pipe, const struct pipe_shader_state *templ) { struct svga_context *svga = svga_context(pipe); struct svga_fragment_shader *fs; fs = CALLOC_STRUCT(svga_fragment_shader); if (!fs) return NULL; fs->base.tokens = tgsi_dup_tokens(templ->tokens); /* Collect basic info that we'll need later: */ tgsi_scan_shader(fs->base.tokens, &fs->base.info); fs->base.id = svga->debug.shader_id++; fs->generic_inputs = svga_get_generic_inputs_mask(&fs->base.info); svga_remap_generics(fs->generic_inputs, fs->generic_remap_table); fs->draw_shader = draw_create_fragment_shader(svga->swtnl.draw, templ); if (SVGA_DEBUG & DEBUG_TGSI || 0) { debug_printf("%s id: %u, inputs: %u, outputs: %u\n", __FUNCTION__, fs->base.id, fs->base.info.num_inputs, fs->base.info.num_outputs); } return fs; }
static void * svga_create_fs_state(struct pipe_context *pipe, const struct pipe_shader_state *templ) { struct svga_context *svga = svga_context(pipe); struct svga_screen *svgascreen = svga_screen(pipe->screen); struct svga_fragment_shader *fs; fs = CALLOC_STRUCT(svga_fragment_shader); if (!fs) return NULL; fs->base.tokens = tgsi_dup_tokens(templ->tokens); /* Collect basic info that we'll need later: */ tgsi_scan_shader(fs->base.tokens, &fs->base.info); fs->base.id = svga->debug.shader_id++; fs->base.use_sm30 = svgascreen->use_ps30; if (SVGA_DEBUG & DEBUG_TGSI || 0) { debug_printf("%s id: %u, inputs: %u, outputs: %u\n", __FUNCTION__, fs->base.id, fs->base.info.num_inputs, fs->base.info.num_outputs); } return fs; }
LLVMModuleRef r600_tgsi_llvm( struct radeon_llvm_context * ctx, const struct tgsi_token * tokens) { struct tgsi_shader_info shader_info; struct lp_build_tgsi_context * bld_base = &ctx->soa.bld_base; radeon_llvm_context_init(ctx); tgsi_scan_shader(tokens, &shader_info); bld_base->info = &shader_info; bld_base->userdata = ctx; bld_base->emit_fetch_funcs[TGSI_FILE_CONSTANT] = llvm_fetch_const; bld_base->emit_prologue = llvm_emit_prologue; bld_base->emit_epilogue = llvm_emit_epilogue; ctx->userdata = ctx; ctx->load_input = llvm_load_input; bld_base->op_actions[TGSI_OPCODE_DP2] = dot_action; bld_base->op_actions[TGSI_OPCODE_DP3] = dot_action; bld_base->op_actions[TGSI_OPCODE_DP4] = dot_action; bld_base->op_actions[TGSI_OPCODE_DPH] = dot_action; bld_base->op_actions[TGSI_OPCODE_TEX].emit = llvm_emit_tex; bld_base->op_actions[TGSI_OPCODE_TXB].emit = llvm_emit_tex; bld_base->op_actions[TGSI_OPCODE_TXD].emit = llvm_emit_tex; bld_base->op_actions[TGSI_OPCODE_TXL].emit = llvm_emit_tex; bld_base->op_actions[TGSI_OPCODE_TXP].fetch_args = txp_fetch_args; bld_base->op_actions[TGSI_OPCODE_TXP].emit = llvm_emit_tex; lp_build_tgsi_llvm(bld_base, tokens); radeon_llvm_finalize_module(ctx); return ctx->gallivm.module; }
LLVMModuleRef r600_tgsi_llvm( struct radeon_llvm_context * ctx, const struct tgsi_token * tokens) { struct tgsi_shader_info shader_info; struct lp_build_tgsi_context * bld_base = &ctx->soa.bld_base; radeon_llvm_context_init(ctx); #if HAVE_LLVM >= 0x0304 LLVMTypeRef Arguments[32]; unsigned ArgumentsCount = 0; for (unsigned i = 0; i < ctx->inputs_count; i++) Arguments[ArgumentsCount++] = LLVMVectorType(bld_base->base.elem_type, 4); radeon_llvm_create_func(ctx, Arguments, ArgumentsCount); for (unsigned i = 0; i < ctx->inputs_count; i++) { LLVMValueRef P = LLVMGetParam(ctx->main_fn, i); LLVMAddAttribute(P, LLVMInRegAttribute); } #else radeon_llvm_create_func(ctx, NULL, 0); #endif tgsi_scan_shader(tokens, &shader_info); bld_base->info = &shader_info; bld_base->userdata = ctx; bld_base->emit_fetch_funcs[TGSI_FILE_CONSTANT] = llvm_fetch_const; bld_base->emit_prologue = llvm_emit_prologue; bld_base->emit_epilogue = llvm_emit_epilogue; ctx->userdata = ctx; ctx->load_input = llvm_load_input; ctx->load_system_value = llvm_load_system_value; bld_base->op_actions[TGSI_OPCODE_DP2] = dot_action; bld_base->op_actions[TGSI_OPCODE_DP3] = dot_action; bld_base->op_actions[TGSI_OPCODE_DP4] = dot_action; bld_base->op_actions[TGSI_OPCODE_DPH] = dot_action; bld_base->op_actions[TGSI_OPCODE_DDX].emit = llvm_emit_tex; bld_base->op_actions[TGSI_OPCODE_DDY].emit = llvm_emit_tex; bld_base->op_actions[TGSI_OPCODE_TEX].emit = llvm_emit_tex; bld_base->op_actions[TGSI_OPCODE_TEX2].emit = llvm_emit_tex; bld_base->op_actions[TGSI_OPCODE_TXB].emit = llvm_emit_tex; bld_base->op_actions[TGSI_OPCODE_TXB2].emit = llvm_emit_tex; bld_base->op_actions[TGSI_OPCODE_TXD].emit = llvm_emit_tex; bld_base->op_actions[TGSI_OPCODE_TXL].emit = llvm_emit_tex; bld_base->op_actions[TGSI_OPCODE_TXL2].emit = llvm_emit_tex; bld_base->op_actions[TGSI_OPCODE_TXF].emit = llvm_emit_tex; bld_base->op_actions[TGSI_OPCODE_TXQ].emit = llvm_emit_tex; bld_base->op_actions[TGSI_OPCODE_TXP].emit = llvm_emit_tex; bld_base->op_actions[TGSI_OPCODE_CMP].emit = emit_cndlt; lp_build_tgsi_llvm(bld_base, tokens); radeon_llvm_finalize_module(ctx); return ctx->gallivm.module; }
static void * nv50_gp_state_create(struct pipe_context *pipe, const struct pipe_shader_state *cso) { struct nv50_program *p = CALLOC_STRUCT(nv50_program); p->pipe.tokens = tgsi_dup_tokens(cso->tokens); p->type = PIPE_SHADER_GEOMETRY; tgsi_scan_shader(p->pipe.tokens, &p->info); return (void *)p; }
static int nv30_fp(int chipset, struct tgsi_token tokens[], unsigned *size, unsigned **code) { struct nv30_fragprog fp; memset(&fp, 0, sizeof(fp)); fp.pipe.tokens = tokens; tgsi_scan_shader(fp.pipe.tokens, &fp.info); _nvfx_fragprog_translate(chipset >= 0x40 ? 0x4097 : 0x3097, &fp); *size = fp.insn_len * 4; *code = fp.insn; return !fp.translated; }
struct draw_geometry_shader * draw_create_geometry_shader(struct draw_context *draw, const struct pipe_shader_state *state) { struct draw_geometry_shader *gs; int i; gs = CALLOC_STRUCT(draw_geometry_shader); if (!gs) return NULL; gs->draw = draw; gs->state = *state; gs->state.tokens = tgsi_dup_tokens(state->tokens); if (!gs->state.tokens) { FREE(gs); return NULL; } tgsi_scan_shader(state->tokens, &gs->info); /* setup the defaults */ gs->input_primitive = PIPE_PRIM_TRIANGLES; gs->output_primitive = PIPE_PRIM_TRIANGLE_STRIP; gs->max_output_vertices = 32; for (i = 0; i < gs->info.num_properties; ++i) { if (gs->info.properties[i].name == TGSI_PROPERTY_GS_INPUT_PRIM) gs->input_primitive = gs->info.properties[i].data[0]; else if (gs->info.properties[i].name == TGSI_PROPERTY_GS_OUTPUT_PRIM) gs->output_primitive = gs->info.properties[i].data[0]; else if (gs->info.properties[i].name == TGSI_PROPERTY_GS_MAX_OUTPUT_VERTICES) gs->max_output_vertices = gs->info.properties[i].data[0]; } gs->machine = draw->gs.tgsi.machine; if (gs) { uint i; for (i = 0; i < gs->info.num_outputs; i++) { if (gs->info.output_semantic_name[i] == TGSI_SEMANTIC_POSITION && gs->info.output_semantic_index[i] == 0) gs->position_output = i; } } return gs; }
static void * nv30_vp_state_create(struct pipe_context *pipe, const struct pipe_shader_state *cso) { struct nv30_vertprog *vp = CALLOC_STRUCT(nv30_vertprog); if (!vp) return NULL; vp->pipe.tokens = tgsi_dup_tokens(cso->tokens); tgsi_scan_shader(vp->pipe.tokens, &vp->info); return vp; }
static void * nv30_fp_state_create(struct pipe_context *pipe, const struct pipe_shader_state *cso) { struct nv30_fragprog *fp = CALLOC_STRUCT(nv30_fragprog); if (!fp) return NULL; fp->pipe.tokens = tgsi_dup_tokens(cso->tokens); tgsi_scan_shader(fp->pipe.tokens, &fp->info); return fp; }
static void * nv40_fp_state_create(struct pipe_context *pipe, const struct pipe_shader_state *cso) { struct nv40_fragment_program *fp; fp = CALLOC(1, sizeof(struct nv40_fragment_program)); fp->pipe.tokens = tgsi_dup_tokens(cso->tokens); tgsi_scan_shader(fp->pipe.tokens, &fp->info); return (void *)fp; }
static int nv30_vp(int chipset, struct tgsi_token tokens[], unsigned *size, unsigned **code) { struct nv30_vertprog vp; memset(&vp, 0, sizeof(vp)); vp.pipe.tokens = tokens; tgsi_scan_shader(vp.pipe.tokens, &vp.info); _nvfx_vertprog_translate(chipset >= 0x40 ? 0x4097 : 0x3097, &vp); *size = vp.nr_insns * 16; *code = (unsigned *)vp.insns; return !vp.translated; }
struct draw_fragment_shader * draw_create_fragment_shader(struct draw_context *draw, const struct pipe_shader_state *shader) { struct draw_fragment_shader *dfs; dfs = CALLOC_STRUCT(draw_fragment_shader); if (dfs) { dfs->base = *shader; tgsi_scan_shader(shader->tokens, &dfs->info); } return dfs; }
/* Create fragment shader state. */ static void* r300_create_fs_state(struct pipe_context* pipe, const struct pipe_shader_state* shader) { struct r300_fragment_shader* fs = NULL; fs = (struct r300_fragment_shader*)CALLOC_STRUCT(r300_fragment_shader); /* Copy state directly into shader. */ fs->state = *shader; fs->state.tokens = tgsi_dup_tokens(shader->tokens); tgsi_scan_shader(shader->tokens, &fs->info); return (void*)fs; }
/** * Create a new fragment shader variant. */ static struct sp_fragment_shader_variant * create_fs_variant(struct softpipe_context *softpipe, struct sp_fragment_shader *fs, const struct sp_fragment_shader_variant_key *key) { struct sp_fragment_shader_variant *var; struct pipe_shader_state *curfs = &fs->shader; /* codegen, create variant object */ var = softpipe_create_fs_variant_exec(softpipe); if (var) { var->key = *key; #if DO_PSTIPPLE_IN_HELPER_MODULE if (key->polygon_stipple) { /* get new shader that implements polygon stippling */ var->tokens = util_pstipple_create_fragment_shader(curfs->tokens, &var->stipple_sampler_unit, 0, TGSI_FILE_INPUT); } else #endif { var->tokens = tgsi_dup_tokens(curfs->tokens); var->stipple_sampler_unit = 0; } tgsi_scan_shader(var->tokens, &var->info); /* See comments elsewhere about draw fragment shaders */ #if 0 /* draw's fs state */ var->draw_shader = draw_create_fragment_shader(softpipe->draw, &fs->shader); if (!var->draw_shader) { var->delete(var); FREE((void *) var->tokens); return NULL; } #endif /* insert variant into linked list */ var->next = fs->variants; fs->variants = var; }
static void *brw_create_fs_state( struct pipe_context *pipe, const struct pipe_shader_state *shader ) { struct brw_context *brw = brw_context(pipe); struct brw_fragment_shader *fs; int i; fs = CALLOC_STRUCT(brw_fragment_shader); if (fs == NULL) return NULL; /* Duplicate tokens, scan shader */ fs->id = brw->program_id++; fs->has_flow_control = has_flow_control(&fs->info); fs->tokens = tgsi_dup_tokens(shader->tokens); if (fs->tokens == NULL) goto fail; tgsi_scan_shader(fs->tokens, &fs->info); scan_immediates(fs->tokens, &fs->info, &fs->immediates); fs->signature.nr_inputs = fs->info.num_inputs; for (i = 0; i < fs->info.num_inputs; i++) { fs->signature.input[i].interp = fs->info.input_interpolate[i]; fs->signature.input[i].semantic = fs->info.input_semantic_name[i]; fs->signature.input[i].semantic_index = fs->info.input_semantic_index[i]; } for (i = 0; i < fs->info.num_inputs; i++) if (fs->info.input_semantic_name[i] == TGSI_SEMANTIC_POSITION) fs->uses_depth = 1; if (fs->info.uses_kill) fs->iz_lookup |= IZ_PS_KILL_ALPHATEST_BIT; if (fs->info.writes_z) fs->iz_lookup |= IZ_PS_COMPUTES_DEPTH_BIT; return (void *)fs; fail: FREE(fs); return NULL; }
static void * i915_create_fs_state(struct pipe_context *pipe, const struct pipe_shader_state *templ) { struct i915_context *i915 = i915_context(pipe); struct i915_fragment_shader *ifs = CALLOC_STRUCT(i915_fragment_shader); if (!ifs) return NULL; ifs->state.tokens = tgsi_dup_tokens(templ->tokens); tgsi_scan_shader(templ->tokens, &ifs->info); /* The shader's compiled to i915 instructions here */ i915_translate_fragment_program(i915, ifs); return ifs; }
static unsigned dd_num_active_viewports(struct dd_context *dctx) { struct tgsi_shader_info info; const struct tgsi_token *tokens; if (dctx->shaders[PIPE_SHADER_GEOMETRY]) tokens = dctx->shaders[PIPE_SHADER_GEOMETRY]->state.shader.tokens; else if (dctx->shaders[PIPE_SHADER_TESS_EVAL]) tokens = dctx->shaders[PIPE_SHADER_TESS_EVAL]->state.shader.tokens; else if (dctx->shaders[PIPE_SHADER_VERTEX]) tokens = dctx->shaders[PIPE_SHADER_VERTEX]->state.shader.tokens; else return 1; tgsi_scan_shader(tokens, &info); return info.writes_viewport_index ? PIPE_MAX_VIEWPORTS : 1; }
void * llvmpipe_create_fs_state(struct pipe_context *pipe, const struct pipe_shader_state *templ) { struct lp_fragment_shader *shader; shader = CALLOC_STRUCT(lp_fragment_shader); if (!shader) return NULL; /* get/save the summary info for this shader */ tgsi_scan_shader(templ->tokens, &shader->info); /* we need to keep a local copy of the tokens */ shader->base.tokens = tgsi_dup_tokens(templ->tokens); return shader; }
static void * llvmpipe_create_fs_state(struct pipe_context *pipe, const struct pipe_shader_state *templ) { struct lp_fragment_shader *shader; int nr_samplers; shader = CALLOC_STRUCT(lp_fragment_shader); if (!shader) return NULL; shader->no = fs_no++; make_empty_list(&shader->variants); /* get/save the summary info for this shader */ tgsi_scan_shader(templ->tokens, &shader->info); /* we need to keep a local copy of the tokens */ shader->base.tokens = tgsi_dup_tokens(templ->tokens); nr_samplers = shader->info.file_max[TGSI_FILE_SAMPLER] + 1; shader->variant_key_size = Offset(struct lp_fragment_shader_variant_key, sampler[nr_samplers]); if (LP_DEBUG & DEBUG_TGSI) { unsigned attrib; debug_printf("llvmpipe: Create fragment shader #%u %p:\n", shader->no, (void *) shader); tgsi_dump(templ->tokens, 0); debug_printf("usage masks:\n"); for (attrib = 0; attrib < shader->info.num_inputs; ++attrib) { unsigned usage_mask = shader->info.input_usage_mask[attrib]; debug_printf(" IN[%u].%s%s%s%s\n", attrib, usage_mask & TGSI_WRITEMASK_X ? "x" : "", usage_mask & TGSI_WRITEMASK_Y ? "y" : "", usage_mask & TGSI_WRITEMASK_Z ? "z" : "", usage_mask & TGSI_WRITEMASK_W ? "w" : ""); } debug_printf("\n"); } return shader; }
static void * svga_create_vs_state(struct pipe_context *pipe, const struct pipe_shader_state *templ) { struct svga_context *svga = svga_context(pipe); struct svga_vertex_shader *vs = CALLOC_STRUCT(svga_vertex_shader); if (!vs) return NULL; SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_CREATEVS); /* substitute a debug shader? */ vs->base.tokens = tgsi_dup_tokens(substitute_vs(svga->debug.shader_id, templ->tokens)); /* Collect basic info that we'll need later: */ tgsi_scan_shader(vs->base.tokens, &vs->base.info); { /* Need to do construct a new template in case we substitued a * debug shader. */ struct pipe_shader_state tmp2 = *templ; tmp2.tokens = vs->base.tokens; vs->draw_shader = draw_create_vertex_shader(svga->swtnl.draw, &tmp2); } vs->base.id = svga->debug.shader_id++; vs->generic_outputs = svga_get_generic_outputs_mask(&vs->base.info); /* check for any stream output declarations */ if (templ->stream_output.num_outputs) { vs->base.stream_output = svga_create_stream_output(svga, &vs->base, &templ->stream_output); } SVGA_STATS_TIME_POP(svga_sws(svga)); return vs; }
static void* r300_create_vs_state(struct pipe_context* pipe, const struct pipe_shader_state* shader) { struct r300_context* r300 = r300_context(pipe); if (r300_screen(pipe->screen)->caps->has_tcl) { struct r300_vertex_shader* vs = CALLOC_STRUCT(r300_vertex_shader); /* Copy state directly into shader. */ vs->state = *shader; vs->state.tokens = tgsi_dup_tokens(shader->tokens); tgsi_scan_shader(shader->tokens, &vs->info); /* Appease Draw. */ vs->draw = draw_create_vertex_shader(r300->draw, shader); return (void*)vs; } else { return draw_create_vertex_shader(r300->draw, shader); } }
static void * svga_create_vs_state(struct pipe_context *pipe, const struct pipe_shader_state *templ) { struct svga_context *svga = svga_context(pipe); struct svga_screen *svgascreen = svga_screen(pipe->screen); struct svga_vertex_shader *vs = CALLOC_STRUCT(svga_vertex_shader); if (!vs) return NULL; /* substitute a debug shader? */ vs->base.tokens = tgsi_dup_tokens(substitute_vs(svga->debug.shader_id, templ->tokens)); /* Collect basic info that we'll need later: */ tgsi_scan_shader(vs->base.tokens, &vs->base.info); { /* Need to do construct a new template in case we substitued a * debug shader. */ struct pipe_shader_state tmp2 = *templ; tmp2.tokens = vs->base.tokens; vs->draw_shader = draw_create_vertex_shader(svga->swtnl.draw, &tmp2); } vs->base.id = svga->debug.shader_id++; vs->base.use_sm30 = svgascreen->use_vs30; if (SVGA_DEBUG & DEBUG_TGSI || 0) { debug_printf("%s id: %u, inputs: %u, outputs: %u\n", __FUNCTION__, vs->base.id, vs->base.info.num_inputs, vs->base.info.num_outputs); } return vs; }
/* * A post-process step in the draw call to fix texture targets and * insert code for fog. */ const struct tgsi_token * st_fixup_atifs(const struct tgsi_token *tokens, const struct st_fp_variant_key *key) { struct tgsi_atifs_transform ctx; struct tgsi_token *newtoks; int newlen; memset(&ctx, 0, sizeof(ctx)); ctx.base.transform_declaration = transform_decl; ctx.base.transform_instruction = transform_instr; ctx.key = key; tgsi_scan_shader(tokens, &ctx.info); newlen = tgsi_num_tokens(tokens) + 30; newtoks = tgsi_alloc_tokens(newlen); if (!newtoks) return NULL; tgsi_transform_shader(tokens, newtoks, newlen, &ctx.base); return newtoks; }
/** * Create fragment shader state. * Called via pipe->create_fs_state() */ static void * cell_create_fs_state(struct pipe_context *pipe, const struct pipe_shader_state *templ) { struct cell_context *cell = cell_context(pipe); struct cell_fragment_shader_state *cfs; cfs = CALLOC_STRUCT(cell_fragment_shader_state); if (!cfs) return NULL; cfs->shader.tokens = tgsi_dup_tokens(templ->tokens); if (!cfs->shader.tokens) { FREE(cfs); return NULL; } tgsi_scan_shader(templ->tokens, &cfs->info); cell_gen_fragment_program(cell, cfs->shader.tokens, &cfs->code); return cfs; }
struct draw_geometry_shader * draw_create_geometry_shader(struct draw_context *draw, const struct pipe_shader_state *state) { #ifdef HAVE_LLVM boolean use_llvm = draw_get_option_use_llvm(); struct llvm_geometry_shader *llvm_gs; #endif struct draw_geometry_shader *gs; unsigned i; #ifdef HAVE_LLVM if (use_llvm) { llvm_gs = CALLOC_STRUCT(llvm_geometry_shader); if (llvm_gs == NULL) return NULL; gs = &llvm_gs->base; make_empty_list(&llvm_gs->variants); } else #endif { gs = CALLOC_STRUCT(draw_geometry_shader); } if (!gs) return NULL; gs->draw = draw; gs->state = *state; gs->state.tokens = tgsi_dup_tokens(state->tokens); if (!gs->state.tokens) { FREE(gs); return NULL; } tgsi_scan_shader(state->tokens, &gs->info); /* setup the defaults */ gs->input_primitive = PIPE_PRIM_TRIANGLES; gs->output_primitive = PIPE_PRIM_TRIANGLE_STRIP; gs->max_output_vertices = 32; gs->max_out_prims = 0; #ifdef HAVE_LLVM if (use_llvm) { /* TODO: change the input array to handle the following vector length, instead of the currently hardcoded TGSI_NUM_CHANNELS gs->vector_length = lp_native_vector_width / 32;*/ gs->vector_length = TGSI_NUM_CHANNELS; } else #endif { gs->vector_length = 1; } for (i = 0; i < gs->info.num_properties; ++i) { if (gs->info.properties[i].name == TGSI_PROPERTY_GS_INPUT_PRIM) gs->input_primitive = gs->info.properties[i].data[0]; else if (gs->info.properties[i].name == TGSI_PROPERTY_GS_OUTPUT_PRIM) gs->output_primitive = gs->info.properties[i].data[0]; else if (gs->info.properties[i].name == TGSI_PROPERTY_GS_MAX_OUTPUT_VERTICES) gs->max_output_vertices = gs->info.properties[i].data[0]; } /* Primitive boundary is bigger than max_output_vertices by one, because * the specification says that the geometry shader should exit if the * number of emitted vertices is bigger or equal to max_output_vertices and * we can't do that because we're running in the SoA mode, which means that * our storing routines will keep getting called on channels that have * overflown. * So we need some scratch area where we can keep writing the overflown * vertices without overwriting anything important or crashing. */ gs->primitive_boundary = gs->max_output_vertices + 1; for (i = 0; i < gs->info.num_outputs; i++) { if (gs->info.output_semantic_name[i] == TGSI_SEMANTIC_POSITION && gs->info.output_semantic_index[i] == 0) gs->position_output = i; if (gs->info.output_semantic_name[i] == TGSI_SEMANTIC_VIEWPORT_INDEX) gs->viewport_index_output = i; if (gs->info.output_semantic_name[i] == TGSI_SEMANTIC_CLIPDIST) { debug_assert(gs->info.output_semantic_index[i] < PIPE_MAX_CLIP_OR_CULL_DISTANCE_ELEMENT_COUNT); gs->clipdistance_output[gs->info.output_semantic_index[i]] = i; } if (gs->info.output_semantic_name[i] == TGSI_SEMANTIC_CULLDIST) { debug_assert(gs->info.output_semantic_index[i] < PIPE_MAX_CLIP_OR_CULL_DISTANCE_ELEMENT_COUNT); gs->culldistance_output[gs->info.output_semantic_index[i]] = i; } } gs->machine = draw->gs.tgsi.machine; #ifdef HAVE_LLVM if (use_llvm) { int vector_size = gs->vector_length * sizeof(float); gs->gs_input = align_malloc(sizeof(struct draw_gs_inputs), 16); memset(gs->gs_input, 0, sizeof(struct draw_gs_inputs)); gs->llvm_prim_lengths = 0; gs->llvm_emitted_primitives = align_malloc(vector_size, vector_size); gs->llvm_emitted_vertices = align_malloc(vector_size, vector_size); gs->llvm_prim_ids = align_malloc(vector_size, vector_size); gs->fetch_outputs = llvm_fetch_gs_outputs; gs->fetch_inputs = llvm_fetch_gs_input; gs->prepare = llvm_gs_prepare; gs->run = llvm_gs_run; gs->jit_context = &draw->llvm->gs_jit_context; llvm_gs->variant_key_size = draw_gs_llvm_variant_key_size( MAX2(gs->info.file_max[TGSI_FILE_SAMPLER]+1, gs->info.file_max[TGSI_FILE_SAMPLER_VIEW]+1)); } else #endif { gs->fetch_outputs = tgsi_fetch_gs_outputs; gs->fetch_inputs = tgsi_fetch_gs_input; gs->prepare = tgsi_gs_prepare; gs->run = tgsi_gs_run; } return gs; }
static void *si_create_compute_state( struct pipe_context *ctx, const struct pipe_compute_state *cso) { struct si_context *sctx = (struct si_context *)ctx; struct si_screen *sscreen = (struct si_screen *)ctx->screen; struct si_compute *program = CALLOC_STRUCT(si_compute); struct si_shader *shader = &program->shader; program->ir_type = cso->ir_type; program->local_size = cso->req_local_mem; program->private_size = cso->req_private_mem; program->input_size = cso->req_input_mem; program->use_code_object_v2 = HAVE_LLVM >= 0x0400 && cso->ir_type == PIPE_SHADER_IR_NATIVE; if (cso->ir_type == PIPE_SHADER_IR_TGSI) { struct si_shader_selector sel; bool scratch_enabled; memset(&sel, 0, sizeof(sel)); sel.tokens = tgsi_dup_tokens(cso->prog); if (!sel.tokens) { FREE(program); return NULL; } tgsi_scan_shader(cso->prog, &sel.info); sel.type = PIPE_SHADER_COMPUTE; sel.local_size = cso->req_local_mem; p_atomic_inc(&sscreen->b.num_shaders_created); program->shader.selector = &sel; if (si_shader_create(sscreen, sctx->tm, &program->shader, &sctx->b.debug)) { FREE(sel.tokens); FREE(program); return NULL; } scratch_enabled = shader->config.scratch_bytes_per_wave > 0; shader->config.rsrc1 = S_00B848_VGPRS((shader->config.num_vgprs - 1) / 4) | S_00B848_SGPRS((shader->config.num_sgprs - 1) / 8) | S_00B848_DX10_CLAMP(1) | S_00B848_FLOAT_MODE(shader->config.float_mode); shader->config.rsrc2 = S_00B84C_USER_SGPR(SI_CS_NUM_USER_SGPR) | S_00B84C_SCRATCH_EN(scratch_enabled) | S_00B84C_TGID_X_EN(1) | S_00B84C_TGID_Y_EN(1) | S_00B84C_TGID_Z_EN(1) | S_00B84C_TIDIG_COMP_CNT(2) | S_00B84C_LDS_SIZE(shader->config.lds_size); FREE(sel.tokens); } else { const struct pipe_llvm_program_header *header; const char *code; header = cso->prog; code = cso->prog + sizeof(struct pipe_llvm_program_header); radeon_elf_read(code, header->num_bytes, &program->shader.binary); if (program->use_code_object_v2) { const amd_kernel_code_t *code_object = si_compute_get_code_object(program, 0); code_object_to_config(code_object, &program->shader.config); } else { si_shader_binary_read_config(&program->shader.binary, &program->shader.config, 0); } si_shader_dump(sctx->screen, &program->shader, &sctx->b.debug, PIPE_SHADER_COMPUTE, stderr); si_shader_binary_upload(sctx->screen, &program->shader); } return program; }
/** * Detect any direct relationship between the output color */ void lp_build_tgsi_info(const struct tgsi_token *tokens, struct lp_tgsi_info *info) { struct tgsi_parse_context parse; struct analysis_context ctx; unsigned index; unsigned chan; memset(info, 0, sizeof *info); tgsi_scan_shader(tokens, &info->base); memset(&ctx, 0, sizeof ctx); ctx.info = info; tgsi_parse_init(&parse, tokens); while (!tgsi_parse_end_of_tokens(&parse)) { tgsi_parse_token(&parse); switch (parse.FullToken.Token.Type) { case TGSI_TOKEN_TYPE_DECLARATION: break; case TGSI_TOKEN_TYPE_INSTRUCTION: { struct tgsi_full_instruction *inst = &parse.FullToken.FullInstruction; if (inst->Instruction.Opcode == TGSI_OPCODE_END || inst->Instruction.Opcode == TGSI_OPCODE_BGNSUB) { /* We reached the end of main function body. */ goto finished; } analyse_instruction(&ctx, inst); } break; case TGSI_TOKEN_TYPE_IMMEDIATE: { const unsigned size = parse.FullToken.FullImmediate.Immediate.NrTokens - 1; assert(size <= 4); if (ctx.num_imms < Elements(ctx.imm)) { for (chan = 0; chan < size; ++chan) { float value = parse.FullToken.FullImmediate.u[chan].Float; ctx.imm[ctx.num_imms][chan] = value; if (value < 0.0f || value > 1.0f) { info->unclamped_immediates = TRUE; } } ++ctx.num_imms; } } break; case TGSI_TOKEN_TYPE_PROPERTY: break; default: assert(0); } } finished: tgsi_parse_free(&parse); /* * Link the output color values. */ for (index = 0; index < PIPE_MAX_COLOR_BUFS; ++index) { const struct lp_tgsi_channel_info null_output[4]; info->cbuf[index] = null_output; } for (index = 0; index < info->base.num_outputs; ++index) { unsigned semantic_name = info->base.output_semantic_name[index]; unsigned semantic_index = info->base.output_semantic_index[index]; if (semantic_name == TGSI_SEMANTIC_COLOR && semantic_index < PIPE_MAX_COLOR_BUFS) { info->cbuf[semantic_index] = info->output[index]; } } if (gallivm_debug & GALLIVM_DEBUG_TGSI) { dump_info(tokens, info); } }