void st_destroy_drawpix(struct st_context *st) { GLuint i; for (i = 0; i < Elements(st->drawpix.shaders); i++) { if (st->drawpix.shaders[i]) _mesa_reference_fragprog(st->ctx, &st->drawpix.shaders[i], NULL); } st_reference_fragprog(st, &st->pixel_xfer.combined_prog, NULL); if (st->drawpix.vert_shaders[0]) ureg_free_tokens(st->drawpix.vert_shaders[0]); if (st->drawpix.vert_shaders[1]) ureg_free_tokens(st->drawpix.vert_shaders[1]); }
/** * Delete a fragment program variant. Note the caller must unlink * the variant from the linked list. */ static void delete_fp_variant(struct st_context *st, struct st_fp_variant *fpv) { if (fpv->driver_shader) cso_delete_fragment_shader(st->cso_context, fpv->driver_shader); if (fpv->parameters) _mesa_free_parameter_list(fpv->parameters); if (fpv->tgsi.tokens) ureg_free_tokens(fpv->tgsi.tokens); free(fpv); }
/** * Delete a vertex program variant. Note the caller must unlink * the variant from the linked list. */ static void delete_vp_variant(struct st_context *st, struct st_vp_variant *vpv) { if (vpv->driver_shader) cso_delete_vertex_shader(st->cso_context, vpv->driver_shader); if (vpv->draw_shader) draw_delete_vertex_shader( st->draw, vpv->draw_shader ); if (vpv->tgsi.tokens) ureg_free_tokens(vpv->tgsi.tokens); free( vpv ); }
/** * Tokens cannot be free with free otherwise the builtin gallium * malloc debugging will get confused. */ void st_free_tokens(const struct tgsi_token *tokens) { ureg_free_tokens(tokens); }
/** * 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; }
/** * The current vertex shader is already executed by the 'draw' * module, so we just need to generate a simple vertex shader * to pass through all those VS outputs that will * be consumed by the fragment shader. * Used when we employ the 'draw' module. */ static enum pipe_error compile_passthrough_vs(struct svga_context *svga, struct svga_vertex_shader *vs, struct svga_fragment_shader *fs, struct svga_shader_variant **out_variant) { struct svga_shader_variant *variant = NULL; unsigned num_inputs; unsigned i; unsigned num_elements; struct svga_vertex_shader new_vs; struct ureg_src src[PIPE_MAX_SHADER_INPUTS]; struct ureg_dst dst[PIPE_MAX_SHADER_OUTPUTS]; struct ureg_program *ureg; unsigned num_tokens; struct svga_compile_key key; enum pipe_error ret; assert(svga_have_vgpu10(svga)); assert(fs); num_inputs = fs->base.info.num_inputs; ureg = ureg_create(TGSI_PROCESSOR_VERTEX); if (!ureg) return PIPE_ERROR_OUT_OF_MEMORY; /* draw will always add position */ dst[0] = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0); src[0] = ureg_DECL_vs_input(ureg, 0); num_elements = 1; /** * swtnl backend redefines the input layout based on the * fragment shader's inputs. So we only need to passthrough * those inputs that will be consumed by the fragment shader. * Note: DX10 requires the number of vertex elements * specified in the input layout to be no less than the * number of inputs to the vertex shader. */ for (i = 0; i < num_inputs; i++) { switch (fs->base.info.input_semantic_name[i]) { case TGSI_SEMANTIC_COLOR: case TGSI_SEMANTIC_GENERIC: case TGSI_SEMANTIC_FOG: dst[num_elements] = ureg_DECL_output(ureg, fs->base.info.input_semantic_name[i], fs->base.info.input_semantic_index[i]); src[num_elements] = ureg_DECL_vs_input(ureg, num_elements); num_elements++; break; default: break; } } for (i = 0; i < num_elements; i++) { ureg_MOV(ureg, dst[i], src[i]); } ureg_END(ureg); memset(&new_vs, 0, sizeof(new_vs)); new_vs.base.tokens = ureg_get_tokens(ureg, &num_tokens); tgsi_scan_shader(new_vs.base.tokens, &new_vs.base.info); memset(&key, 0, sizeof(key)); key.vs.undo_viewport = 1; ret = compile_vs(svga, &new_vs, &key, &variant); if (ret != PIPE_OK) return ret; ureg_free_tokens(new_vs.base.tokens); ureg_destroy(ureg); /* Overwrite the variant key to indicate it's a pass-through VS */ memset(&variant->key, 0, sizeof(variant->key)); variant->key.vs.passthrough = 1; variant->key.vs.undo_viewport = 1; *out_variant = variant; return PIPE_OK; }