Path: blob/21.2-virgl/src/gallium/drivers/nouveau/nv50/nv50_push.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 "nv50/nv50_context.h"8#include "nv50/nv50_resource.h"910#include "nv50/nv50_3d.xml.h"1112struct push_context {13struct nouveau_pushbuf *push;1415const void *idxbuf;1617float edgeflag;18int edgeflag_attr;1920uint32_t vertex_words;21uint32_t packet_vertex_limit;2223struct translate *translate;2425bool primitive_restart;2627bool need_vertex_id;28int32_t index_bias;2930uint32_t prim;31uint32_t restart_index;32uint32_t start_instance;33uint32_t instance_id;34};3536static inline unsigned37prim_restart_search_i08(uint8_t *elts, unsigned push, uint8_t index)38{39unsigned i;40for (i = 0; i < push; ++i)41if (elts[i] == index)42break;43return i;44}4546static inline unsigned47prim_restart_search_i16(uint16_t *elts, unsigned push, uint16_t index)48{49unsigned i;50for (i = 0; i < push; ++i)51if (elts[i] == index)52break;53return i;54}5556static inline unsigned57prim_restart_search_i32(uint32_t *elts, unsigned push, uint32_t index)58{59unsigned i;60for (i = 0; i < push; ++i)61if (elts[i] == index)62break;63return i;64}6566static void67emit_vertices_i08(struct push_context *ctx, unsigned start, unsigned count)68{69uint8_t *elts = (uint8_t *)ctx->idxbuf + start;7071while (count) {72unsigned push = MIN2(count, ctx->packet_vertex_limit);73unsigned size, nr;7475nr = push;76if (ctx->primitive_restart)77nr = prim_restart_search_i08(elts, push, ctx->restart_index);7879size = ctx->vertex_words * nr;8081if (unlikely(ctx->need_vertex_id)) {82BEGIN_NV04(ctx->push, NV84_3D(VERTEX_ID_BASE), 1);83PUSH_DATA (ctx->push, *elts + ctx->index_bias);84}8586BEGIN_NI04(ctx->push, NV50_3D(VERTEX_DATA), size);8788ctx->translate->run_elts8(ctx->translate, elts, nr,89ctx->start_instance, ctx->instance_id,90ctx->push->cur);9192ctx->push->cur += size;93count -= nr;94elts += nr;9596if (nr != push) {97count--;98elts++;99BEGIN_NV04(ctx->push, NV50_3D(VB_ELEMENT_U32), 1);100PUSH_DATA (ctx->push, ctx->restart_index);101}102}103}104105static void106emit_vertices_i16(struct push_context *ctx, unsigned start, unsigned count)107{108uint16_t *elts = (uint16_t *)ctx->idxbuf + start;109110while (count) {111unsigned push = MIN2(count, ctx->packet_vertex_limit);112unsigned size, nr;113114nr = push;115if (ctx->primitive_restart)116nr = prim_restart_search_i16(elts, push, ctx->restart_index);117118size = ctx->vertex_words * nr;119120if (unlikely(ctx->need_vertex_id)) {121BEGIN_NV04(ctx->push, NV84_3D(VERTEX_ID_BASE), 1);122PUSH_DATA (ctx->push, *elts + ctx->index_bias);123}124125BEGIN_NI04(ctx->push, NV50_3D(VERTEX_DATA), size);126127ctx->translate->run_elts16(ctx->translate, elts, nr,128ctx->start_instance, ctx->instance_id,129ctx->push->cur);130131ctx->push->cur += size;132count -= nr;133elts += nr;134135if (nr != push) {136count--;137elts++;138BEGIN_NV04(ctx->push, NV50_3D(VB_ELEMENT_U32), 1);139PUSH_DATA (ctx->push, ctx->restart_index);140}141}142}143144static void145emit_vertices_i32(struct push_context *ctx, unsigned start, unsigned count)146{147uint32_t *elts = (uint32_t *)ctx->idxbuf + start;148149while (count) {150unsigned push = MIN2(count, ctx->packet_vertex_limit);151unsigned size, nr;152153nr = push;154if (ctx->primitive_restart)155nr = prim_restart_search_i32(elts, push, ctx->restart_index);156157size = ctx->vertex_words * nr;158159if (unlikely(ctx->need_vertex_id)) {160BEGIN_NV04(ctx->push, NV84_3D(VERTEX_ID_BASE), 1);161PUSH_DATA (ctx->push, *elts + ctx->index_bias);162}163164BEGIN_NI04(ctx->push, NV50_3D(VERTEX_DATA), size);165166ctx->translate->run_elts(ctx->translate, elts, nr,167ctx->start_instance, ctx->instance_id,168ctx->push->cur);169170ctx->push->cur += size;171count -= nr;172elts += nr;173174if (nr != push) {175count--;176elts++;177BEGIN_NV04(ctx->push, NV50_3D(VB_ELEMENT_U32), 1);178PUSH_DATA (ctx->push, ctx->restart_index);179}180}181}182183static void184emit_vertices_seq(struct push_context *ctx, unsigned start, unsigned count)185{186uint32_t elts = 0;187188while (count) {189unsigned push = MIN2(count, ctx->packet_vertex_limit);190unsigned size = ctx->vertex_words * push;191192if (unlikely(ctx->need_vertex_id)) {193/* For non-indexed draws, gl_VertexID goes up after each vertex. */194BEGIN_NV04(ctx->push, NV84_3D(VERTEX_ID_BASE), 1);195PUSH_DATA (ctx->push, elts++);196}197198BEGIN_NI04(ctx->push, NV50_3D(VERTEX_DATA), size);199200ctx->translate->run(ctx->translate, start, push,201ctx->start_instance, ctx->instance_id,202ctx->push->cur);203ctx->push->cur += size;204count -= push;205start += push;206}207}208209210#define NV50_PRIM_GL_CASE(n) \211case PIPE_PRIM_##n: return NV50_3D_VERTEX_BEGIN_GL_PRIMITIVE_##n212213static inline unsigned214nv50_prim_gl(unsigned prim)215{216switch (prim) {217NV50_PRIM_GL_CASE(POINTS);218NV50_PRIM_GL_CASE(LINES);219NV50_PRIM_GL_CASE(LINE_LOOP);220NV50_PRIM_GL_CASE(LINE_STRIP);221NV50_PRIM_GL_CASE(TRIANGLES);222NV50_PRIM_GL_CASE(TRIANGLE_STRIP);223NV50_PRIM_GL_CASE(TRIANGLE_FAN);224NV50_PRIM_GL_CASE(QUADS);225NV50_PRIM_GL_CASE(QUAD_STRIP);226NV50_PRIM_GL_CASE(POLYGON);227NV50_PRIM_GL_CASE(LINES_ADJACENCY);228NV50_PRIM_GL_CASE(LINE_STRIP_ADJACENCY);229NV50_PRIM_GL_CASE(TRIANGLES_ADJACENCY);230NV50_PRIM_GL_CASE(TRIANGLE_STRIP_ADJACENCY);231/*232NV50_PRIM_GL_CASE(PATCHES); */233default:234return NV50_3D_VERTEX_BEGIN_GL_PRIMITIVE_POINTS;235break;236}237}238239void240nv50_push_vbo(struct nv50_context *nv50, const struct pipe_draw_info *info,241const struct pipe_draw_indirect_info *indirect,242const struct pipe_draw_start_count_bias *draw)243{244struct push_context ctx;245unsigned i, index_size;246unsigned inst_count = info->instance_count;247unsigned vert_count = draw->count;248bool apply_bias = info->index_size && draw->index_bias;249250ctx.push = nv50->base.pushbuf;251ctx.translate = nv50->vertex->translate;252253ctx.need_vertex_id = nv50->screen->base.class_3d >= NV84_3D_CLASS &&254nv50->vertprog->vp.need_vertex_id && (nv50->vertex->num_elements < 32);255ctx.index_bias = info->index_size ? draw->index_bias : 0;256ctx.instance_id = 0;257258/* For indexed draws, gl_VertexID must be emitted for every vertex. */259ctx.packet_vertex_limit =260ctx.need_vertex_id ? 1 : nv50->vertex->packet_vertex_limit;261ctx.vertex_words = nv50->vertex->vertex_size;262263assert(nv50->num_vtxbufs <= PIPE_MAX_ATTRIBS);264for (i = 0; i < nv50->num_vtxbufs; ++i) {265const struct pipe_vertex_buffer *vb = &nv50->vtxbuf[i];266const uint8_t *data;267268if (unlikely(!vb->is_user_buffer)) {269if (!vb->buffer.resource)270continue;271272data = nouveau_resource_map_offset(&nv50->base,273nv04_resource(vb->buffer.resource), vb->buffer_offset, NOUVEAU_BO_RD);274} else275data = vb->buffer.user;276277if (apply_bias && likely(!(nv50->vertex->instance_bufs & (1 << i))))278data += (ptrdiff_t)(info->index_size ? draw->index_bias : 0) * vb->stride;279280ctx.translate->set_buffer(ctx.translate, i, data, vb->stride, ~0);281}282283if (info->index_size) {284if (!info->has_user_indices) {285ctx.idxbuf = nouveau_resource_map_offset(&nv50->base,286nv04_resource(info->index.resource), 0, NOUVEAU_BO_RD);287} else {288ctx.idxbuf = info->index.user;289}290if (!ctx.idxbuf)291return;292index_size = info->index_size;293ctx.primitive_restart = info->primitive_restart;294ctx.restart_index = info->restart_index;295} else {296if (unlikely(indirect && indirect->count_from_stream_output)) {297struct pipe_context *pipe = &nv50->base.pipe;298struct nv50_so_target *targ;299targ = nv50_so_target(indirect->count_from_stream_output);300if (!targ->pq) {301NOUVEAU_ERR("draw_stream_output not supported on pre-NVA0 cards\n");302return;303}304pipe->get_query_result(pipe, targ->pq, true, (void *)&vert_count);305vert_count /= targ->stride;306}307ctx.idxbuf = NULL;308index_size = 0;309ctx.primitive_restart = false;310ctx.restart_index = 0;311}312313ctx.start_instance = info->start_instance;314ctx.prim = nv50_prim_gl(info->mode);315316if (info->primitive_restart) {317BEGIN_NV04(ctx.push, NV50_3D(PRIM_RESTART_ENABLE), 2);318PUSH_DATA (ctx.push, 1);319PUSH_DATA (ctx.push, info->restart_index);320} else321if (nv50->state.prim_restart) {322BEGIN_NV04(ctx.push, NV50_3D(PRIM_RESTART_ENABLE), 1);323PUSH_DATA (ctx.push, 0);324}325nv50->state.prim_restart = info->primitive_restart;326327while (inst_count--) {328BEGIN_NV04(ctx.push, NV50_3D(VERTEX_BEGIN_GL), 1);329PUSH_DATA (ctx.push, ctx.prim);330switch (index_size) {331case 0:332emit_vertices_seq(&ctx, draw->start, vert_count);333break;334case 1:335emit_vertices_i08(&ctx, draw->start, vert_count);336break;337case 2:338emit_vertices_i16(&ctx, draw->start, vert_count);339break;340case 4:341emit_vertices_i32(&ctx, draw->start, vert_count);342break;343default:344assert(0);345break;346}347BEGIN_NV04(ctx.push, NV50_3D(VERTEX_END_GL), 1);348PUSH_DATA (ctx.push, 0);349350ctx.instance_id++;351ctx.prim |= NV50_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT;352}353354if (unlikely(ctx.need_vertex_id)) {355/* Reset gl_VertexID to prevent future indexed draws to be confused. */356BEGIN_NV04(ctx.push, NV84_3D(VERTEX_ID_BASE), 1);357PUSH_DATA (ctx.push, nv50->state.index_bias);358}359}360361362