const struct tgsi_token *ureg_finalize( struct ureg_program *ureg ) { const struct tgsi_token *tokens; emit_header( ureg ); emit_decls( ureg ); copy_instructions( ureg ); fixup_header_size( ureg ); if (ureg->domain[0].tokens == error_tokens || ureg->domain[1].tokens == error_tokens) { debug_printf("%s: error in generated shader\n", __FUNCTION__); assert(0); return NULL; } tokens = &ureg->domain[DOMAIN_DECL].tokens[0].token; if (0) { debug_printf("%s: emitted shader %d tokens:\n", __FUNCTION__, ureg->domain[DOMAIN_DECL].count); tgsi_dump( tokens, 0 ); } #if DEBUG if (tokens && !tgsi_sanity_check(tokens)) { debug_printf("tgsi_ureg.c, sanity check failed on generated tokens:\n"); tgsi_dump(tokens, 0); assert(0); } #endif return tokens; }
/** * Generate the frag shader we'll use for drawing AA lines. * This will be the user's shader plus some texture/modulate instructions. */ static boolean generate_aaline_fs(struct aaline_stage *aaline) { struct pipe_context *pipe = aaline->stage.draw->pipe; const struct pipe_shader_state *orig_fs = &aaline->fs->state; struct pipe_shader_state aaline_fs; struct aa_transform_context transform; const uint newLen = tgsi_num_tokens(orig_fs->tokens) + NUM_NEW_TOKENS; aaline_fs = *orig_fs; /* copy to init */ aaline_fs.tokens = tgsi_alloc_tokens(newLen); if (aaline_fs.tokens == NULL) return FALSE; memset(&transform, 0, sizeof(transform)); transform.colorOutput = -1; transform.maxInput = -1; transform.maxGeneric = -1; transform.colorTemp = -1; transform.texTemp = -1; transform.base.prolog = aa_transform_prolog; transform.base.epilog = aa_transform_epilog; transform.base.transform_instruction = aa_transform_inst; transform.base.transform_declaration = aa_transform_decl; tgsi_transform_shader(orig_fs->tokens, (struct tgsi_token *) aaline_fs.tokens, newLen, &transform.base); #if 0 /* DEBUG */ debug_printf("draw_aaline, orig shader:\n"); tgsi_dump(orig_fs->tokens, 0); debug_printf("draw_aaline, new shader:\n"); tgsi_dump(aaline_fs.tokens, 0); #endif aaline->fs->sampler_unit = transform.freeSampler; aaline->fs->aaline_fs = aaline->driver_create_fs_state(pipe, &aaline_fs); if (aaline->fs->aaline_fs == NULL) goto fail; aaline->fs->generic_attrib = transform.maxGeneric + 1; FREE((void *)aaline_fs.tokens); return TRUE; fail: FREE((void *)aaline_fs.tokens); return FALSE; }
/** * Make simple fragment color pass-through shader that replicates OUT[0] * to all bound colorbuffers. */ void * util_make_fragment_passthrough_shader(struct pipe_context *pipe, int input_semantic, int input_interpolate, boolean write_all_cbufs) { static const char shader_templ[] = "FRAG\n" "%s" "DCL IN[0], %s[0], %s\n" "DCL OUT[0], COLOR[0]\n" "MOV OUT[0], IN[0]\n" "END\n"; char text[sizeof(shader_templ)+100]; struct tgsi_token tokens[1000]; struct pipe_shader_state state; sprintf(text, shader_templ, write_all_cbufs ? "PROPERTY FS_COLOR0_WRITES_ALL_CBUFS 1\n" : "", tgsi_semantic_names[input_semantic], tgsi_interpolate_names[input_interpolate]); if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) { assert(0); return NULL; } pipe_shader_state_from_tgsi(&state, tokens); #if 0 tgsi_dump(state.tokens, 0); #endif return pipe->create_fs_state(pipe, &state); }
void i915_translate_fragment_program( struct i915_context *i915, struct i915_fragment_shader *fs) { struct i915_fp_compile *p; const struct tgsi_token *tokens = fs->state.tokens; struct i915_token_list* i_tokens; #if 0 tgsi_dump(tokens, 0); #endif /* hw doesn't seem to like empty frag programs, even when the depth write * fixup gets emitted below - may that one is fishy, too? */ if (fs->info.num_instructions == 1) { i915_use_passthrough_shader(fs); return; } p = i915_init_compile(i915, fs); i_tokens = i915_optimize(tokens); i915_translate_instructions(p, i_tokens, fs); i915_fixup_depth_write(p); i915_fini_compile(i915, p); i915_optimize_free(i_tokens); #if 0 i915_disassemble_program(NULL, fs->program, fs->program_len); #endif }
static void * llvmpipe_create_gs_state(struct pipe_context *pipe, const struct pipe_shader_state *templ) { struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); struct lp_geometry_shader *state; state = CALLOC_STRUCT(lp_geometry_shader); if (!state) goto no_state; /* debug */ if (LP_DEBUG & DEBUG_TGSI) { debug_printf("llvmpipe: Create geometry shader %p:\n", (void *)state); tgsi_dump(templ->tokens, 0); } /* copy stream output info */ state->no_tokens = !templ->tokens; memcpy(&state->stream_output, &templ->stream_output, sizeof state->stream_output); if (templ->tokens) { state->dgs = draw_create_geometry_shader(llvmpipe->draw, templ); if (state->dgs == NULL) { goto no_dgs; } } return state; no_dgs: FREE( state ); no_state: return NULL; }
/** * Translate the TGSI tokens. */ static bool vs_setup_tgsi(struct toy_compiler *tc, const struct tgsi_token *tokens, struct toy_tgsi *tgsi) { if (ilo_debug & ILO_DEBUG_VS) { ilo_printf("dumping vertex shader\n"); ilo_printf("\n"); tgsi_dump(tokens, 0); ilo_printf("\n"); } toy_compiler_translate_tgsi(tc, tokens, true, tgsi); if (tc->fail) { ilo_err("failed to translate VS TGSI tokens: %s\n", tc->reason); return false; } if (ilo_debug & ILO_DEBUG_VS) { ilo_printf("TGSI translator:\n"); toy_tgsi_dump(tgsi); ilo_printf("\n"); toy_compiler_dump(tc); ilo_printf("\n"); } return true; }
/** * Translate the TGSI tokens. */ static bool gs_setup_tgsi(struct toy_compiler *tc, const struct tgsi_token *tokens, struct toy_tgsi *tgsi) { if (ilo_debug & ILO_DEBUG_GS) { ilo_printf("dumping geometry shader\n"); ilo_printf("\n"); tgsi_dump(tokens, 0); ilo_printf("\n"); } toy_compiler_translate_tgsi(tc, tokens, true, tgsi); if (tc->fail) return false; if (ilo_debug & ILO_DEBUG_GS) { ilo_printf("TGSI translator:\n"); toy_tgsi_dump(tgsi); ilo_printf("\n"); toy_compiler_dump(tc); ilo_printf("\n"); } return true; }
struct ir3_shader * ir3_shader_create(struct ir3_compiler *compiler, const struct pipe_shader_state *cso, gl_shader_stage type, struct pipe_debug_callback *debug, struct pipe_screen *screen) { nir_shader *nir; if (cso->type == PIPE_SHADER_IR_NIR) { /* we take ownership of the reference: */ nir = cso->ir.nir; } else { debug_assert(cso->type == PIPE_SHADER_IR_TGSI); if (ir3_shader_debug & IR3_DBG_DISASM) { tgsi_dump(cso->tokens, 0); } nir = tgsi_to_nir(cso->tokens, screen); } struct ir3_shader *shader = ir3_shader_from_nir(compiler, nir); copy_stream_out(&shader->stream_output, &cso->stream_output); if (fd_mesa_debug & FD_DBG_SHADERDB) { /* if shader-db run, create a standard variant immediately * (as otherwise nothing will trigger the shader to be * actually compiled) */ static struct ir3_shader_key key; memset(&key, 0, sizeof(key)); ir3_shader_variant(shader, key, false, debug); } return shader; }
static struct fd2_shader_stateobj * compile(struct fd_program_stateobj *prog, struct fd2_shader_stateobj *so) { int ret; if (fd_mesa_debug & FD_DBG_DISASM) { DBG("dump tgsi: type=%d", so->type); tgsi_dump(so->tokens, 0); } ret = fd2_compile_shader(prog, so); if (ret) goto fail; /* NOTE: we don't assemble yet because for VS we don't know the * type information for vertex fetch yet.. so those need to be * patched up later before assembling. */ so->info.sizedwords = 0; return so; fail: debug_error("compile failed!"); delete_shader(so); return NULL; }
static void shader_info(struct rbug_connection *con, rbug_context_t ctx) { struct rbug_header *header; struct rbug_proto_shader_list_reply *list; struct rbug_proto_shader_info_reply *info; int i; debug_printf("Sending get shaders to %llu\n", (unsigned long long)ctx); rbug_send_shader_list(con, ctx, NULL); debug_printf("Waiting for shaders from %llu\n", (unsigned long long)ctx); header = rbug_get_message(con, NULL); assert(header->opcode == RBUG_OP_SHADER_LIST_REPLY); list = (struct rbug_proto_shader_list_reply *)header; debug_printf("Got shaders:\n"); for (i = 0; i < list->shaders_len; i++) { rbug_send_shader_info(con, ctx, list->shaders[i], NULL); header = rbug_get_message(con, NULL); assert(header->opcode == RBUG_OP_SHADER_INFO_REPLY); info = (struct rbug_proto_shader_info_reply *)header; debug_printf("#####################################################\n"); debug_printf("ctx: %llu shdr: %llu disabled %u\n", (unsigned long long)ctx, (unsigned long long)list->shaders[i], info->disabled); /* just to be sure */ assert(sizeof(struct tgsi_token) == 4); debug_printf("-----------------------------------------------------\n"); tgsi_dump((struct tgsi_token *)info->original, 0); if (info->replaced_len > 0) { debug_printf("-----------------------------------------------------\n"); tgsi_dump((struct tgsi_token *)info->replaced, 0); } rbug_free_header(header); } debug_printf("#####################################################\n"); rbug_free_header(&list->header); }
void lp_debug_fs_variant(const struct lp_fragment_shader_variant *variant) { debug_printf("llvmpipe: Fragment shader #%u variant #%u:\n", variant->shader->no, variant->no); tgsi_dump(variant->shader->base.tokens, 0); dump_fs_variant_key(&variant->key); debug_printf("variant->opaque = %u\n", variant->opaque); debug_printf("\n"); }
/** * Generate the frag shader we'll use for drawing AA lines. * This will be the user's shader plus some texture/modulate instructions. */ static boolean generate_aaline_fs(struct aaline_stage *aaline) { const struct pipe_shader_state *orig_fs = &aaline->fs->state; struct pipe_shader_state aaline_fs; struct aa_transform_context transform; #define MAX 1000 aaline_fs = *orig_fs; /* copy to init */ aaline_fs.tokens = MALLOC(sizeof(struct tgsi_token) * MAX); if (aaline_fs.tokens == NULL) return FALSE; memset(&transform, 0, sizeof(transform)); transform.colorOutput = -1; transform.maxInput = -1; transform.maxGeneric = -1; transform.colorTemp = -1; transform.texTemp = -1; transform.firstInstruction = TRUE; transform.base.transform_instruction = aa_transform_inst; transform.base.transform_declaration = aa_transform_decl; tgsi_transform_shader(orig_fs->tokens, (struct tgsi_token *) aaline_fs.tokens, MAX, &transform.base); #if 0 /* DEBUG */ tgsi_dump(orig_fs->tokens, 0); tgsi_dump(aaline_fs.tokens, 0); #endif aaline->fs->sampler_unit = transform.freeSampler; aaline->fs->aaline_fs = aaline->driver_create_fs_state(aaline->pipe, &aaline_fs); if (aaline->fs->aaline_fs == NULL) return FALSE; aaline->fs->generic_attrib = transform.maxGeneric + 1; return TRUE; }
int main(int argc, char **argv) { if(argc < 2) { fprintf(stderr, "Must pass shader source name as argument\n"); exit(1); } const char *text = load_text_file(argv[1]); if(!text) { fprintf(stderr, "Unable to open %s\n", argv[1]); exit(1); } struct tgsi_token tokens[1024]; if(tgsi_text_translate(text, tokens, Elements(tokens))) { tgsi_dump(tokens, 0); union { struct tgsi_header h; struct tgsi_token t; } hdr; hdr.t = tokens[0]; printf("Header size: %i\n", hdr.h.HeaderSize); printf("Body size: %i\n", hdr.h.BodySize); int totalSize = hdr.h.HeaderSize + hdr.h.BodySize; for(int i=0; i<totalSize; ++i) { printf("%08x ", *((uint32_t*)&tokens[i])); } printf("\n"); /* Parsing test */ struct tgsi_parse_context ctx = {}; unsigned status = TGSI_PARSE_OK; status = tgsi_parse_init(&ctx, tokens); assert(status == TGSI_PARSE_OK); while(!tgsi_parse_end_of_tokens(&ctx)) { tgsi_parse_token(&ctx); /* declaration / immediate / instruction / property */ printf("Parsed token! %i\n", ctx.FullToken.Token.Type); } tgsi_parse_free(&ctx); } else { fprintf(stderr, "Unable to parse %s\n", argv[1]); } return 0; }
static struct fd3_shader_stateobj * create_shader(struct pipe_context *pctx, const struct pipe_shader_state *cso, enum shader_t type) { struct fd3_shader_stateobj *so = CALLOC_STRUCT(fd3_shader_stateobj); int ret; if (!so) return NULL; so->type = type; if (fd_mesa_debug & FD_DBG_DISASM) { DBG("dump tgsi: type=%d", so->type); tgsi_dump(cso->tokens, 0); } if (type == SHADER_FRAGMENT) { /* we seem to get wrong colors (maybe swap/endianess or hw issue?) * with full precision color reg. And blob driver only seems to * use half precision register for color output (that I can find * so far), even with highp precision. So for force half precision * for frag shader: */ so->half_precision = true; } ret = fd3_compile_shader(so, cso->tokens); if (ret) { debug_error("compile failed!"); goto fail; } assemble_shader(pctx, so); if (!so->bo) { debug_error("assemble failed!"); goto fail; } if (type == SHADER_VERTEX) fixup_vp_regfootprint(so); if (fd_mesa_debug & FD_DBG_DISASM) { DBG("disassemble: type=%d", so->type); disasm_a3xx(fd_bo_map(so->bo), so->info.sizedwords, 0, so->type); } return so; fail: delete_shader(so); return NULL; }
static INLINE struct tgsi_token *tokens_from_assembly(const char *txt, int num_tokens) { struct tgsi_token *tokens; tokens = (struct tgsi_token *) MALLOC(num_tokens * sizeof(tokens[0])); tgsi_text_translate(txt, tokens, num_tokens); #if DEBUG_SHADERS tgsi_dump(tokens, 0); #endif return tokens; }
/** * Print current state. May be called from inside gdb to see currently * bound vertex/fragment shaders and associated constants. */ void st_print_current(void) { GET_CURRENT_CONTEXT(ctx); struct st_context *st = ctx->st; #if 0 int i; printf("Vertex Transform Inputs:\n"); for (i = 0; i < st->vp->state.num_inputs; i++) { printf(" Slot %d: VERT_ATTRIB_%d\n", i, st->vp->index_to_input[i]); } #endif tgsi_dump( st->vp->state.tokens, 0 ); if (st->vp->Base.Base.Parameters) _mesa_print_parameter_list(st->vp->Base.Base.Parameters); tgsi_dump( st->fp->state.tokens, 0 ); if (st->fp->Base.Base.Parameters) _mesa_print_parameter_list(st->fp->Base.Base.Parameters); }
void r300_translate_vertex_shader(struct r300_context* r300, struct r300_vertex_shader* vs) { struct r300_vertex_program_compiler compiler; struct tgsi_to_rc ttr; /* Initialize. */ r300_shader_read_vs_outputs(&vs->info, &vs->outputs); /* Setup the compiler */ rc_init(&compiler.Base); compiler.Base.Debug = DBG_ON(r300, DBG_VP); compiler.code = &vs->code; compiler.UserData = vs; if (compiler.Base.Debug) { debug_printf("r300: Initial vertex program\n"); tgsi_dump(vs->state.tokens, 0); } /* Translate TGSI to our internal representation */ ttr.compiler = &compiler.Base; ttr.info = &vs->info; ttr.use_half_swizzles = FALSE; r300_tgsi_to_rc(&ttr, vs->state.tokens); compiler.RequiredOutputs = ~(~0 << (vs->info.num_outputs+1)); compiler.SetHwInputOutput = &set_vertex_inputs_outputs; /* Insert the WPOS output. */ r300_insert_wpos(&compiler, &vs->outputs); r300_shader_vap_output_fmt(vs); r300_stream_locations_notcl(&vs->outputs, vs->stream_loc_notcl); /* Invoke the compiler */ r3xx_compile_vertex_program(&compiler); if (compiler.Base.Error) { /* XXX We should fallback using Draw. */ fprintf(stderr, "r300 VP: Compiler error\n"); abort(); } /* And, finally... */ rc_destroy(&compiler.Base); vs->translated = TRUE; }
void r300_translate_fragment_shader(struct r300_context* r300, struct r300_fragment_shader* fs) { struct r300_fragment_program_compiler compiler; struct tgsi_to_rc ttr; memset(&compiler, 0, sizeof(compiler)); rc_init(&compiler.Base); compiler.Base.Debug = DBG_ON(r300, DBG_FP); compiler.code = &fs->code; compiler.is_r500 = r300_screen(r300->context.screen)->caps->is_r500; compiler.AllocateHwInputs = &allocate_hardware_inputs; compiler.UserData = fs; /* TODO: Program compilation depends on texture compare modes, * which are sampler state. Therefore, programs need to be recompiled * depending on this state as in the classic Mesa driver. * * This is not yet handled correctly. */ find_output_registers(&compiler, fs); if (compiler.Base.Debug) { debug_printf("r300: Initial fragment program\n"); tgsi_dump(fs->state.tokens, 0); } /* Translate TGSI to our internal representation */ ttr.compiler = &compiler.Base; ttr.info = &fs->info; r300_tgsi_to_rc(&ttr, fs->state.tokens); /* Invoke the compiler */ r3xx_compile_fragment_program(&compiler); if (compiler.Base.Error) { /* XXX failover maybe? */ DBG(r300, DBG_FP, "r300: Error compiling fragment program: %s\n", compiler.Base.ErrorMsg); } /* And, finally... */ rc_destroy(&compiler.Base); fs->translated = TRUE; }
static void * util_make_fs_blit_msaa_gen(struct pipe_context *pipe, enum tgsi_texture_type tgsi_tex, const char *samp_type, const char *output_semantic, const char *output_mask, const char *conversion_decl, const char *conversion) { static const char shader_templ[] = "FRAG\n" "DCL IN[0], GENERIC[0], LINEAR\n" "DCL SAMP[0]\n" "DCL SVIEW[0], %s, %s\n" "DCL OUT[0], %s\n" "DCL TEMP[0]\n" "%s" "F2U TEMP[0], IN[0]\n" "TXF TEMP[0], TEMP[0], SAMP[0], %s\n" "%s" "MOV OUT[0]%s, TEMP[0]\n" "END\n"; const char *type = tgsi_texture_names[tgsi_tex]; char text[sizeof(shader_templ)+100]; struct tgsi_token tokens[1000]; struct pipe_shader_state state; assert(tgsi_tex == TGSI_TEXTURE_2D_MSAA || tgsi_tex == TGSI_TEXTURE_2D_ARRAY_MSAA); util_snprintf(text, sizeof(text), shader_templ, type, samp_type, output_semantic, conversion_decl, type, conversion, output_mask); if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) { puts(text); assert(0); return NULL; } pipe_shader_state_from_tgsi(&state, tokens); #if 0 tgsi_dump(state.tokens, 0); #endif return pipe->create_fs_state(pipe, &state); }
/** * For debugging, print/dump the current vertex program. */ void st_print_current_vertex_program(void) { GET_CURRENT_CONTEXT(ctx); if (ctx->VertexProgram._Current) { struct st_vertex_program *stvp = (struct st_vertex_program *) ctx->VertexProgram._Current; struct st_vp_variant *stv; debug_printf("Vertex program %u\n", stvp->Base.Base.Id); for (stv = stvp->variants; stv; stv = stv->next) { debug_printf("variant %p\n", stv); tgsi_dump(stv->tgsi.tokens, 0); } } }
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 * llvmpipe_create_vs_state(struct pipe_context *pipe, const struct pipe_shader_state *templ) { struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); struct draw_vertex_shader *vs; vs = draw_create_vertex_shader(llvmpipe->draw, templ); if (vs == NULL) { return NULL; } if (LP_DEBUG & DEBUG_TGSI) { debug_printf("llvmpipe: Create vertex shader %p:\n", (void *) vs); tgsi_dump(templ->tokens, 0); } return vs; }
/* a bit annoying that compute-shader and normal shader state objects * aren't a bit more aligned. */ struct ir3_shader * ir3_shader_create_compute(struct ir3_compiler *compiler, const struct pipe_compute_state *cso, struct pipe_debug_callback *debug, struct pipe_screen *screen) { nir_shader *nir; if (cso->ir_type == PIPE_SHADER_IR_NIR) { /* we take ownership of the reference: */ nir = (nir_shader *)cso->prog; } else { debug_assert(cso->ir_type == PIPE_SHADER_IR_TGSI); if (ir3_shader_debug & IR3_DBG_DISASM) { tgsi_dump(cso->prog, 0); } nir = tgsi_to_nir(cso->prog, screen); } struct ir3_shader *shader = ir3_shader_from_nir(compiler, nir); return shader; }
/** * Make a fragment shader that sets the output depth and stencil to depth * and stencil values fetched from two multisample textures / samplers. * The sizes of both textures should match (it should be one depth-stencil * texture). * \param tex_target one of PIPE_TEXTURE_x */ void * util_make_fs_blit_msaa_depthstencil(struct pipe_context *pipe, enum tgsi_texture_type tgsi_tex) { static const char shader_templ[] = "FRAG\n" "DCL IN[0], GENERIC[0], LINEAR\n" "DCL SAMP[0..1]\n" "DCL SVIEW[0..1], %s, FLOAT\n" "DCL OUT[0], POSITION\n" "DCL OUT[1], STENCIL\n" "DCL TEMP[0]\n" "F2U TEMP[0], IN[0]\n" "TXF OUT[0].z, TEMP[0], SAMP[0], %s\n" "TXF OUT[1].y, TEMP[0], SAMP[1], %s\n" "END\n"; const char *type = tgsi_texture_names[tgsi_tex]; char text[sizeof(shader_templ)+100]; struct tgsi_token tokens[1000]; struct pipe_shader_state state; assert(tgsi_tex == TGSI_TEXTURE_2D_MSAA || tgsi_tex == TGSI_TEXTURE_2D_ARRAY_MSAA); sprintf(text, shader_templ, type, type, type); if (!tgsi_text_translate(text, tokens, ARRAY_SIZE(tokens))) { assert(0); return NULL; } pipe_shader_state_from_tgsi(&state, tokens); #if 0 tgsi_dump(state.tokens, 0); #endif return pipe->create_fs_state(pipe, &state); }
static void * llvmpipe_create_gs_state(struct pipe_context *pipe, const struct pipe_shader_state *templ) { struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); struct lp_geometry_shader *state; state = CALLOC_STRUCT(lp_geometry_shader); if (state == NULL ) goto fail; /* debug */ if (0) tgsi_dump(templ->tokens, 0); /* copy stream output info */ state->shader = *templ; if (templ->tokens) { /* copy shader tokens, the ones passed in will go away. */ state->shader.tokens = tgsi_dup_tokens(templ->tokens); if (state->shader.tokens == NULL) goto fail; state->draw_data = draw_create_geometry_shader(llvmpipe->draw, templ); if (state->draw_data == NULL) goto fail; } return state; fail: if (state) { FREE( (void *)state->shader.tokens ); FREE( state->draw_data ); FREE( state ); } return NULL; }
static void * util_make_fs_blit_msaa_gen(struct pipe_context *pipe, unsigned tgsi_tex, const char *output_semantic, const char *output_mask) { static const char shader_templ[] = "FRAG\n" "DCL IN[0], GENERIC[0], LINEAR\n" "DCL SAMP[0]\n" "DCL OUT[0], %s\n" "DCL TEMP[0]\n" "F2U TEMP[0], IN[0]\n" "TXF OUT[0]%s, TEMP[0], SAMP[0], %s\n" "END\n"; const char *type = tgsi_texture_names[tgsi_tex]; char text[sizeof(shader_templ)+100]; struct tgsi_token tokens[1000]; struct pipe_shader_state state = {tokens}; assert(tgsi_tex == TGSI_TEXTURE_2D_MSAA || tgsi_tex == TGSI_TEXTURE_2D_ARRAY_MSAA); sprintf(text, shader_templ, output_semantic, output_mask, type); if (!tgsi_text_translate(text, tokens, Elements(tokens))) { puts(text); assert(0); return NULL; } #if 0 tgsi_dump(state.tokens, 0); #endif return pipe->create_fs_state(pipe, &state); }
static void * llvmpipe_create_vs_state(struct pipe_context *pipe, const struct pipe_shader_state *templ) { struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); struct lp_vertex_shader *state; state = CALLOC_STRUCT(lp_vertex_shader); if (state == NULL ) goto fail; /* copy shader tokens, the ones passed in will go away. */ state->shader.tokens = tgsi_dup_tokens(templ->tokens); if (state->shader.tokens == NULL) goto fail; state->draw_data = draw_create_vertex_shader(llvmpipe->draw, templ); if (state->draw_data == NULL) goto fail; if (LP_DEBUG & DEBUG_TGSI) { debug_printf("llvmpipe: Create vertex shader %p:\n", (void *) state); tgsi_dump(templ->tokens, 0); } return state; fail: if (state) { FREE( (void *)state->shader.tokens ); FREE( state->draw_data ); FREE( state ); } return NULL; }
void lp_build_tgsi_aos(struct gallivm_state *gallivm, const struct tgsi_token *tokens, struct lp_type type, const unsigned char swizzles[4], LLVMValueRef consts_ptr, const LLVMValueRef *inputs, LLVMValueRef *outputs, struct lp_build_sampler_aos *sampler, const struct tgsi_shader_info *info) { struct lp_build_tgsi_aos_context bld; struct tgsi_parse_context parse; uint num_immediates = 0; unsigned chan; int pc = 0; /* Setup build context */ memset(&bld, 0, sizeof bld); lp_build_context_init(&bld.bld_base.base, gallivm, type); lp_build_context_init(&bld.bld_base.uint_bld, gallivm, lp_uint_type(type)); lp_build_context_init(&bld.bld_base.int_bld, gallivm, lp_int_type(type)); lp_build_context_init(&bld.int_bld, gallivm, lp_int_type(type)); for (chan = 0; chan < 4; ++chan) { bld.swizzles[chan] = swizzles[chan]; bld.inv_swizzles[swizzles[chan]] = chan; } bld.inputs = inputs; bld.outputs = outputs; bld.consts_ptr = consts_ptr; bld.sampler = sampler; bld.indirect_files = info->indirect_files; bld.bld_base.emit_swizzle = swizzle_aos; bld.bld_base.info = info; bld.bld_base.emit_fetch_funcs[TGSI_FILE_CONSTANT] = emit_fetch_constant; bld.bld_base.emit_fetch_funcs[TGSI_FILE_IMMEDIATE] = emit_fetch_immediate; bld.bld_base.emit_fetch_funcs[TGSI_FILE_INPUT] = emit_fetch_input; bld.bld_base.emit_fetch_funcs[TGSI_FILE_TEMPORARY] = emit_fetch_temporary; /* Set opcode actions */ lp_set_default_actions_cpu(&bld.bld_base); if (!lp_bld_tgsi_list_init(&bld.bld_base)) { return; } 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: /* Inputs already interpolated */ lp_emit_declaration_aos(&bld, &parse.FullToken.FullDeclaration); break; case TGSI_TOKEN_TYPE_INSTRUCTION: /* save expanded instruction */ lp_bld_tgsi_add_instruction(&bld.bld_base, &parse.FullToken.FullInstruction); break; case TGSI_TOKEN_TYPE_IMMEDIATE: /* simply copy the immediate values into the next immediates[] slot */ { const uint size = parse.FullToken.FullImmediate.Immediate.NrTokens - 1; float imm[4]; assert(size <= 4); assert(num_immediates < LP_MAX_TGSI_IMMEDIATES); for (chan = 0; chan < 4; ++chan) { imm[chan] = 0.0f; } for (chan = 0; chan < size; ++chan) { unsigned swizzle = bld.swizzles[chan]; imm[swizzle] = parse.FullToken.FullImmediate.u[chan].Float; } bld.immediates[num_immediates] = lp_build_const_aos(gallivm, type, imm[0], imm[1], imm[2], imm[3], NULL); num_immediates++; } break; case TGSI_TOKEN_TYPE_PROPERTY: break; default: assert(0); } } while (pc != -1) { struct tgsi_full_instruction *instr = bld.bld_base.instructions + pc; const struct tgsi_opcode_info *opcode_info = tgsi_get_opcode_info(instr->Instruction.Opcode); if (!lp_emit_instruction_aos(&bld, instr, opcode_info, &pc)) _debug_printf("warning: failed to translate tgsi opcode %s to LLVM\n", opcode_info->mnemonic); } if (0) { LLVMBasicBlockRef block = LLVMGetInsertBlock(gallivm->builder); LLVMValueRef function = LLVMGetBasicBlockParent(block); debug_printf("11111111111111111111111111111 \n"); tgsi_dump(tokens, 0); lp_debug_dump_value(function); debug_printf("2222222222222222222222222222 \n"); } tgsi_parse_free(&parse); FREE(bld.bld_base.instructions); if (0) { LLVMModuleRef module = LLVMGetGlobalParent( LLVMGetBasicBlockParent(LLVMGetInsertBlock(gallivm->builder))); LLVMDumpModule(module); } }
static INLINE void dump_info(const struct tgsi_token *tokens, struct lp_tgsi_info *info) { unsigned index; unsigned chan; tgsi_dump(tokens, 0); for (index = 0; index < info->num_texs; ++index) { const struct lp_tgsi_texture_info *tex_info = &info->tex[index]; debug_printf("TEX[%u] =", index); for (chan = 0; chan < 4; ++chan) { const struct lp_tgsi_channel_info *chan_info = &tex_info->coord[chan]; if (chan_info->file != TGSI_FILE_NULL) { debug_printf(" %s[%u].%c", tgsi_file_name(chan_info->file), chan_info->u.index, "xyzw01"[chan_info->swizzle]); } else { debug_printf(" _"); } } debug_printf(", RES[%u], SAMP[%u], %s\n", tex_info->texture_unit, tex_info->sampler_unit, tgsi_texture_names[tex_info->target]); } for (index = 0; index < PIPE_MAX_SHADER_OUTPUTS; ++index) { for (chan = 0; chan < 4; ++chan) { const struct lp_tgsi_channel_info *chan_info = &info->output[index][chan]; if (chan_info->file != TGSI_FILE_NULL) { debug_printf("OUT[%u].%c = ", index, "xyzw"[chan]); if (chan_info->file == TGSI_FILE_IMMEDIATE) { debug_printf("%f", chan_info->u.value); } else { const char *file_name; switch (chan_info->file) { case TGSI_FILE_CONSTANT: file_name = "CONST"; break; case TGSI_FILE_INPUT: file_name = "IN"; break; default: file_name = "???"; break; } debug_printf("%s[%u].%c", file_name, chan_info->u.index, "xyzw01"[chan_info->swizzle]); } debug_printf("\n"); } } } }
/** * Translate a geometry program to create a new variant. */ static struct st_gp_variant * st_translate_geometry_program(struct st_context *st, struct st_geometry_program *stgp, const struct st_gp_variant_key *key) { GLuint inputMapping[VARYING_SLOT_MAX]; GLuint outputMapping[VARYING_SLOT_MAX]; struct pipe_context *pipe = st->pipe; GLuint attr; uint gs_num_inputs = 0; ubyte input_semantic_name[PIPE_MAX_SHADER_INPUTS]; ubyte input_semantic_index[PIPE_MAX_SHADER_INPUTS]; ubyte gs_output_semantic_name[PIPE_MAX_SHADER_OUTPUTS]; ubyte gs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS]; uint gs_num_outputs = 0; GLint i; struct ureg_program *ureg; struct pipe_shader_state state = {0}; struct st_gp_variant *gpv; gpv = CALLOC_STRUCT(st_gp_variant); if (!gpv) return NULL; ureg = ureg_create(TGSI_PROCESSOR_GEOMETRY); if (ureg == NULL) { free(gpv); return NULL; } memset(inputMapping, 0, sizeof(inputMapping)); memset(outputMapping, 0, sizeof(outputMapping)); /* * Convert Mesa program inputs to TGSI input register semantics. */ for (attr = 0; attr < VARYING_SLOT_MAX; attr++) { if ((stgp->Base.Base.InputsRead & BITFIELD64_BIT(attr)) != 0) { const GLuint slot = gs_num_inputs++; inputMapping[attr] = slot; switch (attr) { case VARYING_SLOT_PRIMITIVE_ID: input_semantic_name[slot] = TGSI_SEMANTIC_PRIMID; input_semantic_index[slot] = 0; break; case VARYING_SLOT_POS: input_semantic_name[slot] = TGSI_SEMANTIC_POSITION; input_semantic_index[slot] = 0; break; case VARYING_SLOT_COL0: input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; input_semantic_index[slot] = 0; break; case VARYING_SLOT_COL1: input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; input_semantic_index[slot] = 1; break; case VARYING_SLOT_FOGC: input_semantic_name[slot] = TGSI_SEMANTIC_FOG; input_semantic_index[slot] = 0; break; case VARYING_SLOT_CLIP_VERTEX: input_semantic_name[slot] = TGSI_SEMANTIC_CLIPVERTEX; input_semantic_index[slot] = 0; break; case VARYING_SLOT_CLIP_DIST0: input_semantic_name[slot] = TGSI_SEMANTIC_CLIPDIST; input_semantic_index[slot] = 0; break; case VARYING_SLOT_CLIP_DIST1: input_semantic_name[slot] = TGSI_SEMANTIC_CLIPDIST; input_semantic_index[slot] = 1; break; case VARYING_SLOT_PSIZ: input_semantic_name[slot] = TGSI_SEMANTIC_PSIZE; input_semantic_index[slot] = 0; break; case VARYING_SLOT_TEX0: case VARYING_SLOT_TEX1: case VARYING_SLOT_TEX2: case VARYING_SLOT_TEX3: case VARYING_SLOT_TEX4: case VARYING_SLOT_TEX5: case VARYING_SLOT_TEX6: case VARYING_SLOT_TEX7: if (st->needs_texcoord_semantic) { input_semantic_name[slot] = TGSI_SEMANTIC_TEXCOORD; input_semantic_index[slot] = attr - VARYING_SLOT_TEX0; break; } /* fall through */ case VARYING_SLOT_VAR0: default: assert(attr >= VARYING_SLOT_VAR0 && attr < VARYING_SLOT_MAX); input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; input_semantic_index[slot] = st_get_generic_varying_index(st, attr); break; } } } /* initialize output semantics to defaults */ for (i = 0; i < PIPE_MAX_SHADER_OUTPUTS; i++) { gs_output_semantic_name[i] = TGSI_SEMANTIC_GENERIC; gs_output_semantic_index[i] = 0; } /* * Determine number of outputs, the (default) output register * mapping and the semantic information for each output. */ for (attr = 0; attr < VARYING_SLOT_MAX; attr++) { if (stgp->Base.Base.OutputsWritten & BITFIELD64_BIT(attr)) { GLuint slot = gs_num_outputs++; outputMapping[attr] = slot; switch (attr) { case VARYING_SLOT_POS: assert(slot == 0); gs_output_semantic_name[slot] = TGSI_SEMANTIC_POSITION; gs_output_semantic_index[slot] = 0; break; case VARYING_SLOT_COL0: gs_output_semantic_name[slot] = TGSI_SEMANTIC_COLOR; gs_output_semantic_index[slot] = 0; break; case VARYING_SLOT_COL1: gs_output_semantic_name[slot] = TGSI_SEMANTIC_COLOR; gs_output_semantic_index[slot] = 1; break; case VARYING_SLOT_BFC0: gs_output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR; gs_output_semantic_index[slot] = 0; break; case VARYING_SLOT_BFC1: gs_output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR; gs_output_semantic_index[slot] = 1; break; case VARYING_SLOT_FOGC: gs_output_semantic_name[slot] = TGSI_SEMANTIC_FOG; gs_output_semantic_index[slot] = 0; break; case VARYING_SLOT_PSIZ: gs_output_semantic_name[slot] = TGSI_SEMANTIC_PSIZE; gs_output_semantic_index[slot] = 0; break; case VARYING_SLOT_CLIP_VERTEX: gs_output_semantic_name[slot] = TGSI_SEMANTIC_CLIPVERTEX; gs_output_semantic_index[slot] = 0; break; case VARYING_SLOT_CLIP_DIST0: gs_output_semantic_name[slot] = TGSI_SEMANTIC_CLIPDIST; gs_output_semantic_index[slot] = 0; break; case VARYING_SLOT_CLIP_DIST1: gs_output_semantic_name[slot] = TGSI_SEMANTIC_CLIPDIST; gs_output_semantic_index[slot] = 1; break; case VARYING_SLOT_LAYER: gs_output_semantic_name[slot] = TGSI_SEMANTIC_LAYER; gs_output_semantic_index[slot] = 0; break; case VARYING_SLOT_PRIMITIVE_ID: gs_output_semantic_name[slot] = TGSI_SEMANTIC_PRIMID; gs_output_semantic_index[slot] = 0; break; case VARYING_SLOT_VIEWPORT: gs_output_semantic_name[slot] = TGSI_SEMANTIC_VIEWPORT_INDEX; gs_output_semantic_index[slot] = 0; break; case VARYING_SLOT_TEX0: case VARYING_SLOT_TEX1: case VARYING_SLOT_TEX2: case VARYING_SLOT_TEX3: case VARYING_SLOT_TEX4: case VARYING_SLOT_TEX5: case VARYING_SLOT_TEX6: case VARYING_SLOT_TEX7: if (st->needs_texcoord_semantic) { gs_output_semantic_name[slot] = TGSI_SEMANTIC_TEXCOORD; gs_output_semantic_index[slot] = attr - VARYING_SLOT_TEX0; break; } /* fall through */ case VARYING_SLOT_VAR0: default: assert(slot < ARRAY_SIZE(gs_output_semantic_name)); assert(attr >= VARYING_SLOT_VAR0); gs_output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; gs_output_semantic_index[slot] = st_get_generic_varying_index(st, attr); break; } } } ureg_property(ureg, TGSI_PROPERTY_GS_INPUT_PRIM, stgp->Base.InputType); ureg_property(ureg, TGSI_PROPERTY_GS_OUTPUT_PRIM, stgp->Base.OutputType); ureg_property(ureg, TGSI_PROPERTY_GS_MAX_OUTPUT_VERTICES, stgp->Base.VerticesOut); ureg_property(ureg, TGSI_PROPERTY_GS_INVOCATIONS, stgp->Base.Invocations); st_translate_program(st->ctx, TGSI_PROCESSOR_GEOMETRY, ureg, stgp->glsl_to_tgsi, &stgp->Base.Base, /* inputs */ gs_num_inputs, inputMapping, input_semantic_name, input_semantic_index, NULL, NULL, /* outputs */ gs_num_outputs, outputMapping, gs_output_semantic_name, gs_output_semantic_index, FALSE, FALSE); state.tokens = ureg_get_tokens(ureg, NULL); ureg_destroy(ureg); st_translate_stream_output_info(stgp->glsl_to_tgsi, outputMapping, &state.stream_output); if ((ST_DEBUG & DEBUG_TGSI) && (ST_DEBUG & DEBUG_MESA)) { _mesa_print_program(&stgp->Base.Base); debug_printf("\n"); } if (ST_DEBUG & DEBUG_TGSI) { tgsi_dump(state.tokens, 0); debug_printf("\n"); } /* fill in new variant */ gpv->driver_shader = pipe->create_gs_state(pipe, &state); gpv->key = *key; ureg_free_tokens(state.tokens); return gpv; }