/** * Allocate an extra vertex/geometry shader vertex attribute, if it doesn't * exist already. * * This is used by some of the optional draw module stages such * as wide_point which may need to allocate additional generic/texcoord * attributes. */ int draw_alloc_extra_vertex_attrib(struct draw_context *draw, uint semantic_name, uint semantic_index) { int slot; uint num_outputs; uint n; slot = draw_find_shader_output(draw, semantic_name, semantic_index); if (slot > 0) { return slot; } num_outputs = draw_current_shader_outputs(draw); n = draw->extra_shader_outputs.num; assert(n < Elements(draw->extra_shader_outputs.semantic_name)); draw->extra_shader_outputs.semantic_name[n] = semantic_name; draw->extra_shader_outputs.semantic_index[n] = semantic_index; draw->extra_shader_outputs.slot[n] = num_outputs + n; draw->extra_shader_outputs.num++; return draw->extra_shader_outputs.slot[n]; }
/** * The vertex info describes how to convert the post-transformed vertices * (simple float[][4]) used by the 'draw' module into vertices for * rasterization. * * This function validates the vertex layout. */ static void compute_vertex_info(struct llvmpipe_context *llvmpipe) { const struct tgsi_shader_info *fsInfo = &llvmpipe->fs->info.base; struct vertex_info *vinfo = &llvmpipe->vertex_info; int vs_index; uint i; draw_prepare_shader_outputs(llvmpipe->draw); /* * Those can't actually be 0 (because pos is always at 0). * But use ints anyway to avoid confusion (in vs outputs, they * can very well be at pos 0). */ llvmpipe->color_slot[0] = -1; llvmpipe->color_slot[1] = -1; llvmpipe->bcolor_slot[0] = -1; llvmpipe->bcolor_slot[1] = -1; llvmpipe->viewport_index_slot = -1; llvmpipe->layer_slot = -1; llvmpipe->face_slot = -1; llvmpipe->psize_slot = -1; /* * Match FS inputs against VS outputs, emitting the necessary * attributes. Could cache these structs and look them up with a * combination of fragment shader, vertex shader ids. */ vinfo->num_attribs = 0; vs_index = draw_find_shader_output(llvmpipe->draw, TGSI_SEMANTIC_POSITION, 0); draw_emit_vertex_attr(vinfo, EMIT_4F, vs_index); for (i = 0; i < fsInfo->num_inputs; i++) { /* * Search for each input in current vs output: */ vs_index = draw_find_shader_output(llvmpipe->draw, fsInfo->input_semantic_name[i], fsInfo->input_semantic_index[i]); if (fsInfo->input_semantic_name[i] == TGSI_SEMANTIC_COLOR && fsInfo->input_semantic_index[i] < 2) { int idx = fsInfo->input_semantic_index[i]; llvmpipe->color_slot[idx] = (int)vinfo->num_attribs; } if (fsInfo->input_semantic_name[i] == TGSI_SEMANTIC_FACE) { llvmpipe->face_slot = (int)vinfo->num_attribs; draw_emit_vertex_attr(vinfo, EMIT_4F, vs_index); /* * For vp index and layer, if the fs requires them but the vs doesn't * provide them, draw (vbuf) will give us the required 0 (slot -1). * (This means in this case we'll also use those slots in setup, which * isn't necessary but they'll contain the correct (0) value.) */ } else if (fsInfo->input_semantic_name[i] == TGSI_SEMANTIC_VIEWPORT_INDEX) { llvmpipe->viewport_index_slot = (int)vinfo->num_attribs; draw_emit_vertex_attr(vinfo, EMIT_4F, vs_index); } else if (fsInfo->input_semantic_name[i] == TGSI_SEMANTIC_LAYER) { llvmpipe->layer_slot = (int)vinfo->num_attribs; draw_emit_vertex_attr(vinfo, EMIT_4F, vs_index); } else { /* * Note that we'd actually want to skip position (as we won't use * the attribute in the fs) but can't. The reason is that we don't * actually have a input/output map for setup (even though it looks * like we do...). Could adjust for this though even without a map * (in llvmpipe_create_fs_state()). */ draw_emit_vertex_attr(vinfo, EMIT_4F, vs_index); } } /* Figure out if we need bcolor as well. */ for (i = 0; i < 2; i++) { vs_index = draw_find_shader_output(llvmpipe->draw, TGSI_SEMANTIC_BCOLOR, i); if (vs_index >= 0) { llvmpipe->bcolor_slot[i] = (int)vinfo->num_attribs; draw_emit_vertex_attr(vinfo, EMIT_4F, vs_index); } } /* Figure out if we need pointsize as well. */ vs_index = draw_find_shader_output(llvmpipe->draw, TGSI_SEMANTIC_PSIZE, 0); if (vs_index >= 0) { llvmpipe->psize_slot = (int)vinfo->num_attribs; draw_emit_vertex_attr(vinfo, EMIT_4F, vs_index); } /* Figure out if we need viewport index (if it wasn't already in fs input) */ if (llvmpipe->viewport_index_slot < 0) { vs_index = draw_find_shader_output(llvmpipe->draw, TGSI_SEMANTIC_VIEWPORT_INDEX, 0); if (vs_index >= 0) { llvmpipe->viewport_index_slot =(int)vinfo->num_attribs; draw_emit_vertex_attr(vinfo, EMIT_4F, vs_index); } } /* Figure out if we need layer (if it wasn't already in fs input) */ if (llvmpipe->layer_slot < 0) { vs_index = draw_find_shader_output(llvmpipe->draw, TGSI_SEMANTIC_LAYER, 0); if (vs_index >= 0) { llvmpipe->layer_slot = (int)vinfo->num_attribs; draw_emit_vertex_attr(vinfo, EMIT_4F, vs_index); } } draw_compute_vertex_size(vinfo); lp_setup_set_vertex_info(llvmpipe->setup, vinfo); }
/** * The vertex info describes how to convert the post-transformed vertices * (simple float[][4]) used by the 'draw' module into vertices for * rasterization. * * This function validates the vertex layout and returns a pointer to a * vertex_info object. */ struct vertex_info * softpipe_get_vertex_info(struct softpipe_context *softpipe) { struct vertex_info *vinfo = &softpipe->vertex_info; if (vinfo->num_attribs == 0) { /* compute vertex layout now */ const struct tgsi_shader_info *fsInfo = &softpipe->fs_variant->info; struct vertex_info *vinfo_vbuf = &softpipe->vertex_info_vbuf; const uint num = draw_num_shader_outputs(softpipe->draw); uint i; /* Tell draw_vbuf to simply emit the whole post-xform vertex * as-is. No longer any need to try and emit draw vertex_header * info. */ vinfo_vbuf->num_attribs = 0; for (i = 0; i < num; i++) { draw_emit_vertex_attr(vinfo_vbuf, EMIT_4F, INTERP_PERSPECTIVE, i); } draw_compute_vertex_size(vinfo_vbuf); /* * Loop over fragment shader inputs, searching for the matching output * from the vertex shader. */ vinfo->num_attribs = 0; for (i = 0; i < fsInfo->num_inputs; i++) { int src; enum interp_mode interp = INTERP_LINEAR; switch (fsInfo->input_interpolate[i]) { case TGSI_INTERPOLATE_CONSTANT: interp = INTERP_CONSTANT; break; case TGSI_INTERPOLATE_LINEAR: interp = INTERP_LINEAR; break; case TGSI_INTERPOLATE_PERSPECTIVE: interp = INTERP_PERSPECTIVE; break; case TGSI_INTERPOLATE_COLOR: assert(fsInfo->input_semantic_name[i] == TGSI_SEMANTIC_COLOR); break; default: assert(0); } switch (fsInfo->input_semantic_name[i]) { case TGSI_SEMANTIC_POSITION: interp = INTERP_POS; break; case TGSI_SEMANTIC_COLOR: if (fsInfo->input_interpolate[i] == TGSI_INTERPOLATE_COLOR) { if (softpipe->rasterizer->flatshade) interp = INTERP_CONSTANT; else interp = INTERP_PERSPECTIVE; } break; } /* this includes texcoords and varying vars */ src = draw_find_shader_output(softpipe->draw, fsInfo->input_semantic_name[i], fsInfo->input_semantic_index[i]); if (fsInfo->input_semantic_name[i] == TGSI_SEMANTIC_COLOR && src == 0) /* try and find a bcolor */ src = draw_find_shader_output(softpipe->draw, TGSI_SEMANTIC_BCOLOR, fsInfo->input_semantic_index[i]); draw_emit_vertex_attr(vinfo, EMIT_4F, interp, src); } softpipe->psize_slot = draw_find_shader_output(softpipe->draw, TGSI_SEMANTIC_PSIZE, 0); if (softpipe->psize_slot > 0) { draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_CONSTANT, softpipe->psize_slot); } draw_compute_vertex_size(vinfo); } return vinfo; }
/** * The vertex info describes how to convert the post-transformed vertices * (simple float[][4]) used by the 'draw' module into vertices for * rasterization. * * This function validates the vertex layout. */ static void compute_vertex_info(struct llvmpipe_context *llvmpipe) { const struct lp_fragment_shader *lpfs = llvmpipe->fs; struct vertex_info *vinfo = &llvmpipe->vertex_info; int vs_index; uint i; llvmpipe->color_slot[0] = -1; llvmpipe->color_slot[1] = -1; llvmpipe->bcolor_slot[0] = -1; llvmpipe->bcolor_slot[1] = -1; /* * Match FS inputs against VS outputs, emitting the necessary * attributes. Could cache these structs and look them up with a * combination of fragment shader, vertex shader ids. */ vinfo->num_attribs = 0; vs_index = draw_find_shader_output(llvmpipe->draw, TGSI_SEMANTIC_POSITION, 0); draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, vs_index); for (i = 0; i < lpfs->info.base.num_inputs; i++) { /* * Search for each input in current vs output: */ vs_index = draw_find_shader_output(llvmpipe->draw, lpfs->info.base.input_semantic_name[i], lpfs->info.base.input_semantic_index[i]); if (lpfs->info.base.input_semantic_name[i] == TGSI_SEMANTIC_COLOR && lpfs->info.base.input_semantic_index[i] < 2) { int idx = lpfs->info.base.input_semantic_index[i]; llvmpipe->color_slot[idx] = (int)vinfo->num_attribs; } /* * Emit the requested fs attribute for all but position. */ draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, vs_index); } /* Figure out if we need bcolor as well. */ for (i = 0; i < 2; i++) { vs_index = draw_find_shader_output(llvmpipe->draw, TGSI_SEMANTIC_BCOLOR, i); if (vs_index >= 0) { llvmpipe->bcolor_slot[i] = (int)vinfo->num_attribs; draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, vs_index); } } /* Figure out if we need pointsize as well. */ vs_index = draw_find_shader_output(llvmpipe->draw, TGSI_SEMANTIC_PSIZE, 0); if (vs_index >= 0) { llvmpipe->psize_slot = vinfo->num_attribs; draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_CONSTANT, vs_index); } /* Figure out if we need viewport index */ vs_index = draw_find_shader_output(llvmpipe->draw, TGSI_SEMANTIC_VIEWPORT_INDEX, 0); if (vs_index >= 0) { llvmpipe->viewport_index_slot = vinfo->num_attribs; draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_CONSTANT, vs_index); } else { llvmpipe->viewport_index_slot = 0; } /* Figure out if we need layer */ vs_index = draw_find_shader_output(llvmpipe->draw, TGSI_SEMANTIC_LAYER, 0); if (vs_index >= 0) { llvmpipe->layer_slot = vinfo->num_attribs; draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_CONSTANT, vs_index); } else { llvmpipe->layer_slot = 0; } draw_compute_vertex_size(vinfo); lp_setup_set_vertex_info(llvmpipe->setup, vinfo); }
/** * The vertex info describes how to convert the post-transformed vertices * (simple float[][4]) used by the 'draw' module into vertices for * rasterization. * * This function validates the vertex layout. */ static void compute_vertex_info(struct llvmpipe_context *llvmpipe) { const struct lp_fragment_shader *lpfs = llvmpipe->fs; struct vertex_info *vinfo = &llvmpipe->vertex_info; int vs_index; uint i; draw_prepare_shader_outputs(llvmpipe->draw); llvmpipe->color_slot[0] = 0; llvmpipe->color_slot[1] = 0; llvmpipe->bcolor_slot[0] = 0; llvmpipe->bcolor_slot[1] = 0; llvmpipe->viewport_index_slot = 0; llvmpipe->layer_slot = 0; llvmpipe->face_slot = 0; llvmpipe->psize_slot = 0; /* * Match FS inputs against VS outputs, emitting the necessary * attributes. Could cache these structs and look them up with a * combination of fragment shader, vertex shader ids. */ vinfo->num_attribs = 0; vs_index = draw_find_shader_output(llvmpipe->draw, TGSI_SEMANTIC_POSITION, 0); draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, vs_index); for (i = 0; i < lpfs->info.base.num_inputs; i++) { /* * Search for each input in current vs output: */ vs_index = draw_find_shader_output(llvmpipe->draw, lpfs->info.base.input_semantic_name[i], lpfs->info.base.input_semantic_index[i]); if (lpfs->info.base.input_semantic_name[i] == TGSI_SEMANTIC_COLOR && lpfs->info.base.input_semantic_index[i] < 2) { int idx = lpfs->info.base.input_semantic_index[i]; llvmpipe->color_slot[idx] = vinfo->num_attribs; } if (lpfs->info.base.input_semantic_name[i] == TGSI_SEMANTIC_FACE) { llvmpipe->face_slot = vinfo->num_attribs; draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_CONSTANT, vs_index); } else if (lpfs->info.base.input_semantic_name[i] == TGSI_SEMANTIC_PRIMID) { draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_CONSTANT, vs_index); /* * For vp index and layer, if the fs requires them but the vs doesn't * provide them, store the slot - we'll later replace the data directly * with zero (as required by ARB_fragment_layer_viewport). This is * because draw itself just redirects them to whatever was at output 0. * We'll also store the real vpindex/layer slot for setup use. */ } else if (lpfs->info.base.input_semantic_name[i] == TGSI_SEMANTIC_VIEWPORT_INDEX) { if (vs_index >= 0) { llvmpipe->viewport_index_slot = vinfo->num_attribs; } else { llvmpipe->fake_vpindex_slot = vinfo->num_attribs; } draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_CONSTANT, vs_index); } else if (lpfs->info.base.input_semantic_name[i] == TGSI_SEMANTIC_LAYER) { if (vs_index >= 0) { llvmpipe->layer_slot = vinfo->num_attribs; } else { llvmpipe->fake_layer_slot = vinfo->num_attribs; } draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_CONSTANT, vs_index); } else { /* * Emit the requested fs attribute for all but position. */ draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, vs_index); } } /* Figure out if we need bcolor as well. */ for (i = 0; i < 2; i++) { vs_index = draw_find_shader_output(llvmpipe->draw, TGSI_SEMANTIC_BCOLOR, i); if (vs_index >= 0) { llvmpipe->bcolor_slot[i] = vinfo->num_attribs; draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, vs_index); } } /* Figure out if we need pointsize as well. */ vs_index = draw_find_shader_output(llvmpipe->draw, TGSI_SEMANTIC_PSIZE, 0); if (vs_index >= 0) { llvmpipe->psize_slot = vinfo->num_attribs; draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_CONSTANT, vs_index); } /* Figure out if we need viewport index (if it wasn't already in fs input) */ if (llvmpipe->viewport_index_slot == 0) { vs_index = draw_find_shader_output(llvmpipe->draw, TGSI_SEMANTIC_VIEWPORT_INDEX, 0); if (vs_index >= 0) { llvmpipe->viewport_index_slot = vinfo->num_attribs; draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_CONSTANT, vs_index); } } /* Figure out if we need layer (if it wasn't already in fs input) */ if (llvmpipe->layer_slot == 0) { vs_index = draw_find_shader_output(llvmpipe->draw, TGSI_SEMANTIC_LAYER, 0); if (vs_index >= 0) { llvmpipe->layer_slot = vinfo->num_attribs; draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_CONSTANT, vs_index); } } draw_compute_vertex_size(vinfo); lp_setup_set_vertex_info(llvmpipe->setup, vinfo); }
enum pipe_error svga_swtnl_update_vdecl( struct svga_context *svga ) { struct svga_vbuf_render *svga_render = svga_vbuf_render(svga->swtnl.backend); struct draw_context *draw = svga->swtnl.draw; struct vertex_info *vinfo = &svga_render->vertex_info; SVGA3dVertexDecl vdecl[PIPE_MAX_ATTRIBS]; const enum interp_mode colorInterp = svga->curr.rast->templ.flatshade ? INTERP_CONSTANT : INTERP_LINEAR; struct svga_fragment_shader *fs = svga->curr.fs; int offset = 0; int nr_decls = 0; int src; unsigned i; memset(vinfo, 0, sizeof(*vinfo)); memset(vdecl, 0, sizeof(vdecl)); /* always add position */ src = draw_find_shader_output(draw, TGSI_SEMANTIC_POSITION, 0); draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_LINEAR, src); vinfo->attrib[0].emit = EMIT_4F; vdecl[0].array.offset = offset; vdecl[0].identity.type = SVGA3D_DECLTYPE_FLOAT4; vdecl[0].identity.usage = SVGA3D_DECLUSAGE_POSITIONT; vdecl[0].identity.usageIndex = 0; offset += 16; nr_decls++; for (i = 0; i < fs->base.info.num_inputs; i++) { const unsigned sem_name = fs->base.info.input_semantic_name[i]; const unsigned sem_index = fs->base.info.input_semantic_index[i]; src = draw_find_shader_output(draw, sem_name, sem_index); vdecl[nr_decls].array.offset = offset; vdecl[nr_decls].identity.usageIndex = sem_index; switch (sem_name) { case TGSI_SEMANTIC_COLOR: draw_emit_vertex_attr(vinfo, EMIT_4F, colorInterp, src); vdecl[nr_decls].identity.usage = SVGA3D_DECLUSAGE_COLOR; vdecl[nr_decls].identity.type = SVGA3D_DECLTYPE_FLOAT4; offset += 16; nr_decls++; break; case TGSI_SEMANTIC_GENERIC: draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, src); vdecl[nr_decls].identity.usage = SVGA3D_DECLUSAGE_TEXCOORD; vdecl[nr_decls].identity.type = SVGA3D_DECLTYPE_FLOAT4; vdecl[nr_decls].identity.usageIndex = svga_remap_generic_index(fs->generic_remap_table, sem_index); offset += 16; nr_decls++; break; case TGSI_SEMANTIC_FOG: draw_emit_vertex_attr(vinfo, EMIT_1F, INTERP_PERSPECTIVE, src); vdecl[nr_decls].identity.usage = SVGA3D_DECLUSAGE_TEXCOORD; vdecl[nr_decls].identity.type = SVGA3D_DECLTYPE_FLOAT1; assert(vdecl[nr_decls].identity.usageIndex == 0); offset += 4; nr_decls++; break; case TGSI_SEMANTIC_POSITION: /* generated internally, not a vertex shader output */ break; default: assert(0); } } draw_compute_vertex_size(vinfo); svga_render->vdecl_count = nr_decls; for (i = 0; i < svga_render->vdecl_count; i++) vdecl[i].array.stride = offset; if (memcmp(svga_render->vdecl, vdecl, sizeof(vdecl)) == 0) return 0; memcpy(svga_render->vdecl, vdecl, sizeof(vdecl)); svga->swtnl.new_vdecl = TRUE; return 0; }
/** * The vertex info describes how to convert the post-transformed vertices * (simple float[][4]) used by the 'draw' module into vertices for * rasterization. * * This function validates the vertex layout. */ static void softpipe_compute_vertex_info(struct softpipe_context *softpipe) { struct sp_setup_info *sinfo = &softpipe->setup_info; if (sinfo->valid == 0) { const struct tgsi_shader_info *fsInfo = &softpipe->fs_variant->info; struct vertex_info *vinfo = &softpipe->vertex_info; uint i; int vs_index; /* * This doesn't quite work right (wrt face injection, prim id, * wide points) - hit a couple assertions, misrenderings plus * memory corruption. Albeit could fix (the former two) by calling * this "more often" (rasterizer changes etc.). (The latter would * need to be included in draw_prepare_shader_outputs, but it looks * like that would potentially allocate quite some unused additional * vertex outputs.) * draw_prepare_shader_outputs(softpipe->draw); */ /* * Those can't actually be 0 (because pos is always at 0). * But use ints anyway to avoid confusion (in vs outputs, they * can very well be at pos 0). */ softpipe->viewport_index_slot = -1; softpipe->layer_slot = -1; softpipe->psize_slot = -1; vinfo->num_attribs = 0; /* * Put position always first (setup needs it there). */ vs_index = draw_find_shader_output(softpipe->draw, TGSI_SEMANTIC_POSITION, 0); draw_emit_vertex_attr(vinfo, EMIT_4F, vs_index); /* * Match FS inputs against VS outputs, emitting the necessary * attributes. */ for (i = 0; i < fsInfo->num_inputs; i++) { enum sp_interp_mode interp = SP_INTERP_LINEAR; switch (fsInfo->input_interpolate[i]) { case TGSI_INTERPOLATE_CONSTANT: interp = SP_INTERP_CONSTANT; break; case TGSI_INTERPOLATE_LINEAR: interp = SP_INTERP_LINEAR; break; case TGSI_INTERPOLATE_PERSPECTIVE: interp = SP_INTERP_PERSPECTIVE; break; case TGSI_INTERPOLATE_COLOR: assert(fsInfo->input_semantic_name[i] == TGSI_SEMANTIC_COLOR); break; default: assert(0); } switch (fsInfo->input_semantic_name[i]) { case TGSI_SEMANTIC_POSITION: interp = SP_INTERP_POS; break; case TGSI_SEMANTIC_COLOR: if (fsInfo->input_interpolate[i] == TGSI_INTERPOLATE_COLOR) { if (softpipe->rasterizer->flatshade) interp = SP_INTERP_CONSTANT; else interp = SP_INTERP_PERSPECTIVE; } break; } /* * Search for each input in current vs output: */ vs_index = draw_find_shader_output(softpipe->draw, fsInfo->input_semantic_name[i], fsInfo->input_semantic_index[i]); if (fsInfo->input_semantic_name[i] == TGSI_SEMANTIC_COLOR && vs_index == -1) { /* * try and find a bcolor. * Note that if there's both front and back color, draw will * have copied back to front color already. */ vs_index = draw_find_shader_output(softpipe->draw, TGSI_SEMANTIC_BCOLOR, fsInfo->input_semantic_index[i]); } sinfo->attrib[i].interp = interp; /* extremely pointless index map */ sinfo->attrib[i].src_index = i + 1; /* * For vp index and layer, if the fs requires them but the vs doesn't * provide them, draw (vbuf) will give us the required 0 (slot -1). * (This means in this case we'll also use those slots in setup, which * isn't necessary but they'll contain the correct (0) value.) */ if (fsInfo->input_semantic_name[i] == TGSI_SEMANTIC_VIEWPORT_INDEX) { softpipe->viewport_index_slot = (int)vinfo->num_attribs; draw_emit_vertex_attr(vinfo, EMIT_4F, vs_index); } else if (fsInfo->input_semantic_name[i] == TGSI_SEMANTIC_LAYER) { softpipe->layer_slot = (int)vinfo->num_attribs; draw_emit_vertex_attr(vinfo, EMIT_4F, vs_index); /* * Note that we'd actually want to skip position (as we won't use * the attribute in the fs) but can't. The reason is that we don't * actually have an input/output map for setup (even though it looks * like we do...). Could adjust for this though even without a map. */ } else { /* * Note that we'd actually want to skip position (as we won't use * the attribute in the fs) but can't. The reason is that we don't * actually have an input/output map for setup (even though it looks * like we do...). Could adjust for this though even without a map. */ draw_emit_vertex_attr(vinfo, EMIT_4F, vs_index); } } /* Figure out if we need pointsize as well. */ vs_index = draw_find_shader_output(softpipe->draw, TGSI_SEMANTIC_PSIZE, 0); if (vs_index >= 0) { softpipe->psize_slot = (int)vinfo->num_attribs; draw_emit_vertex_attr(vinfo, EMIT_4F, vs_index); } /* Figure out if we need viewport index (if it wasn't already in fs input) */ if (softpipe->viewport_index_slot < 0) { vs_index = draw_find_shader_output(softpipe->draw, TGSI_SEMANTIC_VIEWPORT_INDEX, 0); if (vs_index >= 0) { softpipe->viewport_index_slot =(int)vinfo->num_attribs; draw_emit_vertex_attr(vinfo, EMIT_4F, vs_index); } } /* Figure out if we need layer (if it wasn't already in fs input) */ if (softpipe->layer_slot < 0) { vs_index = draw_find_shader_output(softpipe->draw, TGSI_SEMANTIC_LAYER, 0); if (vs_index >= 0) { softpipe->layer_slot = (int)vinfo->num_attribs; draw_emit_vertex_attr(vinfo, EMIT_4F, vs_index); } } draw_compute_vertex_size(vinfo); softpipe->setup_info.valid = 1; } return; }
/** * The vertex info describes how to convert the post-transformed vertices * (simple float[][4]) used by the 'draw' module into vertices for * rasterization. * * This function validates the vertex layout. */ static void compute_vertex_info(struct llvmpipe_context *llvmpipe) { const struct lp_fragment_shader *lpfs = llvmpipe->fs; struct vertex_info *vinfo = &llvmpipe->vertex_info; struct lp_shader_input *inputs = llvmpipe->inputs; unsigned vs_index; uint i; /* * Match FS inputs against VS outputs, emitting the necessary attributes. */ vinfo->num_attribs = 0; vs_index = draw_find_shader_output(llvmpipe->draw, TGSI_SEMANTIC_POSITION, 0); draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, vs_index); for (i = 0; i < lpfs->info.num_inputs; i++) { /* * Search for each input in current vs output: */ vs_index = draw_find_shader_output(llvmpipe->draw, lpfs->info.input_semantic_name[i], lpfs->info.input_semantic_index[i]); if (vs_index < 0) { /* * This can happen with sprite coordinates - the vertex * shader doesn't need to provide an output as we generate * them internally. However, lets keep pretending that there * is something there to not confuse other code. */ vs_index = 0; } /* This can be pre-computed, except for flatshade: */ inputs[i].usage_mask = lpfs->info.input_usage_mask[i]; switch (lpfs->info.input_interpolate[i]) { case TGSI_INTERPOLATE_CONSTANT: inputs[i].interp = LP_INTERP_CONSTANT; break; case TGSI_INTERPOLATE_LINEAR: inputs[i].interp = LP_INTERP_LINEAR; break; case TGSI_INTERPOLATE_PERSPECTIVE: inputs[i].interp = LP_INTERP_PERSPECTIVE; break; default: assert(0); break; } switch (lpfs->info.input_semantic_name[i]) { case TGSI_SEMANTIC_FACE: inputs[i].interp = LP_INTERP_FACING; break; case TGSI_SEMANTIC_POSITION: /* Position was already emitted above */ inputs[i].interp = LP_INTERP_POSITION; inputs[i].src_index = 0; continue; case TGSI_SEMANTIC_COLOR: /* Colors are linearly inputs[i].interpolated in the fragment shader * even when flatshading is active. This just tells the * setup module to use coefficients with ddx==0 and * ddy==0. */ if (llvmpipe->rasterizer->flatshade) inputs[i].interp = LP_INTERP_CONSTANT; break; default: break; } /* * Emit the requested fs attribute for all but position. */ inputs[i].src_index = vinfo->num_attribs; draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, vs_index); } /* Figure out if we need pointsize as well. */ vs_index = draw_find_shader_output(llvmpipe->draw, TGSI_SEMANTIC_PSIZE, 0); if (vs_index > 0) { llvmpipe->psize_slot = vinfo->num_attribs; draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_CONSTANT, vs_index); } llvmpipe->num_inputs = lpfs->info.num_inputs; draw_compute_vertex_size(vinfo); lp_setup_set_vertex_info(llvmpipe->setup, vinfo); lp_setup_set_fs_inputs(llvmpipe->setup, inputs, lpfs->info.num_inputs); }