Path: blob/21.2-virgl/src/gallium/drivers/nouveau/nvc0/nvc0_vbo_translate.c
4574 views
1#include "pipe/p_context.h"2#include "pipe/p_state.h"3#include "util/u_inlines.h"4#include "util/format/u_format.h"5#include "translate/translate.h"67#include "nvc0/nvc0_context.h"8#include "nvc0/nvc0_resource.h"910#include "nvc0/nvc0_3d.xml.h"1112struct push_context {13struct nouveau_pushbuf *push;1415struct translate *translate;16void *dest;17const void *idxbuf;1819uint32_t vertex_size;20uint32_t restart_index;21uint32_t start_instance;22uint32_t instance_id;2324bool prim_restart;25bool need_vertex_id;2627struct {28bool enabled;29bool value;30uint8_t width;31unsigned stride;32const uint8_t *data;33} edgeflag;34};3536static void nvc0_push_upload_vertex_ids(struct push_context *,37struct nvc0_context *,38const struct pipe_draw_info *,39const struct pipe_draw_start_count_bias *draw);4041static void42nvc0_push_context_init(struct nvc0_context *nvc0, struct push_context *ctx)43{44ctx->push = nvc0->base.pushbuf;4546ctx->translate = nvc0->vertex->translate;47ctx->vertex_size = nvc0->vertex->size;48ctx->instance_id = 0;4950ctx->need_vertex_id =51nvc0->vertprog->vp.need_vertex_id && (nvc0->vertex->num_elements < 32);5253ctx->edgeflag.value = true;54ctx->edgeflag.enabled = nvc0->vertprog->vp.edgeflag < PIPE_MAX_ATTRIBS;5556/* silence warnings */57ctx->edgeflag.data = NULL;58ctx->edgeflag.stride = 0;59ctx->edgeflag.width = 0;60}6162static inline void63nvc0_vertex_configure_translate(struct nvc0_context *nvc0, int32_t index_bias)64{65struct translate *translate = nvc0->vertex->translate;66unsigned i;6768for (i = 0; i < nvc0->num_vtxbufs; ++i) {69const uint8_t *map;70const struct pipe_vertex_buffer *vb = &nvc0->vtxbuf[i];7172if (likely(vb->is_user_buffer))73map = (const uint8_t *)vb->buffer.user;74else {75if (!vb->buffer.resource)76continue;7778map = nouveau_resource_map_offset(&nvc0->base,79nv04_resource(vb->buffer.resource), vb->buffer_offset, NOUVEAU_BO_RD);80}8182if (index_bias && !unlikely(nvc0->vertex->instance_bufs & (1 << i)))83map += (intptr_t)index_bias * vb->stride;8485translate->set_buffer(translate, i, map, vb->stride, ~0);86}87}8889static inline void90nvc0_push_map_idxbuf(struct push_context *ctx, struct nvc0_context *nvc0,91const struct pipe_draw_info *info)92{93if (!info->has_user_indices) {94struct nv04_resource *buf = nv04_resource(info->index.resource);95ctx->idxbuf = nouveau_resource_map_offset(96&nvc0->base, buf, 0, NOUVEAU_BO_RD);97} else {98ctx->idxbuf = info->index.user;99}100}101102static inline void103nvc0_push_map_edgeflag(struct push_context *ctx, struct nvc0_context *nvc0,104int32_t index_bias)105{106unsigned attr = nvc0->vertprog->vp.edgeflag;107struct pipe_vertex_element *ve = &nvc0->vertex->element[attr].pipe;108struct pipe_vertex_buffer *vb = &nvc0->vtxbuf[ve->vertex_buffer_index];109struct nv04_resource *buf = nv04_resource(vb->buffer.resource);110111ctx->edgeflag.stride = vb->stride;112ctx->edgeflag.width = util_format_get_blocksize(ve->src_format);113if (!vb->is_user_buffer) {114unsigned offset = vb->buffer_offset + ve->src_offset;115ctx->edgeflag.data = nouveau_resource_map_offset(&nvc0->base,116buf, offset, NOUVEAU_BO_RD);117} else {118ctx->edgeflag.data = (const uint8_t *)vb->buffer.user + ve->src_offset;119}120121if (index_bias)122ctx->edgeflag.data += (intptr_t)index_bias * vb->stride;123}124125static inline unsigned126prim_restart_search_i08(const uint8_t *elts, unsigned push, uint8_t index)127{128unsigned i;129for (i = 0; i < push && elts[i] != index; ++i);130return i;131}132133static inline unsigned134prim_restart_search_i16(const uint16_t *elts, unsigned push, uint16_t index)135{136unsigned i;137for (i = 0; i < push && elts[i] != index; ++i);138return i;139}140141static inline unsigned142prim_restart_search_i32(const uint32_t *elts, unsigned push, uint32_t index)143{144unsigned i;145for (i = 0; i < push && elts[i] != index; ++i);146return i;147}148149static inline bool150ef_value_8(const struct push_context *ctx, uint32_t index)151{152uint8_t *pf = (uint8_t *)&ctx->edgeflag.data[index * ctx->edgeflag.stride];153return !!*pf;154}155156static inline bool157ef_value_32(const struct push_context *ctx, uint32_t index)158{159uint32_t *pf = (uint32_t *)&ctx->edgeflag.data[index * ctx->edgeflag.stride];160return !!*pf;161}162163static inline bool164ef_toggle(struct push_context *ctx)165{166ctx->edgeflag.value = !ctx->edgeflag.value;167return ctx->edgeflag.value;168}169170static inline unsigned171ef_toggle_search_i08(struct push_context *ctx, const uint8_t *elts, unsigned n)172{173unsigned i;174bool ef = ctx->edgeflag.value;175if (ctx->edgeflag.width == 1)176for (i = 0; i < n && ef_value_8(ctx, elts[i]) == ef; ++i);177else178for (i = 0; i < n && ef_value_32(ctx, elts[i]) == ef; ++i);179return i;180}181182static inline unsigned183ef_toggle_search_i16(struct push_context *ctx, const uint16_t *elts, unsigned n)184{185unsigned i;186bool ef = ctx->edgeflag.value;187if (ctx->edgeflag.width == 1)188for (i = 0; i < n && ef_value_8(ctx, elts[i]) == ef; ++i);189else190for (i = 0; i < n && ef_value_32(ctx, elts[i]) == ef; ++i);191return i;192}193194static inline unsigned195ef_toggle_search_i32(struct push_context *ctx, const uint32_t *elts, unsigned n)196{197unsigned i;198bool ef = ctx->edgeflag.value;199if (ctx->edgeflag.width == 1)200for (i = 0; i < n && ef_value_8(ctx, elts[i]) == ef; ++i);201else202for (i = 0; i < n && ef_value_32(ctx, elts[i]) == ef; ++i);203return i;204}205206static inline unsigned207ef_toggle_search_seq(struct push_context *ctx, unsigned start, unsigned n)208{209unsigned i;210bool ef = ctx->edgeflag.value;211if (ctx->edgeflag.width == 1)212for (i = 0; i < n && ef_value_8(ctx, start++) == ef; ++i);213else214for (i = 0; i < n && ef_value_32(ctx, start++) == ef; ++i);215return i;216}217218static inline void *219nvc0_push_setup_vertex_array(struct nvc0_context *nvc0, const unsigned count)220{221struct nouveau_pushbuf *push = nvc0->base.pushbuf;222struct nouveau_bo *bo;223uint64_t va;224const unsigned size = count * nvc0->vertex->size;225226void *const dest = nouveau_scratch_get(&nvc0->base, size, &va, &bo);227228BEGIN_NVC0(push, NVC0_3D(VERTEX_ARRAY_START_HIGH(0)), 2);229PUSH_DATAh(push, va);230PUSH_DATA (push, va);231232if (nvc0->screen->eng3d->oclass < TU102_3D_CLASS)233BEGIN_NVC0(push, NVC0_3D(VERTEX_ARRAY_LIMIT_HIGH(0)), 2);234else235BEGIN_NVC0(push, SUBC_3D(TU102_3D_VERTEX_ARRAY_LIMIT_HIGH(0)), 2);236PUSH_DATAh(push, va + size - 1);237PUSH_DATA (push, va + size - 1);238239BCTX_REFN_bo(nvc0->bufctx_3d, 3D_VTX_TMP, NOUVEAU_BO_GART | NOUVEAU_BO_RD,240bo);241nouveau_pushbuf_validate(push);242243return dest;244}245246static void247disp_vertices_i08(struct push_context *ctx, unsigned start, unsigned count)248{249struct nouveau_pushbuf *push = ctx->push;250struct translate *translate = ctx->translate;251const uint8_t *restrict elts = (uint8_t *)ctx->idxbuf + start;252unsigned pos = 0;253254do {255unsigned nR = count;256257if (unlikely(ctx->prim_restart))258nR = prim_restart_search_i08(elts, nR, ctx->restart_index);259260translate->run_elts8(translate, elts, nR,261ctx->start_instance, ctx->instance_id, ctx->dest);262count -= nR;263ctx->dest += nR * ctx->vertex_size;264265while (nR) {266unsigned nE = nR;267268if (unlikely(ctx->edgeflag.enabled))269nE = ef_toggle_search_i08(ctx, elts, nR);270271PUSH_SPACE(push, 4);272if (likely(nE >= 2)) {273BEGIN_NVC0(push, NVC0_3D(VERTEX_BUFFER_FIRST), 2);274PUSH_DATA (push, pos);275PUSH_DATA (push, nE);276} else277if (nE) {278if (pos <= 0xff) {279IMMED_NVC0(push, NVC0_3D(VB_ELEMENT_U32), pos);280} else {281BEGIN_NVC0(push, NVC0_3D(VB_ELEMENT_U32), 1);282PUSH_DATA (push, pos);283}284}285if (unlikely(nE != nR))286IMMED_NVC0(push, NVC0_3D(EDGEFLAG), ef_toggle(ctx));287288pos += nE;289elts += nE;290nR -= nE;291}292if (count) {293BEGIN_NVC0(push, NVC0_3D(VB_ELEMENT_U32), 1);294PUSH_DATA (push, 0xffffffff);295++elts;296ctx->dest += ctx->vertex_size;297++pos;298--count;299}300} while (count);301}302303static void304disp_vertices_i16(struct push_context *ctx, unsigned start, unsigned count)305{306struct nouveau_pushbuf *push = ctx->push;307struct translate *translate = ctx->translate;308const uint16_t *restrict elts = (uint16_t *)ctx->idxbuf + start;309unsigned pos = 0;310311do {312unsigned nR = count;313314if (unlikely(ctx->prim_restart))315nR = prim_restart_search_i16(elts, nR, ctx->restart_index);316317translate->run_elts16(translate, elts, nR,318ctx->start_instance, ctx->instance_id, ctx->dest);319count -= nR;320ctx->dest += nR * ctx->vertex_size;321322while (nR) {323unsigned nE = nR;324325if (unlikely(ctx->edgeflag.enabled))326nE = ef_toggle_search_i16(ctx, elts, nR);327328PUSH_SPACE(push, 4);329if (likely(nE >= 2)) {330BEGIN_NVC0(push, NVC0_3D(VERTEX_BUFFER_FIRST), 2);331PUSH_DATA (push, pos);332PUSH_DATA (push, nE);333} else334if (nE) {335if (pos <= 0xff) {336IMMED_NVC0(push, NVC0_3D(VB_ELEMENT_U32), pos);337} else {338BEGIN_NVC0(push, NVC0_3D(VB_ELEMENT_U32), 1);339PUSH_DATA (push, pos);340}341}342if (unlikely(nE != nR))343IMMED_NVC0(push, NVC0_3D(EDGEFLAG), ef_toggle(ctx));344345pos += nE;346elts += nE;347nR -= nE;348}349if (count) {350BEGIN_NVC0(push, NVC0_3D(VB_ELEMENT_U32), 1);351PUSH_DATA (push, 0xffffffff);352++elts;353ctx->dest += ctx->vertex_size;354++pos;355--count;356}357} while (count);358}359360static void361disp_vertices_i32(struct push_context *ctx, unsigned start, unsigned count)362{363struct nouveau_pushbuf *push = ctx->push;364struct translate *translate = ctx->translate;365const uint32_t *restrict elts = (uint32_t *)ctx->idxbuf + start;366unsigned pos = 0;367368do {369unsigned nR = count;370371if (unlikely(ctx->prim_restart))372nR = prim_restart_search_i32(elts, nR, ctx->restart_index);373374translate->run_elts(translate, elts, nR,375ctx->start_instance, ctx->instance_id, ctx->dest);376count -= nR;377ctx->dest += nR * ctx->vertex_size;378379while (nR) {380unsigned nE = nR;381382if (unlikely(ctx->edgeflag.enabled))383nE = ef_toggle_search_i32(ctx, elts, nR);384385PUSH_SPACE(push, 4);386if (likely(nE >= 2)) {387BEGIN_NVC0(push, NVC0_3D(VERTEX_BUFFER_FIRST), 2);388PUSH_DATA (push, pos);389PUSH_DATA (push, nE);390} else391if (nE) {392if (pos <= 0xff) {393IMMED_NVC0(push, NVC0_3D(VB_ELEMENT_U32), pos);394} else {395BEGIN_NVC0(push, NVC0_3D(VB_ELEMENT_U32), 1);396PUSH_DATA (push, pos);397}398}399if (unlikely(nE != nR))400IMMED_NVC0(push, NVC0_3D(EDGEFLAG), ef_toggle(ctx));401402pos += nE;403elts += nE;404nR -= nE;405}406if (count) {407BEGIN_NVC0(push, NVC0_3D(VB_ELEMENT_U32), 1);408PUSH_DATA (push, 0xffffffff);409++elts;410ctx->dest += ctx->vertex_size;411++pos;412--count;413}414} while (count);415}416417static void418disp_vertices_seq(struct push_context *ctx, unsigned start, unsigned count)419{420struct nouveau_pushbuf *push = ctx->push;421struct translate *translate = ctx->translate;422unsigned pos = 0;423424/* XXX: This will read the data corresponding to the primitive restart index,425* maybe we should avoid that ?426*/427translate->run(translate, start, count,428ctx->start_instance, ctx->instance_id, ctx->dest);429do {430unsigned nr = count;431432if (unlikely(ctx->edgeflag.enabled))433nr = ef_toggle_search_seq(ctx, start + pos, nr);434435PUSH_SPACE(push, 4);436if (likely(nr)) {437BEGIN_NVC0(push, NVC0_3D(VERTEX_BUFFER_FIRST), 2);438PUSH_DATA (push, pos);439PUSH_DATA (push, nr);440}441if (unlikely(nr != count))442IMMED_NVC0(push, NVC0_3D(EDGEFLAG), ef_toggle(ctx));443444pos += nr;445count -= nr;446} while (count);447}448449450#define NVC0_PRIM_GL_CASE(n) \451case PIPE_PRIM_##n: return NVC0_3D_VERTEX_BEGIN_GL_PRIMITIVE_##n452453static inline unsigned454nvc0_prim_gl(unsigned prim)455{456switch (prim) {457NVC0_PRIM_GL_CASE(POINTS);458NVC0_PRIM_GL_CASE(LINES);459NVC0_PRIM_GL_CASE(LINE_LOOP);460NVC0_PRIM_GL_CASE(LINE_STRIP);461NVC0_PRIM_GL_CASE(TRIANGLES);462NVC0_PRIM_GL_CASE(TRIANGLE_STRIP);463NVC0_PRIM_GL_CASE(TRIANGLE_FAN);464NVC0_PRIM_GL_CASE(QUADS);465NVC0_PRIM_GL_CASE(QUAD_STRIP);466NVC0_PRIM_GL_CASE(POLYGON);467NVC0_PRIM_GL_CASE(LINES_ADJACENCY);468NVC0_PRIM_GL_CASE(LINE_STRIP_ADJACENCY);469NVC0_PRIM_GL_CASE(TRIANGLES_ADJACENCY);470NVC0_PRIM_GL_CASE(TRIANGLE_STRIP_ADJACENCY);471NVC0_PRIM_GL_CASE(PATCHES);472default:473return NVC0_3D_VERTEX_BEGIN_GL_PRIMITIVE_POINTS;474}475}476477typedef struct {478uint32_t count;479uint32_t primCount;480uint32_t first;481uint32_t baseInstance;482} DrawArraysIndirectCommand;483484typedef struct {485uint32_t count;486uint32_t primCount;487uint32_t firstIndex;488int32_t baseVertex;489uint32_t baseInstance;490} DrawElementsIndirectCommand;491492void493nvc0_push_vbo_indirect(struct nvc0_context *nvc0, const struct pipe_draw_info *info,494unsigned drawid_offset,495const struct pipe_draw_indirect_info *indirect,496const struct pipe_draw_start_count_bias *draw)497{498/* The strategy here is to just read the commands from the indirect buffer499* and do the draws. This is suboptimal, but will only happen in the case500* that conversion is required for FIXED or DOUBLE inputs.501*/502struct nvc0_screen *screen = nvc0->screen;503struct nouveau_pushbuf *push = nvc0->base.pushbuf;504struct nv04_resource *buf = nv04_resource(indirect->buffer);505struct nv04_resource *buf_count = nv04_resource(indirect->indirect_draw_count);506unsigned i;507508unsigned draw_count = indirect->draw_count;509if (buf_count) {510uint32_t *count = nouveau_resource_map_offset(511&nvc0->base, buf_count, indirect->indirect_draw_count_offset,512NOUVEAU_BO_RD);513draw_count = *count;514}515516uint8_t *buf_data = nouveau_resource_map_offset(517&nvc0->base, buf, indirect->offset, NOUVEAU_BO_RD);518struct pipe_draw_info single = *info;519struct pipe_draw_start_count_bias sdraw = *draw;520for (i = 0; i < draw_count; i++, buf_data += indirect->stride) {521if (info->index_size) {522DrawElementsIndirectCommand *cmd = (void *)buf_data;523sdraw.start = draw->start + cmd->firstIndex;524sdraw.count = cmd->count;525single.start_instance = cmd->baseInstance;526single.instance_count = cmd->primCount;527sdraw.index_bias = cmd->baseVertex;528} else {529DrawArraysIndirectCommand *cmd = (void *)buf_data;530sdraw.start = cmd->first;531sdraw.count = cmd->count;532single.start_instance = cmd->baseInstance;533single.instance_count = cmd->primCount;534}535536if (nvc0->vertprog->vp.need_draw_parameters) {537PUSH_SPACE(push, 9);538BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 3);539PUSH_DATA (push, NVC0_CB_AUX_SIZE);540PUSH_DATAh(push, screen->uniform_bo->offset + NVC0_CB_AUX_INFO(0));541PUSH_DATA (push, screen->uniform_bo->offset + NVC0_CB_AUX_INFO(0));542BEGIN_1IC0(push, NVC0_3D(CB_POS), 1 + 3);543PUSH_DATA (push, NVC0_CB_AUX_DRAW_INFO);544PUSH_DATA (push, sdraw.index_bias);545PUSH_DATA (push, single.start_instance);546PUSH_DATA (push, drawid_offset + i);547}548549nvc0_push_vbo(nvc0, &single, NULL, &sdraw);550}551552nouveau_resource_unmap(buf);553if (buf_count)554nouveau_resource_unmap(buf_count);555}556557void558nvc0_push_vbo(struct nvc0_context *nvc0, const struct pipe_draw_info *info,559const struct pipe_draw_indirect_info *indirect,560const struct pipe_draw_start_count_bias *draw)561{562struct push_context ctx;563unsigned i, index_size;564unsigned index_bias = info->index_size ? draw->index_bias : 0;565unsigned inst_count = info->instance_count;566unsigned vert_count = draw->count;567unsigned prim;568569nvc0_push_context_init(nvc0, &ctx);570571nvc0_vertex_configure_translate(nvc0, index_bias);572573if (nvc0->state.index_bias) {574/* this is already taken care of by translate */575IMMED_NVC0(ctx.push, NVC0_3D(VB_ELEMENT_BASE), 0);576nvc0->state.index_bias = 0;577}578579if (unlikely(ctx.edgeflag.enabled))580nvc0_push_map_edgeflag(&ctx, nvc0, index_bias);581582ctx.prim_restart = info->primitive_restart;583ctx.restart_index = info->restart_index;584585if (info->primitive_restart) {586/* NOTE: I hope we won't ever need that last index (~0).587* If we do, we have to disable primitive restart here always and588* use END,BEGIN to restart. (XXX: would that affect PrimitiveID ?)589* We could also deactivate PRIM_RESTART_WITH_DRAW_ARRAYS temporarily,590* and add manual restart to disp_vertices_seq.591*/592BEGIN_NVC0(ctx.push, NVC0_3D(PRIM_RESTART_ENABLE), 2);593PUSH_DATA (ctx.push, 1);594PUSH_DATA (ctx.push, info->index_size ? 0xffffffff : info->restart_index);595} else596if (nvc0->state.prim_restart) {597IMMED_NVC0(ctx.push, NVC0_3D(PRIM_RESTART_ENABLE), 0);598}599nvc0->state.prim_restart = info->primitive_restart;600601if (info->index_size) {602nvc0_push_map_idxbuf(&ctx, nvc0, info);603index_size = info->index_size;604} else {605if (unlikely(indirect && indirect->count_from_stream_output)) {606struct pipe_context *pipe = &nvc0->base.pipe;607struct nvc0_so_target *targ;608targ = nvc0_so_target(indirect->count_from_stream_output);609pipe->get_query_result(pipe, targ->pq, true, (void *)&vert_count);610vert_count /= targ->stride;611}612ctx.idxbuf = NULL; /* shut up warnings */613index_size = 0;614}615616ctx.start_instance = info->start_instance;617618prim = nvc0_prim_gl(info->mode);619do {620PUSH_SPACE(ctx.push, 9);621622ctx.dest = nvc0_push_setup_vertex_array(nvc0, vert_count);623if (unlikely(!ctx.dest))624break;625626if (unlikely(ctx.need_vertex_id))627nvc0_push_upload_vertex_ids(&ctx, nvc0, info, draw);628629if (nvc0->screen->eng3d->oclass < GM107_3D_CLASS)630IMMED_NVC0(ctx.push, NVC0_3D(VERTEX_ARRAY_FLUSH), 0);631BEGIN_NVC0(ctx.push, NVC0_3D(VERTEX_BEGIN_GL), 1);632PUSH_DATA (ctx.push, prim);633switch (index_size) {634case 1:635disp_vertices_i08(&ctx, draw->start, vert_count);636break;637case 2:638disp_vertices_i16(&ctx, draw->start, vert_count);639break;640case 4:641disp_vertices_i32(&ctx, draw->start, vert_count);642break;643default:644assert(index_size == 0);645disp_vertices_seq(&ctx, draw->start, vert_count);646break;647}648PUSH_SPACE(ctx.push, 1);649IMMED_NVC0(ctx.push, NVC0_3D(VERTEX_END_GL), 0);650651if (--inst_count) {652prim |= NVC0_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT;653++ctx.instance_id;654}655nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_VTX_TMP);656nouveau_scratch_done(&nvc0->base);657} while (inst_count);658659660/* reset state and unmap buffers (no-op) */661662if (unlikely(!ctx.edgeflag.value)) {663PUSH_SPACE(ctx.push, 1);664IMMED_NVC0(ctx.push, NVC0_3D(EDGEFLAG), 1);665}666667if (unlikely(ctx.need_vertex_id)) {668PUSH_SPACE(ctx.push, 4);669IMMED_NVC0(ctx.push, NVC0_3D(VERTEX_ID_REPLACE), 0);670BEGIN_NVC0(ctx.push, NVC0_3D(VERTEX_ATTRIB_FORMAT(1)), 1);671PUSH_DATA (ctx.push,672NVC0_3D_VERTEX_ATTRIB_FORMAT_CONST |673NVC0_3D_VERTEX_ATTRIB_FORMAT_TYPE_FLOAT |674NVC0_3D_VERTEX_ATTRIB_FORMAT_SIZE_32);675IMMED_NVC0(ctx.push, NVC0_3D(VERTEX_ARRAY_FETCH(1)), 0);676}677678if (info->index_size && !info->has_user_indices)679nouveau_resource_unmap(nv04_resource(info->index.resource));680for (i = 0; i < nvc0->num_vtxbufs; ++i)681nouveau_resource_unmap(nv04_resource(nvc0->vtxbuf[i].buffer.resource));682683NOUVEAU_DRV_STAT(&nvc0->screen->base, draw_calls_fallback_count, 1);684}685686static inline void687copy_indices_u8(uint32_t *dst, const uint8_t *elts, uint32_t bias, unsigned n)688{689unsigned i;690for (i = 0; i < n; ++i)691dst[i] = elts[i] + bias;692}693694static inline void695copy_indices_u16(uint32_t *dst, const uint16_t *elts, uint32_t bias, unsigned n)696{697unsigned i;698for (i = 0; i < n; ++i)699dst[i] = elts[i] + bias;700}701702static inline void703copy_indices_u32(uint32_t *dst, const uint32_t *elts, uint32_t bias, unsigned n)704{705unsigned i;706for (i = 0; i < n; ++i)707dst[i] = elts[i] + bias;708}709710static void711nvc0_push_upload_vertex_ids(struct push_context *ctx,712struct nvc0_context *nvc0,713const struct pipe_draw_info *info,714const struct pipe_draw_start_count_bias *draw)715716{717struct nouveau_pushbuf *push = ctx->push;718struct nouveau_bo *bo;719uint64_t va;720uint32_t *data;721uint32_t format;722unsigned index_size = info->index_size;723unsigned i;724unsigned a = nvc0->vertex->num_elements;725726if (!index_size || draw->index_bias)727index_size = 4;728data = (uint32_t *)nouveau_scratch_get(&nvc0->base,729draw->count * index_size, &va, &bo);730731BCTX_REFN_bo(nvc0->bufctx_3d, 3D_VTX_TMP, NOUVEAU_BO_GART | NOUVEAU_BO_RD,732bo);733nouveau_pushbuf_validate(push);734735if (info->index_size) {736if (!draw->index_bias) {737memcpy(data, ctx->idxbuf, draw->count * index_size);738} else {739switch (info->index_size) {740case 1:741copy_indices_u8(data, ctx->idxbuf, draw->index_bias, draw->count);742break;743case 2:744copy_indices_u16(data, ctx->idxbuf, draw->index_bias, draw->count);745break;746default:747copy_indices_u32(data, ctx->idxbuf, draw->index_bias, draw->count);748break;749}750}751} else {752for (i = 0; i < draw->count; ++i)753data[i] = i + (draw->start + draw->index_bias);754}755756format = (1 << NVC0_3D_VERTEX_ATTRIB_FORMAT_BUFFER__SHIFT) |757NVC0_3D_VERTEX_ATTRIB_FORMAT_TYPE_UINT;758759switch (index_size) {760case 1:761format |= NVC0_3D_VERTEX_ATTRIB_FORMAT_SIZE_8;762break;763case 2:764format |= NVC0_3D_VERTEX_ATTRIB_FORMAT_SIZE_16;765break;766default:767format |= NVC0_3D_VERTEX_ATTRIB_FORMAT_SIZE_32;768break;769}770771PUSH_SPACE(push, 12);772773if (unlikely(nvc0->state.instance_elts & 2)) {774nvc0->state.instance_elts &= ~2;775IMMED_NVC0(push, NVC0_3D(VERTEX_ARRAY_PER_INSTANCE(1)), 0);776}777778BEGIN_NVC0(push, NVC0_3D(VERTEX_ATTRIB_FORMAT(a)), 1);779PUSH_DATA (push, format);780781BEGIN_NVC0(push, NVC0_3D(VERTEX_ARRAY_FETCH(1)), 3);782PUSH_DATA (push, NVC0_3D_VERTEX_ARRAY_FETCH_ENABLE | index_size);783PUSH_DATAh(push, va);784PUSH_DATA (push, va);785786if (nvc0->screen->eng3d->oclass < TU102_3D_CLASS)787BEGIN_NVC0(push, NVC0_3D(VERTEX_ARRAY_LIMIT_HIGH(1)), 2);788else789BEGIN_NVC0(push, SUBC_3D(TU102_3D_VERTEX_ARRAY_LIMIT_HIGH(1)), 2);790PUSH_DATAh(push, va + draw->count * index_size - 1);791PUSH_DATA (push, va + draw->count * index_size - 1);792793#define NVC0_3D_VERTEX_ID_REPLACE_SOURCE_ATTR_X(a) \794(((0x80 + (a) * 0x10) / 4) << NVC0_3D_VERTEX_ID_REPLACE_SOURCE__SHIFT)795796BEGIN_NVC0(push, NVC0_3D(VERTEX_ID_REPLACE), 1);797PUSH_DATA (push, NVC0_3D_VERTEX_ID_REPLACE_SOURCE_ATTR_X(a) | 1);798}799800801