Path: blob/21.2-virgl/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c
4565 views
/**************************************************************************1*2* Copyright 2007 VMware, Inc.3* All Rights Reserved.4*5* Permission is hereby granted, free of charge, to any person obtaining a6* copy of this software and associated documentation files (the7* "Software"), to deal in the Software without restriction, including8* without limitation the rights to use, copy, modify, merge, publish,9* distribute, sub license, and/or sell copies of the Software, and to10* permit persons to whom the Software is furnished to do so, subject to11* the following conditions:12*13* The above copyright notice and this permission notice (including the14* next paragraph) shall be included in all copies or substantial portions15* of the Software.16*17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS18* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF19* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.20* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR21* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,22* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE23* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.24*25**************************************************************************/2627/*28* Authors:29* Keith Whitwell <[email protected]>30*/313233#include "util/u_math.h"34#include "util/u_memory.h"35#include "draw/draw_context.h"36#include "draw/draw_private.h"37#include "draw/draw_vbuf.h"38#include "draw/draw_vertex.h"39#include "draw/draw_pt.h"40#include "draw/draw_vs.h"414243struct fetch_shade_emit;444546/* Prototype fetch, shade, emit-hw-verts all in one go.47*/48struct fetch_shade_emit {49struct draw_pt_middle_end base;50struct draw_context *draw;5152/* Temporaries:53*/54const float *constants;55unsigned pitch[PIPE_MAX_ATTRIBS];56const ubyte *src[PIPE_MAX_ATTRIBS];57unsigned prim;5859struct draw_vs_variant_key key;60struct draw_vs_variant *active;6162const struct vertex_info *vinfo;63};64656667static void68fse_prepare(struct draw_pt_middle_end *middle,69unsigned prim,70unsigned opt,71unsigned *max_vertices)72{73struct fetch_shade_emit *fse = (struct fetch_shade_emit *)middle;74struct draw_context *draw = fse->draw;75unsigned num_vs_inputs = draw->vs.vertex_shader->info.num_inputs;76const struct vertex_info *vinfo;77unsigned i;78unsigned nr_vbs = 0;7980/* Can't support geometry shader on this path.81*/82assert(!draw->gs.geometry_shader);8384draw->render->set_primitive(draw->render, prim);8586/* Must do this after set_primitive() above:87*/88fse->vinfo = vinfo = draw->render->get_vertex_info(draw->render);8990fse->key.output_stride = vinfo->size * 4;91fse->key.nr_outputs = vinfo->num_attribs;92fse->key.nr_inputs = num_vs_inputs;9394fse->key.nr_elements = MAX2(fse->key.nr_outputs, /* outputs - translate to hw format */95fse->key.nr_inputs); /* inputs - fetch from api format */9697fse->key.viewport = !draw->bypass_viewport;98fse->key.clip = draw->clip_xy || draw->clip_z || draw->clip_user;99fse->key.const_vbuffers = 0;100101memset(fse->key.element, 0,102fse->key.nr_elements * sizeof(fse->key.element[0]));103104for (i = 0; i < num_vs_inputs; i++) {105const struct pipe_vertex_element *src = &draw->pt.vertex_element[i];106fse->key.element[i].in.format = src->src_format;107108/* Consider ignoring these, ie make generated programs109* independent of this state:110*/111fse->key.element[i].in.buffer = src->vertex_buffer_index;112fse->key.element[i].in.offset = src->src_offset;113nr_vbs = MAX2(nr_vbs, src->vertex_buffer_index + 1);114}115116for (i = 0; i < 5 && i < nr_vbs; i++) {117if (draw->pt.vertex_buffer[i].stride == 0)118fse->key.const_vbuffers |= (1<<i);119}120121if (0) debug_printf("%s: lookup const_vbuffers: %x\n", __FUNCTION__, fse->key.const_vbuffers);122123{124unsigned dst_offset = 0;125126for (i = 0; i < vinfo->num_attribs; i++) {127unsigned emit_sz = draw_translate_vinfo_size(vinfo->attrib[i].emit);128129/* doesn't handle EMIT_OMIT */130assert(emit_sz != 0);131132/* The elements in the key correspond to vertex shader output133* numbers, not to positions in the hw vertex description --134* that's handled by the output_offset field.135*/136fse->key.element[i].out.format = vinfo->attrib[i].emit;137fse->key.element[i].out.vs_output = vinfo->attrib[i].src_index;138fse->key.element[i].out.offset = dst_offset;139140dst_offset += emit_sz;141assert(fse->key.output_stride >= dst_offset);142}143}144145fse->active = draw_vs_lookup_variant( draw->vs.vertex_shader,146&fse->key );147148if (!fse->active) {149assert(0);150return ;151}152153if (0) debug_printf("%s: found const_vbuffers: %x\n", __FUNCTION__,154fse->active->key.const_vbuffers);155156/* Now set buffer pointers:157*/158for (i = 0; i < draw->pt.nr_vertex_buffers; i++) {159fse->active->set_buffer( fse->active,160i,161((const ubyte *) draw->pt.user.vbuffer[i].map +162draw->pt.vertex_buffer[i].buffer_offset),163draw->pt.vertex_buffer[i].stride,164draw->pt.max_index );165}166167*max_vertices = (draw->render->max_vertex_buffer_bytes /168(vinfo->size * 4));169170/* Probably need to do this somewhere (or fix exec shader not to171* need it):172*/173if (1) {174struct draw_vertex_shader *vs = draw->vs.vertex_shader;175vs->prepare(vs, draw);176}177}178179180static void181fse_bind_parameters(struct draw_pt_middle_end *middle)182{183/* No-op? */184}185186187static void188fse_run_linear(struct draw_pt_middle_end *middle,189unsigned start,190unsigned count,191unsigned prim_flags)192{193struct fetch_shade_emit *fse = (struct fetch_shade_emit *)middle;194struct draw_context *draw = fse->draw;195char *hw_verts;196197/* XXX: need to flush to get prim_vbuf.c to release its allocation??198*/199draw_do_flush( draw, DRAW_FLUSH_BACKEND );200201if (!draw->render->allocate_vertices( draw->render,202(ushort)fse->key.output_stride,203(ushort)count ))204goto fail;205206hw_verts = draw->render->map_vertices( draw->render );207if (!hw_verts)208goto fail;209210/* Single routine to fetch vertices, run shader and emit HW verts.211* Clipping is done elsewhere -- either by the API or on hardware,212* or for some other reason not required...213*/214fse->active->run_linear( fse->active,215start, count,216hw_verts );217218if (0) {219unsigned i;220for (i = 0; i < count; i++) {221debug_printf("\n\n%s vertex %d: (stride %d, offset %d)\n", __FUNCTION__, i,222fse->key.output_stride,223fse->key.output_stride * i);224225draw_dump_emitted_vertex( fse->vinfo,226(const uint8_t *)hw_verts + fse->key.output_stride * i );227}228}229230draw->render->unmap_vertices( draw->render, 0, (ushort)(count - 1) );231232/* Draw arrays path to avoid re-emitting index list again and233* again.234*/235draw->render->draw_arrays( draw->render,2360,237count );238239draw->render->release_vertices( draw->render );240241return;242243fail:244debug_warn_once("allocate or map of vertex buffer failed (out of memory?)");245return;246}247248249static void250fse_run(struct draw_pt_middle_end *middle,251const unsigned *fetch_elts,252unsigned fetch_count,253const ushort *draw_elts,254unsigned draw_count,255unsigned prim_flags )256{257struct fetch_shade_emit *fse = (struct fetch_shade_emit *)middle;258struct draw_context *draw = fse->draw;259void *hw_verts;260261/* XXX: need to flush to get prim_vbuf.c to release its allocation??262*/263draw_do_flush( draw, DRAW_FLUSH_BACKEND );264265if (!draw->render->allocate_vertices( draw->render,266(ushort)fse->key.output_stride,267(ushort)fetch_count ))268goto fail;269270hw_verts = draw->render->map_vertices( draw->render );271if (!hw_verts)272goto fail;273274/* Single routine to fetch vertices, run shader and emit HW verts.275*/276fse->active->run_elts( fse->active,277fetch_elts,278fetch_count,279hw_verts );280281if (0) {282unsigned i;283for (i = 0; i < fetch_count; i++) {284debug_printf("\n\n%s vertex %d:\n", __FUNCTION__, i);285draw_dump_emitted_vertex( fse->vinfo,286(const uint8_t *)hw_verts +287fse->key.output_stride * i );288}289}290291draw->render->unmap_vertices( draw->render, 0, (ushort)(fetch_count - 1) );292293draw->render->draw_elements( draw->render,294draw_elts,295draw_count );296297draw->render->release_vertices( draw->render );298return;299300fail:301debug_warn_once("allocate or map of vertex buffer failed (out of memory?)");302return;303}304305306307static boolean308fse_run_linear_elts(struct draw_pt_middle_end *middle,309unsigned start,310unsigned count,311const ushort *draw_elts,312unsigned draw_count,313unsigned prim_flags)314{315struct fetch_shade_emit *fse = (struct fetch_shade_emit *)middle;316struct draw_context *draw = fse->draw;317char *hw_verts;318319/* XXX: need to flush to get prim_vbuf.c to release its allocation??320*/321draw_do_flush( draw, DRAW_FLUSH_BACKEND );322323if (!draw->render->allocate_vertices( draw->render,324(ushort)fse->key.output_stride,325(ushort)count ))326return FALSE;327328hw_verts = draw->render->map_vertices( draw->render );329if (!hw_verts)330return FALSE;331332/* Single routine to fetch vertices, run shader and emit HW verts.333* Clipping is done elsewhere -- either by the API or on hardware,334* or for some other reason not required...335*/336fse->active->run_linear( fse->active,337start, count,338hw_verts );339340draw->render->draw_elements( draw->render,341draw_elts,342draw_count );343344draw->render->unmap_vertices( draw->render, 0, (ushort)(count - 1) );345346draw->render->release_vertices( draw->render );347348return TRUE;349}350351352353static void354fse_finish(struct draw_pt_middle_end *middle)355{356}357358359static void360fse_destroy(struct draw_pt_middle_end *middle)361{362FREE(middle);363}364365366struct draw_pt_middle_end *367draw_pt_middle_fse(struct draw_context *draw)368{369struct fetch_shade_emit *fse = CALLOC_STRUCT(fetch_shade_emit);370if (!fse)371return NULL;372373fse->base.prepare = fse_prepare;374fse->base.bind_parameters = fse_bind_parameters;375fse->base.run = fse_run;376fse->base.run_linear = fse_run_linear;377fse->base.run_linear_elts = fse_run_linear_elts;378fse->base.finish = fse_finish;379fse->base.destroy = fse_destroy;380fse->draw = draw;381382return &fse->base;383}384385386