X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fstate_tracker%2Fst_glsl_to_tgsi.cpp;h=9b982569490ce1b529f5b2ec472be07f8e3bb396;hb=a921b215dd9487aef74bec868e4201232d976992;hp=2b9183abbb8392ffd70971b7fea193d2e1512431;hpb=ae5770171ccfb085a57c3ef9251c16484c47b6af;p=mesa.git diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp index 2b9183abbb8..9b982569490 100644 --- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp +++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp @@ -53,8 +53,6 @@ #include "st_program.h" #include "st_mesa_to_tgsi.h" #include "st_format.h" -#include "st_nir.h" -#include "st_shader_cache.h" #include "st_glsl_to_tgsi_temprename.h" #include "util/hash_table.h" @@ -781,6 +779,7 @@ glsl_to_tgsi_visitor::get_opcode(enum tgsi_opcode op, case7(ISHR, LAST, ISHR, USHR, LAST, I64SHR, U64SHR); case7(ATOMIMAX,LAST, ATOMIMAX,ATOMUMAX,LAST, LAST, LAST); case7(ATOMIMIN,LAST, ATOMIMIN,ATOMUMIN,LAST, LAST, LAST); + case7(ATOMUADD,ATOMFADD,ATOMUADD,ATOMUADD,LAST, LAST, LAST); casecomp(SEQ, FSEQ, USEQ, USEQ, DSEQ, U64SEQ, U64SEQ); casecomp(SNE, FSNE, USNE, USNE, DSNE, U64SNE, U64SNE); @@ -1065,7 +1064,7 @@ type_has_array_or_matrix(const glsl_type *type) if (type->is_array() || type->is_matrix()) return true; - if (type->is_record()) { + if (type->is_struct()) { for (unsigned i = 0; i < type->length; i++) { if (type_has_array_or_matrix(type->fields.structure[i].type)) { return true; @@ -1111,7 +1110,7 @@ glsl_to_tgsi_visitor::get_temp(const glsl_type *type) next_temp += type_size(type); } - if (type->is_array() || type->is_record()) { + if (type->is_array() || type->is_struct()) { src.swizzle = SWIZZLE_NOOP; } else { src.swizzle = swizzle_for_size(type->vector_elements); @@ -1135,11 +1134,6 @@ glsl_to_tgsi_visitor::find_variable_storage(ir_variable *var) void glsl_to_tgsi_visitor::visit(ir_variable *ir) { - if (strcmp(ir->name, "gl_FragCoord") == 0) { - this->prog->OriginUpperLeft = ir->data.origin_upper_left; - this->prog->PixelCenterInteger = ir->data.pixel_center_integer; - } - if (ir->data.mode == ir_var_uniform && strncmp(ir->name, "gl_", 3) == 0) { unsigned int i; const ir_state_slot *const slots = ir->get_state_slots(); @@ -1274,6 +1268,10 @@ glsl_to_tgsi_visitor::try_emit_mad(ir_expression *ir, int mul_operand) st_src_reg a, b, c; st_dst_reg result_dst; + // there is no TGSI opcode for this + if (ir->type->is_integer_64()) + return false; + ir_expression *expr = ir->operands[mul_operand]->as_expression(); if (!expr || expr->operation != ir_binop_mul) return false; @@ -2084,7 +2082,7 @@ glsl_to_tgsi_visitor::visit_expression(ir_expression* ir, st_src_reg *op) emit_asm(ir, TGSI_OPCODE_USHR, st_dst_reg(index_reg), offset, st_src_reg_for_int(4)); cbuf.reladdr = ralloc(mem_ctx, st_src_reg); - memcpy(cbuf.reladdr, &index_reg, sizeof(index_reg)); + *cbuf.reladdr = index_reg; } if (const_uniform_block) { @@ -2093,7 +2091,7 @@ glsl_to_tgsi_visitor::visit_expression(ir_expression* ir, st_src_reg *op) } else { /* Relative/variable constant buffer */ cbuf.reladdr2 = ralloc(mem_ctx, st_src_reg); - memcpy(cbuf.reladdr2, &op[0], sizeof(st_src_reg)); + *cbuf.reladdr2 = op[0]; } cbuf.has_index2 = true; @@ -2717,6 +2715,42 @@ shrink_array_declarations(struct inout_decl *decls, unsigned count, } } + +static void +mark_array_io(struct inout_decl *decls, unsigned count, + GLbitfield64* usage_mask, + GLbitfield64 double_usage_mask, + GLbitfield* patch_usage_mask) +{ + unsigned i; + int j; + + /* Fix array declarations by removing unused array elements at both ends + * of the arrays. For example, mat4[3] where only mat[1] is used. + */ + for (i = 0; i < count; i++) { + struct inout_decl *decl = &decls[i]; + if (!decl->array_id) + continue; + + /* When not all entries of an array are accessed, we mark them as used + * here anyway, to ensure that the input/output mapping logic doesn't get + * confused. + * + * TODO This happens when an array isn't used via indirect access, which + * some game ports do (at least eON-based). There is an optimization + * opportunity here by replacing the array declaration with non-array + * declarations of those slots that are actually used. + */ + for (j = 0; j < (int)decl->size; ++j) { + if (decl->mesa_index >= VARYING_SLOT_PATCH0) + *patch_usage_mask |= BITFIELD64_BIT(decl->mesa_index - VARYING_SLOT_PATCH0 + j); + else + *usage_mask |= BITFIELD64_BIT(decl->mesa_index + j); + } + } +} + void glsl_to_tgsi_visitor::visit(ir_dereference_array *ir) { @@ -2732,7 +2766,7 @@ glsl_to_tgsi_visitor::visit(ir_dereference_array *ir) * for arrays of structs. Indirect sampler and image indexing is handled * elsewhere. */ - int element_size = ir->type->without_array()->is_record() ? + int element_size = ir->type->without_array()->is_struct() ? st_glsl_storage_type_size(ir->type, var->data.bindless) : type_size(ir->type); @@ -2804,12 +2838,12 @@ glsl_to_tgsi_visitor::visit(ir_dereference_array *ir) if (is_2D) { src.reladdr2 = ralloc(mem_ctx, st_src_reg); - memcpy(src.reladdr2, &index_reg, sizeof(index_reg)); + *src.reladdr2 = index_reg; src.index2D = 0; src.has_index2 = true; } else { src.reladdr = ralloc(mem_ctx, st_src_reg); - memcpy(src.reladdr, &index_reg, sizeof(index_reg)); + *src.reladdr = index_reg; } } @@ -2987,7 +3021,7 @@ glsl_to_tgsi_visitor::emit_block_mov(ir_assignment *ir, const struct glsl_type * st_dst_reg *l, st_src_reg *r, st_src_reg *cond, bool cond_swap) { - if (type->is_record()) { + if (type->is_struct()) { for (unsigned int i = 0; i < type->length; i++) { emit_block_mov(ir, type->fields.structure[i].type, l, r, cond, cond_swap); @@ -3175,7 +3209,7 @@ glsl_to_tgsi_visitor::visit(ir_constant *ir) * aggregate constant and move each constant value into it. If we * get lucky, copy propagation will eliminate the extra moves. */ - if (ir->type->is_record()) { + if (ir->type->is_struct()) { st_src_reg temp_base = get_temp(ir->type); st_dst_reg temp = st_dst_reg(temp_base); @@ -3904,6 +3938,21 @@ glsl_to_tgsi_visitor::visit_image_intrinsic(ir_call *ir) case ir_intrinsic_image_atomic_comp_swap: opcode = TGSI_OPCODE_ATOMCAS; break; + case ir_intrinsic_image_atomic_inc_wrap: { + /* There's a bit of disagreement between GLSL and the hardware. The + * hardware wants to wrap after the given wrap value, while GLSL + * wants to wrap at the value. Subtract 1 to make up the difference. + */ + st_src_reg wrap = get_temp(glsl_type::uint_type); + emit_asm(ir, TGSI_OPCODE_ADD, st_dst_reg(wrap), + arg1, st_src_reg_for_int(-1)); + arg1 = wrap; + opcode = TGSI_OPCODE_ATOMINC_WRAP; + break; + } + case ir_intrinsic_image_atomic_dec_wrap: + opcode = TGSI_OPCODE_ATOMDEC_WRAP; + break; default: assert(!"Unexpected intrinsic"); return; @@ -4029,6 +4078,8 @@ glsl_to_tgsi_visitor::visit(ir_call *ir) case ir_intrinsic_image_atomic_comp_swap: case ir_intrinsic_image_size: case ir_intrinsic_image_samples: + case ir_intrinsic_image_atomic_inc_wrap: + case ir_intrinsic_image_atomic_dec_wrap: visit_image_intrinsic(ir); return; @@ -4088,7 +4139,7 @@ glsl_to_tgsi_visitor::calc_deref_offsets(ir_dereference *tail, calc_deref_offsets(deref_record->record->as_dereference(), array_elements, index, indirect, location); assert(field_index >= 0); - *location += struct_type->record_location_offset(field_index); + *location += struct_type->struct_location_offset(field_index); break; } @@ -4145,8 +4196,7 @@ glsl_to_tgsi_visitor::get_deref_offsets(ir_dereference *ir, unsigned location = 0; ir_variable *var = ir->variable_referenced(); - memset(reladdr, 0, sizeof(*reladdr)); - reladdr->file = PROGRAM_UNDEFINED; + reladdr->reset(); *base = 0; *array_size = 1; @@ -4655,6 +4705,7 @@ glsl_to_tgsi_visitor::glsl_to_tgsi_visitor() ctx = NULL; prog = NULL; precise = 0; + need_uarl = false; shader_program = NULL; shader = NULL; options = NULL; @@ -5593,7 +5644,7 @@ glsl_to_tgsi_visitor::split_arrays(void) void glsl_to_tgsi_visitor::merge_registers(void) { - struct array_live_range *arr_live_ranges = NULL; + class array_live_range *arr_live_ranges = NULL; struct register_live_range *reg_live_ranges = rzalloc_array(mem_ctx, struct register_live_range, this->next_temp); @@ -5601,7 +5652,7 @@ glsl_to_tgsi_visitor::merge_registers(void) if (this->next_array > 0) { arr_live_ranges = new array_live_range[this->next_array]; for (unsigned i = 0; i < this->next_array; ++i) - arr_live_ranges[i] = array_live_range(i+1, this->array_sizes[i+1]); + arr_live_ranges[i] = array_live_range(i+1, this->array_sizes[i]); } @@ -5616,10 +5667,11 @@ glsl_to_tgsi_visitor::merge_registers(void) this->next_array = merge_arrays(this->next_array, this->array_sizes, &this->instructions, arr_live_ranges); - - if (arr_live_ranges) - delete[] arr_live_ranges; } + + if (arr_live_ranges) + delete[] arr_live_ranges; + ralloc_free(reg_live_ranges); } @@ -5739,6 +5791,8 @@ _mesa_sysval_to_semantic(unsigned sysval) /* Fragment shader */ case SYSTEM_VALUE_FRAG_COORD: return TGSI_SEMANTIC_POSITION; + case SYSTEM_VALUE_POINT_COORD: + return TGSI_SEMANTIC_PCOORD; case SYSTEM_VALUE_FRONT_FACE: return TGSI_SEMANTIC_FACE; case SYSTEM_VALUE_SAMPLE_ID: @@ -5792,6 +5846,10 @@ _mesa_sysval_to_semantic(unsigned sysval) case SYSTEM_VALUE_LOCAL_INVOCATION_INDEX: case SYSTEM_VALUE_GLOBAL_INVOCATION_ID: case SYSTEM_VALUE_VERTEX_CNT: + case SYSTEM_VALUE_BARYCENTRIC_PIXEL: + case SYSTEM_VALUE_BARYCENTRIC_SAMPLE: + case SYSTEM_VALUE_BARYCENTRIC_CENTROID: + case SYSTEM_VALUE_BARYCENTRIC_SIZE: default: assert(!"Unexpected SYSTEM_VALUE_ enum"); return TGSI_SEMANTIC_COUNT; @@ -6198,7 +6256,10 @@ compile_tgsi_instruction(struct st_translate *t, case TGSI_OPCODE_ATOMUMAX: case TGSI_OPCODE_ATOMIMIN: case TGSI_OPCODE_ATOMIMAX: + case TGSI_OPCODE_ATOMFADD: case TGSI_OPCODE_IMG2HND: + case TGSI_OPCODE_ATOMINC_WRAP: + case TGSI_OPCODE_ATOMDEC_WRAP: for (i = num_src - 1; i >= 0; i--) src[i + 1] = src[i]; num_src++; @@ -6263,6 +6324,34 @@ compile_tgsi_instruction(struct st_translate *t, } } +/* Invert SamplePos.y when rendering to the default framebuffer. */ +static void +emit_samplepos_adjustment(struct st_translate *t, int wpos_y_transform) +{ + struct ureg_program *ureg = t->ureg; + + assert(wpos_y_transform >= 0); + struct ureg_src trans_const = ureg_DECL_constant(ureg, wpos_y_transform); + struct ureg_src samplepos_sysval = t->systemValues[SYSTEM_VALUE_SAMPLE_POS]; + struct ureg_dst samplepos_flipped = ureg_DECL_temporary(ureg); + struct ureg_dst is_fbo = ureg_DECL_temporary(ureg); + + ureg_ADD(ureg, ureg_writemask(samplepos_flipped, TGSI_WRITEMASK_Y), + ureg_imm1f(ureg, 1), ureg_negate(samplepos_sysval)); + + /* If trans.x == 1, use samplepos.y, else use 1 - samplepos.y. */ + ureg_FSEQ(ureg, ureg_writemask(is_fbo, TGSI_WRITEMASK_Y), + ureg_scalar(trans_const, TGSI_SWIZZLE_X), ureg_imm1f(ureg, 1)); + ureg_UCMP(ureg, ureg_writemask(samplepos_flipped, TGSI_WRITEMASK_Y), + ureg_src(is_fbo), samplepos_sysval, ureg_src(samplepos_flipped)); + ureg_MOV(ureg, ureg_writemask(samplepos_flipped, TGSI_WRITEMASK_X), + samplepos_sysval); + + /* Use the result in place of the system value. */ + t->systemValues[SYSTEM_VALUE_SAMPLE_POS] = ureg_src(samplepos_flipped); +} + + /** * Emit the TGSI instructions for inverting and adjusting WPOS. * This code is unavoidable because it also depends on whether @@ -6386,7 +6475,7 @@ emit_wpos(struct st_context *st, * u,i -> l,h: (99.0 + 0.5) * -1 + 100 = 0.5 * u,h -> l,i: (99.5 + 0.5) * -1 + 100 = 0 */ - if (program->OriginUpperLeft) { + if (program->info.fs.origin_upper_left) { /* Fragment shader wants origin in upper-left */ if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT)) { /* the driver supports upper-left origin */ @@ -6413,7 +6502,7 @@ emit_wpos(struct st_context *st, assert(0); } - if (program->PixelCenterInteger) { + if (program->info.fs.pixel_center_integer) { /* Fragment shader wants pixel center integer */ if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER)) { /* the driver supports pixel center integer */ @@ -6830,6 +6919,10 @@ st_translate_program( emit_wpos(st_context(ctx), t, proginfo, ureg, program->wpos_transform_const); + if (procType == PIPE_SHADER_FRAGMENT && + semName == TGSI_SEMANTIC_SAMPLEPOS) + emit_samplepos_adjustment(t, program->wpos_transform_const); + sysInputs &= ~(1ull << i); } } @@ -7124,14 +7217,28 @@ get_mesa_program_tgsi(struct gl_context *ctx, } do_set_program_inouts(shader->ir, prog, shader->Stage); + _mesa_copy_linked_program_data(shader_program, shader); - shrink_array_declarations(v->inputs, v->num_inputs, - &prog->info.inputs_read, - prog->info.vs.double_inputs_read, - &prog->info.patch_inputs_read); - shrink_array_declarations(v->outputs, v->num_outputs, - &prog->info.outputs_written, 0ULL, - &prog->info.patch_outputs_written); + + if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_SKIP_SHRINK_IO_ARRAYS)) { + mark_array_io(v->inputs, v->num_inputs, + &prog->info.inputs_read, + prog->DualSlotInputs, + &prog->info.patch_inputs_read); + + mark_array_io(v->outputs, v->num_outputs, + &prog->info.outputs_written, 0ULL, + &prog->info.patch_outputs_written); + } else { + shrink_array_declarations(v->inputs, v->num_inputs, + &prog->info.inputs_read, + prog->DualSlotInputs, + &prog->info.patch_inputs_read); + shrink_array_declarations(v->outputs, v->num_outputs, + &prog->info.outputs_written, 0ULL, + &prog->info.patch_outputs_written); + } + count_resources(v, prog); /* The GLSL IR won't be needed anymore. */ @@ -7141,7 +7248,8 @@ get_mesa_program_tgsi(struct gl_context *ctx, /* This must be done before the uniform storage is associated. */ if (shader->Stage == MESA_SHADER_FRAGMENT && (prog->info.inputs_read & VARYING_BIT_POS || - prog->info.system_values_read & (1ull << SYSTEM_VALUE_FRAG_COORD))) { + prog->info.system_values_read & (1ull << SYSTEM_VALUE_FRAG_COORD) || + prog->info.system_values_read & (1ull << SYSTEM_VALUE_SAMPLE_POS))) { static const gl_state_index16 wposTransformState[STATE_LENGTH] = { STATE_INTERNAL, STATE_FB_WPOS_Y_TRANSFORM }; @@ -7160,7 +7268,7 @@ get_mesa_program_tgsi(struct gl_context *ctx, * prog->ParameterValues to get reallocated (e.g., anything that adds a * program constant) has to happen before creating this linkage. */ - _mesa_associate_uniform_storage(ctx, shader_program, prog, true); + _mesa_associate_uniform_storage(ctx, shader_program, prog); if (!shader_program->data->LinkStatus) { free_glsl_to_tgsi_visitor(v); _mesa_reference_program(ctx, &shader->Program, NULL); @@ -7251,130 +7359,29 @@ has_unsupported_control_flow(exec_list *ir, return visitor.unsupported; } -extern "C" { - /** * Link a shader. - * Called via ctx->Driver.LinkShader() * This actually involves converting GLSL IR into an intermediate TGSI-like IR * with code lowering and other optimizations. */ GLboolean -st_link_shader(struct gl_context *ctx, struct gl_shader_program *prog) +st_link_tgsi(struct gl_context *ctx, struct gl_shader_program *prog) { struct pipe_screen *pscreen = ctx->st->pipe->screen; - enum pipe_shader_ir preferred_ir = (enum pipe_shader_ir) - pscreen->get_shader_param(pscreen, PIPE_SHADER_VERTEX, - PIPE_SHADER_CAP_PREFERRED_IR); - bool use_nir = preferred_ir == PIPE_SHADER_IR_NIR; - - /* Return early if we are loading the shader from on-disk cache */ - if (st_load_ir_from_disk_cache(ctx, prog, use_nir)) { - return GL_TRUE; - } - - assert(prog->data->LinkStatus); - for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { - if (prog->_LinkedShaders[i] == NULL) + struct gl_linked_shader *shader = prog->_LinkedShaders[i]; + if (shader == NULL) continue; - struct gl_linked_shader *shader = prog->_LinkedShaders[i]; exec_list *ir = shader->ir; gl_shader_stage stage = shader->Stage; + enum pipe_shader_type ptarget = pipe_shader_type_from_mesa(stage); const struct gl_shader_compiler_options *options = &ctx->Const.ShaderCompilerOptions[stage]; - enum pipe_shader_type ptarget = pipe_shader_type_from_mesa(stage); - bool have_dround = pscreen->get_shader_param(pscreen, ptarget, - PIPE_SHADER_CAP_TGSI_DROUND_SUPPORTED); - bool have_dfrexp = pscreen->get_shader_param(pscreen, ptarget, - PIPE_SHADER_CAP_TGSI_DFRACEXP_DLDEXP_SUPPORTED); - bool have_ldexp = pscreen->get_shader_param(pscreen, ptarget, - PIPE_SHADER_CAP_TGSI_LDEXP_SUPPORTED); + unsigned if_threshold = pscreen->get_shader_param(pscreen, ptarget, PIPE_SHADER_CAP_LOWER_IF_THRESHOLD); - - /* If there are forms of indirect addressing that the driver - * cannot handle, perform the lowering pass. - */ - if (options->EmitNoIndirectInput || options->EmitNoIndirectOutput || - options->EmitNoIndirectTemp || options->EmitNoIndirectUniform) { - lower_variable_index_to_cond_assign(stage, ir, - options->EmitNoIndirectInput, - options->EmitNoIndirectOutput, - options->EmitNoIndirectTemp, - options->EmitNoIndirectUniform); - } - - if (!pscreen->get_param(pscreen, PIPE_CAP_INT64_DIVMOD)) - lower_64bit_integer_instructions(ir, DIV64 | MOD64); - - if (ctx->Extensions.ARB_shading_language_packing) { - unsigned lower_inst = LOWER_PACK_SNORM_2x16 | - LOWER_UNPACK_SNORM_2x16 | - LOWER_PACK_UNORM_2x16 | - LOWER_UNPACK_UNORM_2x16 | - LOWER_PACK_SNORM_4x8 | - LOWER_UNPACK_SNORM_4x8 | - LOWER_UNPACK_UNORM_4x8 | - LOWER_PACK_UNORM_4x8; - - if (ctx->Extensions.ARB_gpu_shader5) - lower_inst |= LOWER_PACK_USE_BFI | - LOWER_PACK_USE_BFE; - if (!ctx->st->has_half_float_packing) - lower_inst |= LOWER_PACK_HALF_2x16 | - LOWER_UNPACK_HALF_2x16; - - lower_packing_builtins(ir, lower_inst); - } - - if (!pscreen->get_param(pscreen, PIPE_CAP_TEXTURE_GATHER_OFFSETS)) - lower_offset_arrays(ir); - do_mat_op_to_vec(ir); - - if (stage == MESA_SHADER_FRAGMENT) - lower_blend_equation_advanced( - shader, ctx->Extensions.KHR_blend_equation_advanced_coherent); - - lower_instructions(ir, - MOD_TO_FLOOR | - FDIV_TO_MUL_RCP | - EXP_TO_EXP2 | - LOG_TO_LOG2 | - (have_ldexp ? 0 : LDEXP_TO_ARITH) | - (have_dfrexp ? 0 : DFREXP_DLDEXP_TO_ARITH) | - CARRY_TO_ARITH | - BORROW_TO_ARITH | - (have_dround ? 0 : DOPS_TO_DFRAC) | - (options->EmitNoPow ? POW_TO_EXP2 : 0) | - (!ctx->Const.NativeIntegers ? INT_DIV_TO_MUL_RCP : 0) | - (options->EmitNoSat ? SAT_TO_CLAMP : 0) | - (ctx->Const.ForceGLSLAbsSqrt ? SQRT_TO_ABS_SQRT : 0) | - /* Assume that if ARB_gpu_shader5 is not supported - * then all of the extended integer functions need - * lowering. It may be necessary to add some caps - * for individual instructions. - */ - (!ctx->Extensions.ARB_gpu_shader5 - ? BIT_COUNT_TO_MATH | - EXTRACT_TO_SHIFTS | - INSERT_TO_SHIFTS | - REVERSE_TO_SHIFTS | - FIND_LSB_TO_FLOAT_CAST | - FIND_MSB_TO_FLOAT_CAST | - IMUL_HIGH_TO_MUL - : 0)); - - do_vec_index_to_cond_assign(ir); - lower_vector_insert(ir, true); - lower_quadop_vector(ir, false); - lower_noise(ir); - if (options->MaxIfDepth == 0) { - lower_discard(ir); - } - if (ctx->Const.GLSLOptimizeConservatively) { /* Do it once and repeat only if there's unsupported control flow. */ do { @@ -7400,17 +7407,6 @@ st_link_shader(struct gl_context *ctx, struct gl_shader_program *prog) do_vec_index_to_cond_assign(ir); validate_ir_tree(ir); - } - - build_program_resource_list(ctx, prog); - - if (use_nir) - return st_link_nir(ctx, prog); - - for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { - struct gl_linked_shader *shader = prog->_LinkedShaders[i]; - if (shader == NULL) - continue; struct gl_program *linked_prog = get_mesa_program_tgsi(ctx, prog, shader); @@ -7429,26 +7425,20 @@ st_link_shader(struct gl_context *ctx, struct gl_shader_program *prog) return GL_TRUE; } -void -st_translate_stream_output_info(glsl_to_tgsi_visitor *glsl_to_tgsi, - const ubyte outputMapping[], - struct pipe_stream_output_info *so) -{ - if (!glsl_to_tgsi->shader_program->last_vert_prog) - return; - - struct gl_transform_feedback_info *info = - glsl_to_tgsi->shader_program->last_vert_prog->sh.LinkedTransformFeedback; - st_translate_stream_output_info2(info, outputMapping, so); -} +extern "C" { void -st_translate_stream_output_info2(struct gl_transform_feedback_info *info, +st_translate_stream_output_info(struct gl_transform_feedback_info *info, const ubyte outputMapping[], struct pipe_stream_output_info *so) { unsigned i; + if (!info) { + so->num_outputs = 0; + return; + } + for (i = 0; i < info->NumOutputs; i++) { so->output[i].register_index = outputMapping[info->Outputs[i].OutputRegister];