/** * Translate a vertex program to create a new variant. */ static struct st_vp_variant * st_translate_vertex_program(struct st_context *st, struct st_vertex_program *stvp, const struct st_vp_variant_key *key) { struct st_vp_variant *vpv = CALLOC_STRUCT(st_vp_variant); struct pipe_context *pipe = st->pipe; struct ureg_program *ureg; enum pipe_error error; unsigned num_outputs; st_prepare_vertex_program(st->ctx, stvp); if (!stvp->glsl_to_tgsi) { _mesa_remove_output_reads(&stvp->Base.Base, PROGRAM_OUTPUT); } ureg = ureg_create( TGSI_PROCESSOR_VERTEX ); if (ureg == NULL) { free(vpv); return NULL; } vpv->key = *key; vpv->num_inputs = stvp->num_inputs; num_outputs = stvp->num_outputs; if (key->passthrough_edgeflags) { vpv->num_inputs++; num_outputs++; } if (ST_DEBUG & DEBUG_MESA) { _mesa_print_program(&stvp->Base.Base); _mesa_print_program_parameters(st->ctx, &stvp->Base.Base); debug_printf("\n"); } if (stvp->glsl_to_tgsi) error = st_translate_program(st->ctx, TGSI_PROCESSOR_VERTEX, ureg, stvp->glsl_to_tgsi, &stvp->Base.Base, /* inputs */ vpv->num_inputs, stvp->input_to_index, NULL, /* input semantic name */ NULL, /* input semantic index */ NULL, /* interp mode */ NULL, /* interp location */ /* outputs */ num_outputs, stvp->result_to_output, stvp->output_semantic_name, stvp->output_semantic_index, key->passthrough_edgeflags, key->clamp_color); else error = st_translate_mesa_program(st->ctx, TGSI_PROCESSOR_VERTEX, ureg, &stvp->Base.Base, /* inputs */ vpv->num_inputs, stvp->input_to_index, NULL, /* input semantic name */ NULL, /* input semantic index */ NULL, /* outputs */ num_outputs, stvp->result_to_output, stvp->output_semantic_name, stvp->output_semantic_index, key->passthrough_edgeflags, key->clamp_color); if (error) goto fail; vpv->tgsi.tokens = ureg_get_tokens( ureg, NULL ); if (!vpv->tgsi.tokens) goto fail; ureg_destroy( ureg ); if (stvp->glsl_to_tgsi) { st_translate_stream_output_info(stvp->glsl_to_tgsi, stvp->result_to_output, &vpv->tgsi.stream_output); } if (ST_DEBUG & DEBUG_TGSI) { tgsi_dump(vpv->tgsi.tokens, 0); debug_printf("\n"); } vpv->driver_shader = pipe->create_vs_state(pipe, &vpv->tgsi); return vpv; fail: debug_printf("%s: failed to translate Mesa program:\n", __func__); _mesa_print_program(&stvp->Base.Base); debug_assert(0); ureg_destroy( ureg ); return NULL; }
/** * 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; }
/** * 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; GLbitfield64 inputsRead; GLuint vslot = 0; GLuint num_generic = 0; uint gs_num_inputs = 0; uint gs_builtin_inputs = 0; uint gs_array_offset = 0; 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; GLuint maxSlot = 0; struct ureg_program *ureg; struct st_gp_variant *gpv; gpv = CALLOC_STRUCT(st_gp_variant); if (!gpv) return NULL; _mesa_remove_output_reads(&stgp->Base.Base, PROGRAM_OUTPUT); ureg = ureg_create( TGSI_PROCESSOR_GEOMETRY ); if (ureg == NULL) { free(gpv); return NULL; } /* which vertex output goes to the first geometry input */ vslot = 0; memset(inputMapping, 0, sizeof(inputMapping)); memset(outputMapping, 0, sizeof(outputMapping)); /* * Convert Mesa program inputs to TGSI input register semantics. */ inputsRead = stgp->Base.Base.InputsRead; for (attr = 0; attr < VARYING_SLOT_MAX; attr++) { if ((inputsRead & BITFIELD64_BIT(attr)) != 0) { const GLuint slot = gs_num_inputs; gs_num_inputs++; inputMapping[attr] = slot; stgp->input_map[slot + gs_array_offset] = vslot - gs_builtin_inputs; stgp->input_to_index[attr] = vslot; stgp->index_to_input[vslot] = attr; ++vslot; if (attr != VARYING_SLOT_PRIMITIVE_ID) { gs_array_offset += 2; } else ++gs_builtin_inputs; #if 0 debug_printf("input map at %d = %d\n", slot + gs_array_offset, stgp->input_map[slot + gs_array_offset]); #endif switch (attr) { case VARYING_SLOT_PRIMITIVE_ID: stgp->input_semantic_name[slot] = TGSI_SEMANTIC_PRIMID; stgp->input_semantic_index[slot] = 0; break; case VARYING_SLOT_POS: stgp->input_semantic_name[slot] = TGSI_SEMANTIC_POSITION; stgp->input_semantic_index[slot] = 0; break; case VARYING_SLOT_COL0: stgp->input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; stgp->input_semantic_index[slot] = 0; break; case VARYING_SLOT_COL1: stgp->input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; stgp->input_semantic_index[slot] = 1; break; case VARYING_SLOT_FOGC: stgp->input_semantic_name[slot] = TGSI_SEMANTIC_FOG; stgp->input_semantic_index[slot] = 0; break; case VARYING_SLOT_TEX0: stgp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; stgp->input_semantic_index[slot] = num_generic++; break; case VARYING_SLOT_VAR0: /* fall-through */ default: stgp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; stgp->input_semantic_index[slot] = num_generic++; } } } /* 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; } num_generic = 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; slot = gs_num_outputs; 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_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: /* fall-through */ case VARYING_SLOT_VAR0: /* fall-through */ default: assert(slot < Elements(gs_output_semantic_name)); /* use default semantic info */ gs_output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; gs_output_semantic_index[slot] = num_generic++; } } } assert(gs_output_semantic_name[0] == TGSI_SEMANTIC_POSITION); /* find max output slot referenced to compute gs_num_outputs */ for (attr = 0; attr < VARYING_SLOT_MAX; attr++) { if (outputMapping[attr] != ~0 && outputMapping[attr] > maxSlot) maxSlot = outputMapping[attr]; } gs_num_outputs = maxSlot + 1; #if 0 /* debug */ { GLuint i; printf("outputMapping? %d\n", outputMapping ? 1 : 0); if (outputMapping) { printf("attr -> slot\n"); for (i = 0; i < 16; i++) { printf(" %2d %3d\n", i, outputMapping[i]); } } printf("slot sem_name sem_index\n"); for (i = 0; i < gs_num_outputs; i++) { printf(" %2d %d %d\n", i, gs_output_semantic_name[i], gs_output_semantic_index[i]); } } #endif /* free old shader state, if any */ if (stgp->tgsi.tokens) { st_free_tokens(stgp->tgsi.tokens); stgp->tgsi.tokens = NULL; } ureg_property_gs_input_prim(ureg, stgp->Base.InputType); ureg_property_gs_output_prim(ureg, stgp->Base.OutputType); ureg_property_gs_max_vertices(ureg, stgp->Base.VerticesOut); st_translate_mesa_program(st->ctx, TGSI_PROCESSOR_GEOMETRY, ureg, &stgp->Base.Base, /* inputs */ gs_num_inputs, inputMapping, stgp->input_semantic_name, stgp->input_semantic_index, NULL, /* outputs */ gs_num_outputs, outputMapping, gs_output_semantic_name, gs_output_semantic_index, FALSE, FALSE); stgp->num_inputs = gs_num_inputs; stgp->tgsi.tokens = ureg_get_tokens( ureg, NULL ); ureg_destroy( ureg ); if (stgp->glsl_to_tgsi) { st_translate_stream_output_info(stgp->glsl_to_tgsi, outputMapping, &stgp->tgsi.stream_output); } /* fill in new variant */ gpv->driver_shader = pipe->create_gs_state(pipe, &stgp->tgsi); gpv->key = *key; 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(stgp->tgsi.tokens, 0); debug_printf("\n"); } return gpv; }