1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright 2010 Christoph Bumiller 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be included in 12bf215546Sopenharmony_ci * all copies or substantial portions of the Software. 13bf215546Sopenharmony_ci * 14bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 18bf215546Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19bf215546Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20bf215546Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE. 21bf215546Sopenharmony_ci */ 22bf215546Sopenharmony_ci 23bf215546Sopenharmony_ci#define NVC0_PUSH_EXPLICIT_SPACE_CHECKING 24bf215546Sopenharmony_ci 25bf215546Sopenharmony_ci#include "pipe/p_context.h" 26bf215546Sopenharmony_ci#include "pipe/p_state.h" 27bf215546Sopenharmony_ci#include "util/u_draw.h" 28bf215546Sopenharmony_ci#include "util/u_inlines.h" 29bf215546Sopenharmony_ci#include "util/format/u_format.h" 30bf215546Sopenharmony_ci#include "translate/translate.h" 31bf215546Sopenharmony_ci 32bf215546Sopenharmony_ci#include "nvc0/nvc0_context.h" 33bf215546Sopenharmony_ci#include "nvc0/nvc0_query_hw.h" 34bf215546Sopenharmony_ci#include "nvc0/nvc0_resource.h" 35bf215546Sopenharmony_ci 36bf215546Sopenharmony_ci#include "nvc0/nvc0_3d.xml.h" 37bf215546Sopenharmony_ci 38bf215546Sopenharmony_civoid 39bf215546Sopenharmony_cinvc0_vertex_state_delete(struct pipe_context *pipe, 40bf215546Sopenharmony_ci void *hwcso) 41bf215546Sopenharmony_ci{ 42bf215546Sopenharmony_ci struct nvc0_vertex_stateobj *so = hwcso; 43bf215546Sopenharmony_ci 44bf215546Sopenharmony_ci if (so->translate) 45bf215546Sopenharmony_ci so->translate->release(so->translate); 46bf215546Sopenharmony_ci FREE(hwcso); 47bf215546Sopenharmony_ci} 48bf215546Sopenharmony_ci 49bf215546Sopenharmony_civoid * 50bf215546Sopenharmony_cinvc0_vertex_state_create(struct pipe_context *pipe, 51bf215546Sopenharmony_ci unsigned num_elements, 52bf215546Sopenharmony_ci const struct pipe_vertex_element *elements) 53bf215546Sopenharmony_ci{ 54bf215546Sopenharmony_ci struct nvc0_vertex_stateobj *so; 55bf215546Sopenharmony_ci struct translate_key transkey; 56bf215546Sopenharmony_ci unsigned i; 57bf215546Sopenharmony_ci unsigned src_offset_max = 0; 58bf215546Sopenharmony_ci 59bf215546Sopenharmony_ci so = MALLOC(sizeof(*so) + 60bf215546Sopenharmony_ci num_elements * sizeof(struct nvc0_vertex_element)); 61bf215546Sopenharmony_ci if (!so) 62bf215546Sopenharmony_ci return NULL; 63bf215546Sopenharmony_ci so->num_elements = num_elements; 64bf215546Sopenharmony_ci so->instance_elts = 0; 65bf215546Sopenharmony_ci so->instance_bufs = 0; 66bf215546Sopenharmony_ci so->shared_slots = false; 67bf215546Sopenharmony_ci so->need_conversion = false; 68bf215546Sopenharmony_ci 69bf215546Sopenharmony_ci memset(so->vb_access_size, 0, sizeof(so->vb_access_size)); 70bf215546Sopenharmony_ci 71bf215546Sopenharmony_ci for (i = 0; i < PIPE_MAX_ATTRIBS; ++i) 72bf215546Sopenharmony_ci so->min_instance_div[i] = 0xffffffff; 73bf215546Sopenharmony_ci 74bf215546Sopenharmony_ci transkey.nr_elements = 0; 75bf215546Sopenharmony_ci transkey.output_stride = 0; 76bf215546Sopenharmony_ci 77bf215546Sopenharmony_ci for (i = 0; i < num_elements; ++i) { 78bf215546Sopenharmony_ci const struct pipe_vertex_element *ve = &elements[i]; 79bf215546Sopenharmony_ci const unsigned vbi = ve->vertex_buffer_index; 80bf215546Sopenharmony_ci unsigned size; 81bf215546Sopenharmony_ci enum pipe_format fmt = ve->src_format; 82bf215546Sopenharmony_ci 83bf215546Sopenharmony_ci so->element[i].pipe = elements[i]; 84bf215546Sopenharmony_ci so->element[i].state = nvc0_vertex_format[fmt].vtx; 85bf215546Sopenharmony_ci 86bf215546Sopenharmony_ci if (!so->element[i].state) { 87bf215546Sopenharmony_ci switch (util_format_get_nr_components(fmt)) { 88bf215546Sopenharmony_ci case 1: fmt = PIPE_FORMAT_R32_FLOAT; break; 89bf215546Sopenharmony_ci case 2: fmt = PIPE_FORMAT_R32G32_FLOAT; break; 90bf215546Sopenharmony_ci case 3: fmt = PIPE_FORMAT_R32G32B32_FLOAT; break; 91bf215546Sopenharmony_ci case 4: fmt = PIPE_FORMAT_R32G32B32A32_FLOAT; break; 92bf215546Sopenharmony_ci default: 93bf215546Sopenharmony_ci assert(0); 94bf215546Sopenharmony_ci FREE(so); 95bf215546Sopenharmony_ci return NULL; 96bf215546Sopenharmony_ci } 97bf215546Sopenharmony_ci so->element[i].state = nvc0_vertex_format[fmt].vtx; 98bf215546Sopenharmony_ci so->need_conversion = true; 99bf215546Sopenharmony_ci util_debug_message(&nouveau_context(pipe)->debug, FALLBACK, 100bf215546Sopenharmony_ci "Converting vertex element %d, no hw format %s", 101bf215546Sopenharmony_ci i, util_format_name(ve->src_format)); 102bf215546Sopenharmony_ci } 103bf215546Sopenharmony_ci size = util_format_get_blocksize(fmt); 104bf215546Sopenharmony_ci 105bf215546Sopenharmony_ci src_offset_max = MAX2(src_offset_max, ve->src_offset); 106bf215546Sopenharmony_ci 107bf215546Sopenharmony_ci if (so->vb_access_size[vbi] < (ve->src_offset + size)) 108bf215546Sopenharmony_ci so->vb_access_size[vbi] = ve->src_offset + size; 109bf215546Sopenharmony_ci 110bf215546Sopenharmony_ci if (unlikely(ve->instance_divisor)) { 111bf215546Sopenharmony_ci so->instance_elts |= 1 << i; 112bf215546Sopenharmony_ci so->instance_bufs |= 1 << vbi; 113bf215546Sopenharmony_ci if (ve->instance_divisor < so->min_instance_div[vbi]) 114bf215546Sopenharmony_ci so->min_instance_div[vbi] = ve->instance_divisor; 115bf215546Sopenharmony_ci } 116bf215546Sopenharmony_ci 117bf215546Sopenharmony_ci if (1) { 118bf215546Sopenharmony_ci unsigned ca; 119bf215546Sopenharmony_ci unsigned j = transkey.nr_elements++; 120bf215546Sopenharmony_ci 121bf215546Sopenharmony_ci ca = util_format_description(fmt)->channel[0].size / 8; 122bf215546Sopenharmony_ci if (ca != 1 && ca != 2) 123bf215546Sopenharmony_ci ca = 4; 124bf215546Sopenharmony_ci 125bf215546Sopenharmony_ci transkey.element[j].type = TRANSLATE_ELEMENT_NORMAL; 126bf215546Sopenharmony_ci transkey.element[j].input_format = ve->src_format; 127bf215546Sopenharmony_ci transkey.element[j].input_buffer = vbi; 128bf215546Sopenharmony_ci transkey.element[j].input_offset = ve->src_offset; 129bf215546Sopenharmony_ci transkey.element[j].instance_divisor = ve->instance_divisor; 130bf215546Sopenharmony_ci 131bf215546Sopenharmony_ci transkey.output_stride = align(transkey.output_stride, ca); 132bf215546Sopenharmony_ci transkey.element[j].output_format = fmt; 133bf215546Sopenharmony_ci transkey.element[j].output_offset = transkey.output_stride; 134bf215546Sopenharmony_ci transkey.output_stride += size; 135bf215546Sopenharmony_ci 136bf215546Sopenharmony_ci so->element[i].state_alt = so->element[i].state; 137bf215546Sopenharmony_ci so->element[i].state_alt |= transkey.element[j].output_offset << 7; 138bf215546Sopenharmony_ci } 139bf215546Sopenharmony_ci 140bf215546Sopenharmony_ci so->element[i].state |= i << NVC0_3D_VERTEX_ATTRIB_FORMAT_BUFFER__SHIFT; 141bf215546Sopenharmony_ci } 142bf215546Sopenharmony_ci transkey.output_stride = align(transkey.output_stride, 4); 143bf215546Sopenharmony_ci 144bf215546Sopenharmony_ci so->size = transkey.output_stride; 145bf215546Sopenharmony_ci so->translate = translate_create(&transkey); 146bf215546Sopenharmony_ci 147bf215546Sopenharmony_ci if (so->instance_elts || src_offset_max >= (1 << 14)) 148bf215546Sopenharmony_ci return so; 149bf215546Sopenharmony_ci so->shared_slots = true; 150bf215546Sopenharmony_ci 151bf215546Sopenharmony_ci for (i = 0; i < num_elements; ++i) { 152bf215546Sopenharmony_ci const unsigned b = elements[i].vertex_buffer_index; 153bf215546Sopenharmony_ci const unsigned s = elements[i].src_offset; 154bf215546Sopenharmony_ci so->element[i].state &= ~NVC0_3D_VERTEX_ATTRIB_FORMAT_BUFFER__MASK; 155bf215546Sopenharmony_ci so->element[i].state |= b << NVC0_3D_VERTEX_ATTRIB_FORMAT_BUFFER__SHIFT; 156bf215546Sopenharmony_ci so->element[i].state |= s << NVC0_3D_VERTEX_ATTRIB_FORMAT_OFFSET__SHIFT; 157bf215546Sopenharmony_ci } 158bf215546Sopenharmony_ci return so; 159bf215546Sopenharmony_ci} 160bf215546Sopenharmony_ci 161bf215546Sopenharmony_ci#define NVC0_3D_VERTEX_ATTRIB_INACTIVE \ 162bf215546Sopenharmony_ci NVC0_3D_VERTEX_ATTRIB_FORMAT_TYPE_FLOAT | \ 163bf215546Sopenharmony_ci NVC0_3D_VERTEX_ATTRIB_FORMAT_SIZE_32 | NVC0_3D_VERTEX_ATTRIB_FORMAT_CONST 164bf215546Sopenharmony_ci 165bf215546Sopenharmony_ci#define VTX_ATTR(a, c, t, s) \ 166bf215546Sopenharmony_ci ((NVC0_3D_VTX_ATTR_DEFINE_TYPE_##t) | \ 167bf215546Sopenharmony_ci (NVC0_3D_VTX_ATTR_DEFINE_SIZE_##s) | \ 168bf215546Sopenharmony_ci ((a) << NVC0_3D_VTX_ATTR_DEFINE_ATTR__SHIFT) | \ 169bf215546Sopenharmony_ci ((c) << NVC0_3D_VTX_ATTR_DEFINE_COMP__SHIFT)) 170bf215546Sopenharmony_ci 171bf215546Sopenharmony_cistatic void 172bf215546Sopenharmony_cinvc0_set_constant_vertex_attrib(struct nvc0_context *nvc0, const unsigned a) 173bf215546Sopenharmony_ci{ 174bf215546Sopenharmony_ci struct nouveau_pushbuf *push = nvc0->base.pushbuf; 175bf215546Sopenharmony_ci struct pipe_vertex_element *ve = &nvc0->vertex->element[a].pipe; 176bf215546Sopenharmony_ci struct pipe_vertex_buffer *vb = &nvc0->vtxbuf[ve->vertex_buffer_index]; 177bf215546Sopenharmony_ci uint32_t mode; 178bf215546Sopenharmony_ci const struct util_format_description *desc; 179bf215546Sopenharmony_ci void *dst; 180bf215546Sopenharmony_ci const void *src = (const uint8_t *)vb->buffer.user + ve->src_offset; 181bf215546Sopenharmony_ci assert(vb->is_user_buffer); 182bf215546Sopenharmony_ci 183bf215546Sopenharmony_ci desc = util_format_description(ve->src_format); 184bf215546Sopenharmony_ci 185bf215546Sopenharmony_ci PUSH_SPACE(push, 6); 186bf215546Sopenharmony_ci BEGIN_NVC0(push, NVC0_3D(VTX_ATTR_DEFINE), 5); 187bf215546Sopenharmony_ci dst = &push->cur[1]; 188bf215546Sopenharmony_ci util_format_unpack_rgba(ve->src_format, dst, src, 1); 189bf215546Sopenharmony_ci if (desc->channel[0].pure_integer) { 190bf215546Sopenharmony_ci if (desc->channel[0].type == UTIL_FORMAT_TYPE_SIGNED) { 191bf215546Sopenharmony_ci mode = VTX_ATTR(a, 4, SINT, 32); 192bf215546Sopenharmony_ci } else { 193bf215546Sopenharmony_ci mode = VTX_ATTR(a, 4, UINT, 32); 194bf215546Sopenharmony_ci } 195bf215546Sopenharmony_ci } else { 196bf215546Sopenharmony_ci mode = VTX_ATTR(a, 4, FLOAT, 32); 197bf215546Sopenharmony_ci } 198bf215546Sopenharmony_ci push->cur[0] = mode; 199bf215546Sopenharmony_ci push->cur += 5; 200bf215546Sopenharmony_ci} 201bf215546Sopenharmony_ci 202bf215546Sopenharmony_cistatic inline void 203bf215546Sopenharmony_cinvc0_user_vbuf_range(struct nvc0_context *nvc0, int vbi, 204bf215546Sopenharmony_ci uint32_t *base, uint32_t *size) 205bf215546Sopenharmony_ci{ 206bf215546Sopenharmony_ci if (unlikely(nvc0->vertex->instance_bufs & (1 << vbi))) { 207bf215546Sopenharmony_ci const uint32_t div = nvc0->vertex->min_instance_div[vbi]; 208bf215546Sopenharmony_ci *base = nvc0->instance_off * nvc0->vtxbuf[vbi].stride; 209bf215546Sopenharmony_ci *size = (nvc0->instance_max / div) * nvc0->vtxbuf[vbi].stride + 210bf215546Sopenharmony_ci nvc0->vertex->vb_access_size[vbi]; 211bf215546Sopenharmony_ci } else { 212bf215546Sopenharmony_ci /* NOTE: if there are user buffers, we *must* have index bounds */ 213bf215546Sopenharmony_ci assert(nvc0->vb_elt_limit != ~0); 214bf215546Sopenharmony_ci *base = nvc0->vb_elt_first * nvc0->vtxbuf[vbi].stride; 215bf215546Sopenharmony_ci *size = nvc0->vb_elt_limit * nvc0->vtxbuf[vbi].stride + 216bf215546Sopenharmony_ci nvc0->vertex->vb_access_size[vbi]; 217bf215546Sopenharmony_ci } 218bf215546Sopenharmony_ci} 219bf215546Sopenharmony_ci 220bf215546Sopenharmony_cistatic inline void 221bf215546Sopenharmony_cinvc0_release_user_vbufs(struct nvc0_context *nvc0) 222bf215546Sopenharmony_ci{ 223bf215546Sopenharmony_ci if (nvc0->vbo_user) { 224bf215546Sopenharmony_ci nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_VTX_TMP); 225bf215546Sopenharmony_ci nouveau_scratch_done(&nvc0->base); 226bf215546Sopenharmony_ci } 227bf215546Sopenharmony_ci} 228bf215546Sopenharmony_ci 229bf215546Sopenharmony_cistatic void 230bf215546Sopenharmony_cinvc0_update_user_vbufs(struct nvc0_context *nvc0) 231bf215546Sopenharmony_ci{ 232bf215546Sopenharmony_ci uint64_t address[PIPE_MAX_ATTRIBS]; 233bf215546Sopenharmony_ci struct nouveau_pushbuf *push = nvc0->base.pushbuf; 234bf215546Sopenharmony_ci int i; 235bf215546Sopenharmony_ci uint32_t written = 0; 236bf215546Sopenharmony_ci 237bf215546Sopenharmony_ci PUSH_SPACE(push, nvc0->vertex->num_elements * 8); 238bf215546Sopenharmony_ci for (i = 0; i < nvc0->vertex->num_elements; ++i) { 239bf215546Sopenharmony_ci struct pipe_vertex_element *ve = &nvc0->vertex->element[i].pipe; 240bf215546Sopenharmony_ci const unsigned b = ve->vertex_buffer_index; 241bf215546Sopenharmony_ci struct pipe_vertex_buffer *vb = &nvc0->vtxbuf[b]; 242bf215546Sopenharmony_ci uint32_t base, size; 243bf215546Sopenharmony_ci 244bf215546Sopenharmony_ci if (!(nvc0->vbo_user & (1 << b))) 245bf215546Sopenharmony_ci continue; 246bf215546Sopenharmony_ci if (nvc0->constant_vbos & (1 << b)) { 247bf215546Sopenharmony_ci nvc0_set_constant_vertex_attrib(nvc0, i); 248bf215546Sopenharmony_ci continue; 249bf215546Sopenharmony_ci } 250bf215546Sopenharmony_ci nvc0_user_vbuf_range(nvc0, b, &base, &size); 251bf215546Sopenharmony_ci 252bf215546Sopenharmony_ci if (!(written & (1 << b))) { 253bf215546Sopenharmony_ci struct nouveau_bo *bo; 254bf215546Sopenharmony_ci const uint32_t bo_flags = NOUVEAU_BO_RD | NOUVEAU_BO_GART; 255bf215546Sopenharmony_ci written |= 1 << b; 256bf215546Sopenharmony_ci address[b] = nouveau_scratch_data(&nvc0->base, vb->buffer.user, 257bf215546Sopenharmony_ci base, size, &bo); 258bf215546Sopenharmony_ci if (bo) 259bf215546Sopenharmony_ci BCTX_REFN_bo(nvc0->bufctx_3d, 3D_VTX_TMP, bo_flags, bo); 260bf215546Sopenharmony_ci 261bf215546Sopenharmony_ci NOUVEAU_DRV_STAT(&nvc0->screen->base, user_buffer_upload_bytes, size); 262bf215546Sopenharmony_ci } 263bf215546Sopenharmony_ci 264bf215546Sopenharmony_ci BEGIN_1IC0(push, NVC0_3D(MACRO_VERTEX_ARRAY_SELECT), 5); 265bf215546Sopenharmony_ci PUSH_DATA (push, i); 266bf215546Sopenharmony_ci PUSH_DATAh(push, address[b] + base + size - 1); 267bf215546Sopenharmony_ci PUSH_DATA (push, address[b] + base + size - 1); 268bf215546Sopenharmony_ci PUSH_DATAh(push, address[b] + ve->src_offset); 269bf215546Sopenharmony_ci PUSH_DATA (push, address[b] + ve->src_offset); 270bf215546Sopenharmony_ci } 271bf215546Sopenharmony_ci nvc0->base.vbo_dirty = true; 272bf215546Sopenharmony_ci} 273bf215546Sopenharmony_ci 274bf215546Sopenharmony_cistatic void 275bf215546Sopenharmony_cinvc0_update_user_vbufs_shared(struct nvc0_context *nvc0) 276bf215546Sopenharmony_ci{ 277bf215546Sopenharmony_ci struct nouveau_pushbuf *push = nvc0->base.pushbuf; 278bf215546Sopenharmony_ci uint32_t mask = nvc0->vbo_user & ~nvc0->constant_vbos; 279bf215546Sopenharmony_ci 280bf215546Sopenharmony_ci PUSH_SPACE(push, nvc0->num_vtxbufs * 8); 281bf215546Sopenharmony_ci while (mask) { 282bf215546Sopenharmony_ci struct nouveau_bo *bo; 283bf215546Sopenharmony_ci const uint32_t bo_flags = NOUVEAU_BO_RD | NOUVEAU_BO_GART; 284bf215546Sopenharmony_ci uint64_t address; 285bf215546Sopenharmony_ci uint32_t base, size; 286bf215546Sopenharmony_ci const int b = ffs(mask) - 1; 287bf215546Sopenharmony_ci mask &= ~(1 << b); 288bf215546Sopenharmony_ci 289bf215546Sopenharmony_ci nvc0_user_vbuf_range(nvc0, b, &base, &size); 290bf215546Sopenharmony_ci 291bf215546Sopenharmony_ci address = nouveau_scratch_data(&nvc0->base, nvc0->vtxbuf[b].buffer.user, 292bf215546Sopenharmony_ci base, size, &bo); 293bf215546Sopenharmony_ci if (bo) 294bf215546Sopenharmony_ci BCTX_REFN_bo(nvc0->bufctx_3d, 3D_VTX_TMP, bo_flags, bo); 295bf215546Sopenharmony_ci 296bf215546Sopenharmony_ci BEGIN_1IC0(push, NVC0_3D(MACRO_VERTEX_ARRAY_SELECT), 5); 297bf215546Sopenharmony_ci PUSH_DATA (push, b); 298bf215546Sopenharmony_ci PUSH_DATAh(push, address + base + size - 1); 299bf215546Sopenharmony_ci PUSH_DATA (push, address + base + size - 1); 300bf215546Sopenharmony_ci PUSH_DATAh(push, address); 301bf215546Sopenharmony_ci PUSH_DATA (push, address); 302bf215546Sopenharmony_ci 303bf215546Sopenharmony_ci NOUVEAU_DRV_STAT(&nvc0->screen->base, user_buffer_upload_bytes, size); 304bf215546Sopenharmony_ci } 305bf215546Sopenharmony_ci 306bf215546Sopenharmony_ci mask = nvc0->state.constant_elts; 307bf215546Sopenharmony_ci while (mask) { 308bf215546Sopenharmony_ci int i = ffs(mask) - 1; 309bf215546Sopenharmony_ci mask &= ~(1 << i); 310bf215546Sopenharmony_ci nvc0_set_constant_vertex_attrib(nvc0, i); 311bf215546Sopenharmony_ci } 312bf215546Sopenharmony_ci} 313bf215546Sopenharmony_ci 314bf215546Sopenharmony_cistatic void 315bf215546Sopenharmony_cinvc0_validate_vertex_buffers(struct nvc0_context *nvc0) 316bf215546Sopenharmony_ci{ 317bf215546Sopenharmony_ci struct nouveau_pushbuf *push = nvc0->base.pushbuf; 318bf215546Sopenharmony_ci const struct nvc0_vertex_stateobj *vertex = nvc0->vertex; 319bf215546Sopenharmony_ci uint32_t refd = 0; 320bf215546Sopenharmony_ci unsigned i; 321bf215546Sopenharmony_ci 322bf215546Sopenharmony_ci PUSH_SPACE(push, vertex->num_elements * 8); 323bf215546Sopenharmony_ci for (i = 0; i < vertex->num_elements; ++i) { 324bf215546Sopenharmony_ci const struct nvc0_vertex_element *ve; 325bf215546Sopenharmony_ci const struct pipe_vertex_buffer *vb; 326bf215546Sopenharmony_ci struct nv04_resource *res; 327bf215546Sopenharmony_ci unsigned b; 328bf215546Sopenharmony_ci unsigned limit, offset; 329bf215546Sopenharmony_ci 330bf215546Sopenharmony_ci if (nvc0->state.constant_elts & (1 << i)) 331bf215546Sopenharmony_ci continue; 332bf215546Sopenharmony_ci ve = &vertex->element[i]; 333bf215546Sopenharmony_ci b = ve->pipe.vertex_buffer_index; 334bf215546Sopenharmony_ci vb = &nvc0->vtxbuf[b]; 335bf215546Sopenharmony_ci 336bf215546Sopenharmony_ci if (nvc0->vbo_user & (1 << b)) { 337bf215546Sopenharmony_ci if (!(nvc0->constant_vbos & (1 << b))) { 338bf215546Sopenharmony_ci if (ve->pipe.instance_divisor) { 339bf215546Sopenharmony_ci BEGIN_NVC0(push, NVC0_3D(VERTEX_ARRAY_DIVISOR(i)), 1); 340bf215546Sopenharmony_ci PUSH_DATA (push, ve->pipe.instance_divisor); 341bf215546Sopenharmony_ci } 342bf215546Sopenharmony_ci BEGIN_NVC0(push, NVC0_3D(VERTEX_ARRAY_FETCH(i)), 1); 343bf215546Sopenharmony_ci PUSH_DATA (push, (1 << 12) | vb->stride); 344bf215546Sopenharmony_ci } 345bf215546Sopenharmony_ci /* address/value set in nvc0_update_user_vbufs */ 346bf215546Sopenharmony_ci continue; 347bf215546Sopenharmony_ci } 348bf215546Sopenharmony_ci res = nv04_resource(vb->buffer.resource); 349bf215546Sopenharmony_ci offset = ve->pipe.src_offset + vb->buffer_offset; 350bf215546Sopenharmony_ci limit = vb->buffer.resource->width0 - 1; 351bf215546Sopenharmony_ci 352bf215546Sopenharmony_ci if (unlikely(ve->pipe.instance_divisor)) { 353bf215546Sopenharmony_ci BEGIN_NVC0(push, NVC0_3D(VERTEX_ARRAY_FETCH(i)), 4); 354bf215546Sopenharmony_ci PUSH_DATA (push, NVC0_3D_VERTEX_ARRAY_FETCH_ENABLE | vb->stride); 355bf215546Sopenharmony_ci PUSH_DATAh(push, res->address + offset); 356bf215546Sopenharmony_ci PUSH_DATA (push, res->address + offset); 357bf215546Sopenharmony_ci PUSH_DATA (push, ve->pipe.instance_divisor); 358bf215546Sopenharmony_ci } else { 359bf215546Sopenharmony_ci BEGIN_NVC0(push, NVC0_3D(VERTEX_ARRAY_FETCH(i)), 3); 360bf215546Sopenharmony_ci PUSH_DATA (push, NVC0_3D_VERTEX_ARRAY_FETCH_ENABLE | vb->stride); 361bf215546Sopenharmony_ci PUSH_DATAh(push, res->address + offset); 362bf215546Sopenharmony_ci PUSH_DATA (push, res->address + offset); 363bf215546Sopenharmony_ci } 364bf215546Sopenharmony_ci 365bf215546Sopenharmony_ci if (nvc0->screen->eng3d->oclass < TU102_3D_CLASS) 366bf215546Sopenharmony_ci BEGIN_NVC0(push, NVC0_3D(VERTEX_ARRAY_LIMIT_HIGH(i)), 2); 367bf215546Sopenharmony_ci else 368bf215546Sopenharmony_ci BEGIN_NVC0(push, SUBC_3D(TU102_3D_VERTEX_ARRAY_LIMIT_HIGH(i)), 2); 369bf215546Sopenharmony_ci PUSH_DATAh(push, res->address + limit); 370bf215546Sopenharmony_ci PUSH_DATA (push, res->address + limit); 371bf215546Sopenharmony_ci 372bf215546Sopenharmony_ci if (!(refd & (1 << b))) { 373bf215546Sopenharmony_ci refd |= 1 << b; 374bf215546Sopenharmony_ci BCTX_REFN(nvc0->bufctx_3d, 3D_VTX, res, RD); 375bf215546Sopenharmony_ci } 376bf215546Sopenharmony_ci } 377bf215546Sopenharmony_ci if (nvc0->vbo_user) 378bf215546Sopenharmony_ci nvc0_update_user_vbufs(nvc0); 379bf215546Sopenharmony_ci} 380bf215546Sopenharmony_ci 381bf215546Sopenharmony_cistatic void 382bf215546Sopenharmony_cinvc0_validate_vertex_buffers_shared(struct nvc0_context *nvc0) 383bf215546Sopenharmony_ci{ 384bf215546Sopenharmony_ci struct nouveau_pushbuf *push = nvc0->base.pushbuf; 385bf215546Sopenharmony_ci unsigned b; 386bf215546Sopenharmony_ci const uint32_t mask = nvc0->vbo_user; 387bf215546Sopenharmony_ci 388bf215546Sopenharmony_ci PUSH_SPACE(push, nvc0->num_vtxbufs * 8 + nvc0->vertex->num_elements); 389bf215546Sopenharmony_ci for (b = 0; b < nvc0->num_vtxbufs; ++b) { 390bf215546Sopenharmony_ci struct pipe_vertex_buffer *vb = &nvc0->vtxbuf[b]; 391bf215546Sopenharmony_ci struct nv04_resource *buf; 392bf215546Sopenharmony_ci uint32_t offset, limit; 393bf215546Sopenharmony_ci 394bf215546Sopenharmony_ci if (mask & (1 << b)) { 395bf215546Sopenharmony_ci if (!(nvc0->constant_vbos & (1 << b))) { 396bf215546Sopenharmony_ci BEGIN_NVC0(push, NVC0_3D(VERTEX_ARRAY_FETCH(b)), 1); 397bf215546Sopenharmony_ci PUSH_DATA (push, NVC0_3D_VERTEX_ARRAY_FETCH_ENABLE | vb->stride); 398bf215546Sopenharmony_ci } 399bf215546Sopenharmony_ci /* address/value set in nvc0_update_user_vbufs_shared */ 400bf215546Sopenharmony_ci continue; 401bf215546Sopenharmony_ci } else if (!vb->buffer.resource) { 402bf215546Sopenharmony_ci /* there can be holes in the vertex buffer lists */ 403bf215546Sopenharmony_ci IMMED_NVC0(push, NVC0_3D(VERTEX_ARRAY_FETCH(b)), 0); 404bf215546Sopenharmony_ci continue; 405bf215546Sopenharmony_ci } 406bf215546Sopenharmony_ci buf = nv04_resource(vb->buffer.resource); 407bf215546Sopenharmony_ci offset = vb->buffer_offset; 408bf215546Sopenharmony_ci limit = buf->base.width0 - 1; 409bf215546Sopenharmony_ci 410bf215546Sopenharmony_ci BEGIN_NVC0(push, NVC0_3D(VERTEX_ARRAY_FETCH(b)), 3); 411bf215546Sopenharmony_ci PUSH_DATA (push, NVC0_3D_VERTEX_ARRAY_FETCH_ENABLE | vb->stride); 412bf215546Sopenharmony_ci PUSH_DATAh(push, buf->address + offset); 413bf215546Sopenharmony_ci PUSH_DATA (push, buf->address + offset); 414bf215546Sopenharmony_ci 415bf215546Sopenharmony_ci if (nvc0->screen->eng3d->oclass < TU102_3D_CLASS) 416bf215546Sopenharmony_ci BEGIN_NVC0(push, NVC0_3D(VERTEX_ARRAY_LIMIT_HIGH(b)), 2); 417bf215546Sopenharmony_ci else 418bf215546Sopenharmony_ci BEGIN_NVC0(push, SUBC_3D(TU102_3D_VERTEX_ARRAY_LIMIT_HIGH(b)), 2); 419bf215546Sopenharmony_ci PUSH_DATAh(push, buf->address + limit); 420bf215546Sopenharmony_ci PUSH_DATA (push, buf->address + limit); 421bf215546Sopenharmony_ci 422bf215546Sopenharmony_ci BCTX_REFN(nvc0->bufctx_3d, 3D_VTX, buf, RD); 423bf215546Sopenharmony_ci } 424bf215546Sopenharmony_ci /* If there are more elements than buffers, we might not have unset 425bf215546Sopenharmony_ci * fetching on the later elements. 426bf215546Sopenharmony_ci */ 427bf215546Sopenharmony_ci for (; b < nvc0->vertex->num_elements; ++b) 428bf215546Sopenharmony_ci IMMED_NVC0(push, NVC0_3D(VERTEX_ARRAY_FETCH(b)), 0); 429bf215546Sopenharmony_ci 430bf215546Sopenharmony_ci if (nvc0->vbo_user) 431bf215546Sopenharmony_ci nvc0_update_user_vbufs_shared(nvc0); 432bf215546Sopenharmony_ci} 433bf215546Sopenharmony_ci 434bf215546Sopenharmony_civoid 435bf215546Sopenharmony_cinvc0_vertex_arrays_validate(struct nvc0_context *nvc0) 436bf215546Sopenharmony_ci{ 437bf215546Sopenharmony_ci struct nouveau_pushbuf *push = nvc0->base.pushbuf; 438bf215546Sopenharmony_ci struct nvc0_vertex_stateobj *vertex = nvc0->vertex; 439bf215546Sopenharmony_ci struct nvc0_vertex_element *ve; 440bf215546Sopenharmony_ci uint32_t const_vbos; 441bf215546Sopenharmony_ci unsigned i; 442bf215546Sopenharmony_ci uint8_t vbo_mode; 443bf215546Sopenharmony_ci bool update_vertex; 444bf215546Sopenharmony_ci 445bf215546Sopenharmony_ci nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_VTX); 446bf215546Sopenharmony_ci 447bf215546Sopenharmony_ci assert(vertex); 448bf215546Sopenharmony_ci if (unlikely(vertex->need_conversion) || 449bf215546Sopenharmony_ci unlikely(nvc0->vertprog->vp.edgeflag < PIPE_MAX_ATTRIBS)) { 450bf215546Sopenharmony_ci vbo_mode = 3; 451bf215546Sopenharmony_ci } else if (nvc0->vbo_user & ~nvc0->constant_vbos) { 452bf215546Sopenharmony_ci vbo_mode = nvc0->vbo_push_hint ? 1 : 0; 453bf215546Sopenharmony_ci } else { 454bf215546Sopenharmony_ci vbo_mode = 0; 455bf215546Sopenharmony_ci } 456bf215546Sopenharmony_ci const_vbos = vbo_mode ? 0 : nvc0->constant_vbos; 457bf215546Sopenharmony_ci 458bf215546Sopenharmony_ci update_vertex = (nvc0->dirty_3d & NVC0_NEW_3D_VERTEX) || 459bf215546Sopenharmony_ci (const_vbos != nvc0->state.constant_vbos) || 460bf215546Sopenharmony_ci (vbo_mode != nvc0->state.vbo_mode); 461bf215546Sopenharmony_ci 462bf215546Sopenharmony_ci if (update_vertex) { 463bf215546Sopenharmony_ci const unsigned n = MAX2(vertex->num_elements, nvc0->state.num_vtxelts); 464bf215546Sopenharmony_ci 465bf215546Sopenharmony_ci nvc0->state.constant_vbos = const_vbos; 466bf215546Sopenharmony_ci nvc0->state.constant_elts = 0; 467bf215546Sopenharmony_ci nvc0->state.num_vtxelts = vertex->num_elements; 468bf215546Sopenharmony_ci nvc0->state.vbo_mode = vbo_mode; 469bf215546Sopenharmony_ci 470bf215546Sopenharmony_ci if (unlikely(vbo_mode)) { 471bf215546Sopenharmony_ci if (unlikely(nvc0->state.instance_elts & 3)) { 472bf215546Sopenharmony_ci /* translate mode uses only 2 vertex buffers */ 473bf215546Sopenharmony_ci nvc0->state.instance_elts &= ~3; 474bf215546Sopenharmony_ci PUSH_SPACE(push, 3); 475bf215546Sopenharmony_ci BEGIN_NVC0(push, NVC0_3D(VERTEX_ARRAY_PER_INSTANCE(0)), 2); 476bf215546Sopenharmony_ci PUSH_DATA (push, 0); 477bf215546Sopenharmony_ci PUSH_DATA (push, 0); 478bf215546Sopenharmony_ci } 479bf215546Sopenharmony_ci 480bf215546Sopenharmony_ci PUSH_SPACE(push, n * 2 + 4); 481bf215546Sopenharmony_ci 482bf215546Sopenharmony_ci BEGIN_NVC0(push, NVC0_3D(VERTEX_ATTRIB_FORMAT(0)), n); 483bf215546Sopenharmony_ci for (i = 0; i < vertex->num_elements; ++i) 484bf215546Sopenharmony_ci PUSH_DATA(push, vertex->element[i].state_alt); 485bf215546Sopenharmony_ci for (; i < n; ++i) 486bf215546Sopenharmony_ci PUSH_DATA(push, NVC0_3D_VERTEX_ATTRIB_INACTIVE); 487bf215546Sopenharmony_ci 488bf215546Sopenharmony_ci BEGIN_NVC0(push, NVC0_3D(VERTEX_ARRAY_FETCH(0)), 1); 489bf215546Sopenharmony_ci PUSH_DATA (push, (1 << 12) | vertex->size); 490bf215546Sopenharmony_ci for (i = 1; i < n; ++i) 491bf215546Sopenharmony_ci IMMED_NVC0(push, NVC0_3D(VERTEX_ARRAY_FETCH(i)), 0); 492bf215546Sopenharmony_ci } else { 493bf215546Sopenharmony_ci uint32_t *restrict data; 494bf215546Sopenharmony_ci 495bf215546Sopenharmony_ci if (unlikely(vertex->instance_elts != nvc0->state.instance_elts)) { 496bf215546Sopenharmony_ci nvc0->state.instance_elts = vertex->instance_elts; 497bf215546Sopenharmony_ci assert(n); /* if (n == 0), both masks should be 0 */ 498bf215546Sopenharmony_ci PUSH_SPACE(push, 3); 499bf215546Sopenharmony_ci BEGIN_NVC0(push, NVC0_3D(MACRO_VERTEX_ARRAY_PER_INSTANCE), 2); 500bf215546Sopenharmony_ci PUSH_DATA (push, n); 501bf215546Sopenharmony_ci PUSH_DATA (push, vertex->instance_elts); 502bf215546Sopenharmony_ci } 503bf215546Sopenharmony_ci 504bf215546Sopenharmony_ci PUSH_SPACE(push, n * 2 + 1); 505bf215546Sopenharmony_ci BEGIN_NVC0(push, NVC0_3D(VERTEX_ATTRIB_FORMAT(0)), n); 506bf215546Sopenharmony_ci data = push->cur; 507bf215546Sopenharmony_ci push->cur += n; 508bf215546Sopenharmony_ci for (i = 0; i < vertex->num_elements; ++i) { 509bf215546Sopenharmony_ci ve = &vertex->element[i]; 510bf215546Sopenharmony_ci data[i] = ve->state; 511bf215546Sopenharmony_ci if (unlikely(const_vbos & (1 << ve->pipe.vertex_buffer_index))) { 512bf215546Sopenharmony_ci nvc0->state.constant_elts |= 1 << i; 513bf215546Sopenharmony_ci data[i] |= NVC0_3D_VERTEX_ATTRIB_FORMAT_CONST; 514bf215546Sopenharmony_ci IMMED_NVC0(push, NVC0_3D(VERTEX_ARRAY_FETCH(i)), 0); 515bf215546Sopenharmony_ci } 516bf215546Sopenharmony_ci } 517bf215546Sopenharmony_ci for (; i < n; ++i) { 518bf215546Sopenharmony_ci data[i] = NVC0_3D_VERTEX_ATTRIB_INACTIVE; 519bf215546Sopenharmony_ci IMMED_NVC0(push, NVC0_3D(VERTEX_ARRAY_FETCH(i)), 0); 520bf215546Sopenharmony_ci } 521bf215546Sopenharmony_ci } 522bf215546Sopenharmony_ci } 523bf215546Sopenharmony_ci if (nvc0->state.vbo_mode) /* using translate, don't set up arrays here */ 524bf215546Sopenharmony_ci return; 525bf215546Sopenharmony_ci 526bf215546Sopenharmony_ci if (vertex->shared_slots) 527bf215546Sopenharmony_ci nvc0_validate_vertex_buffers_shared(nvc0); 528bf215546Sopenharmony_ci else 529bf215546Sopenharmony_ci nvc0_validate_vertex_buffers(nvc0); 530bf215546Sopenharmony_ci} 531bf215546Sopenharmony_ci 532bf215546Sopenharmony_ci#define NVC0_PRIM_GL_CASE(n) \ 533bf215546Sopenharmony_ci case PIPE_PRIM_##n: return NVC0_3D_VERTEX_BEGIN_GL_PRIMITIVE_##n 534bf215546Sopenharmony_ci 535bf215546Sopenharmony_cistatic inline unsigned 536bf215546Sopenharmony_cinvc0_prim_gl(unsigned prim) 537bf215546Sopenharmony_ci{ 538bf215546Sopenharmony_ci switch (prim) { 539bf215546Sopenharmony_ci NVC0_PRIM_GL_CASE(POINTS); 540bf215546Sopenharmony_ci NVC0_PRIM_GL_CASE(LINES); 541bf215546Sopenharmony_ci NVC0_PRIM_GL_CASE(LINE_LOOP); 542bf215546Sopenharmony_ci NVC0_PRIM_GL_CASE(LINE_STRIP); 543bf215546Sopenharmony_ci NVC0_PRIM_GL_CASE(TRIANGLES); 544bf215546Sopenharmony_ci NVC0_PRIM_GL_CASE(TRIANGLE_STRIP); 545bf215546Sopenharmony_ci NVC0_PRIM_GL_CASE(TRIANGLE_FAN); 546bf215546Sopenharmony_ci NVC0_PRIM_GL_CASE(QUADS); 547bf215546Sopenharmony_ci NVC0_PRIM_GL_CASE(QUAD_STRIP); 548bf215546Sopenharmony_ci NVC0_PRIM_GL_CASE(POLYGON); 549bf215546Sopenharmony_ci NVC0_PRIM_GL_CASE(LINES_ADJACENCY); 550bf215546Sopenharmony_ci NVC0_PRIM_GL_CASE(LINE_STRIP_ADJACENCY); 551bf215546Sopenharmony_ci NVC0_PRIM_GL_CASE(TRIANGLES_ADJACENCY); 552bf215546Sopenharmony_ci NVC0_PRIM_GL_CASE(TRIANGLE_STRIP_ADJACENCY); 553bf215546Sopenharmony_ci NVC0_PRIM_GL_CASE(PATCHES); 554bf215546Sopenharmony_ci default: 555bf215546Sopenharmony_ci return NVC0_3D_VERTEX_BEGIN_GL_PRIMITIVE_POINTS; 556bf215546Sopenharmony_ci } 557bf215546Sopenharmony_ci} 558bf215546Sopenharmony_ci 559bf215546Sopenharmony_cistatic void 560bf215546Sopenharmony_cinvc0_draw_vbo_kick_notify(struct nouveau_pushbuf *push) 561bf215546Sopenharmony_ci{ 562bf215546Sopenharmony_ci struct nvc0_screen *screen = push->user_priv; 563bf215546Sopenharmony_ci 564bf215546Sopenharmony_ci nouveau_fence_update(&screen->base, true); 565bf215546Sopenharmony_ci 566bf215546Sopenharmony_ci NOUVEAU_DRV_STAT(&screen->base, pushbuf_count, 1); 567bf215546Sopenharmony_ci} 568bf215546Sopenharmony_ci 569bf215546Sopenharmony_cistatic void 570bf215546Sopenharmony_cinvc0_draw_arrays(struct nvc0_context *nvc0, 571bf215546Sopenharmony_ci unsigned mode, unsigned start, unsigned count, 572bf215546Sopenharmony_ci unsigned instance_count) 573bf215546Sopenharmony_ci{ 574bf215546Sopenharmony_ci struct nouveau_pushbuf *push = nvc0->base.pushbuf; 575bf215546Sopenharmony_ci unsigned prim; 576bf215546Sopenharmony_ci 577bf215546Sopenharmony_ci if (nvc0->state.index_bias) { 578bf215546Sopenharmony_ci /* index_bias is implied 0 if !info->index_size (really ?) */ 579bf215546Sopenharmony_ci /* TODO: can we deactivate it for the VERTEX_BUFFER_FIRST command ? */ 580bf215546Sopenharmony_ci PUSH_SPACE(push, 2); 581bf215546Sopenharmony_ci IMMED_NVC0(push, NVC0_3D(VB_ELEMENT_BASE), 0); 582bf215546Sopenharmony_ci IMMED_NVC0(push, NVC0_3D(VERTEX_ID_BASE), 0); 583bf215546Sopenharmony_ci nvc0->state.index_bias = 0; 584bf215546Sopenharmony_ci } 585bf215546Sopenharmony_ci 586bf215546Sopenharmony_ci prim = nvc0_prim_gl(mode); 587bf215546Sopenharmony_ci 588bf215546Sopenharmony_ci while (instance_count--) { 589bf215546Sopenharmony_ci PUSH_SPACE(push, 6); 590bf215546Sopenharmony_ci BEGIN_NVC0(push, NVC0_3D(VERTEX_BEGIN_GL), 1); 591bf215546Sopenharmony_ci PUSH_DATA (push, prim); 592bf215546Sopenharmony_ci BEGIN_NVC0(push, NVC0_3D(VERTEX_BUFFER_FIRST), 2); 593bf215546Sopenharmony_ci PUSH_DATA (push, start); 594bf215546Sopenharmony_ci PUSH_DATA (push, count); 595bf215546Sopenharmony_ci IMMED_NVC0(push, NVC0_3D(VERTEX_END_GL), 0); 596bf215546Sopenharmony_ci 597bf215546Sopenharmony_ci prim |= NVC0_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT; 598bf215546Sopenharmony_ci } 599bf215546Sopenharmony_ci NOUVEAU_DRV_STAT(&nvc0->screen->base, draw_calls_array, 1); 600bf215546Sopenharmony_ci} 601bf215546Sopenharmony_ci 602bf215546Sopenharmony_cistatic void 603bf215546Sopenharmony_cinvc0_draw_elements_inline_u08(struct nouveau_pushbuf *push, const uint8_t *map, 604bf215546Sopenharmony_ci unsigned start, unsigned count) 605bf215546Sopenharmony_ci{ 606bf215546Sopenharmony_ci map += start; 607bf215546Sopenharmony_ci 608bf215546Sopenharmony_ci if (count & 3) { 609bf215546Sopenharmony_ci unsigned i; 610bf215546Sopenharmony_ci PUSH_SPACE(push, 4); 611bf215546Sopenharmony_ci BEGIN_NIC0(push, NVC0_3D(VB_ELEMENT_U32), count & 3); 612bf215546Sopenharmony_ci for (i = 0; i < (count & 3); ++i) 613bf215546Sopenharmony_ci PUSH_DATA(push, *map++); 614bf215546Sopenharmony_ci count &= ~3; 615bf215546Sopenharmony_ci } 616bf215546Sopenharmony_ci while (count) { 617bf215546Sopenharmony_ci unsigned i, nr = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN * 4) / 4; 618bf215546Sopenharmony_ci 619bf215546Sopenharmony_ci PUSH_SPACE(push, nr + 1); 620bf215546Sopenharmony_ci BEGIN_NIC0(push, NVC0_3D(VB_ELEMENT_U8), nr); 621bf215546Sopenharmony_ci for (i = 0; i < nr; ++i) { 622bf215546Sopenharmony_ci PUSH_DATA(push, 623bf215546Sopenharmony_ci (map[3] << 24) | (map[2] << 16) | (map[1] << 8) | map[0]); 624bf215546Sopenharmony_ci map += 4; 625bf215546Sopenharmony_ci } 626bf215546Sopenharmony_ci count -= nr * 4; 627bf215546Sopenharmony_ci } 628bf215546Sopenharmony_ci} 629bf215546Sopenharmony_ci 630bf215546Sopenharmony_cistatic void 631bf215546Sopenharmony_cinvc0_draw_elements_inline_u16(struct nouveau_pushbuf *push, const uint16_t *map, 632bf215546Sopenharmony_ci unsigned start, unsigned count) 633bf215546Sopenharmony_ci{ 634bf215546Sopenharmony_ci map += start; 635bf215546Sopenharmony_ci 636bf215546Sopenharmony_ci if (count & 1) { 637bf215546Sopenharmony_ci count &= ~1; 638bf215546Sopenharmony_ci PUSH_SPACE(push, 2); 639bf215546Sopenharmony_ci BEGIN_NVC0(push, NVC0_3D(VB_ELEMENT_U32), 1); 640bf215546Sopenharmony_ci PUSH_DATA (push, *map++); 641bf215546Sopenharmony_ci } 642bf215546Sopenharmony_ci while (count) { 643bf215546Sopenharmony_ci unsigned i, nr = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN * 2) / 2; 644bf215546Sopenharmony_ci 645bf215546Sopenharmony_ci PUSH_SPACE(push, nr + 1); 646bf215546Sopenharmony_ci BEGIN_NIC0(push, NVC0_3D(VB_ELEMENT_U16), nr); 647bf215546Sopenharmony_ci for (i = 0; i < nr; ++i) { 648bf215546Sopenharmony_ci PUSH_DATA(push, (map[1] << 16) | map[0]); 649bf215546Sopenharmony_ci map += 2; 650bf215546Sopenharmony_ci } 651bf215546Sopenharmony_ci count -= nr * 2; 652bf215546Sopenharmony_ci } 653bf215546Sopenharmony_ci} 654bf215546Sopenharmony_ci 655bf215546Sopenharmony_cistatic void 656bf215546Sopenharmony_cinvc0_draw_elements_inline_u32(struct nouveau_pushbuf *push, const uint32_t *map, 657bf215546Sopenharmony_ci unsigned start, unsigned count) 658bf215546Sopenharmony_ci{ 659bf215546Sopenharmony_ci map += start; 660bf215546Sopenharmony_ci 661bf215546Sopenharmony_ci while (count) { 662bf215546Sopenharmony_ci const unsigned nr = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN); 663bf215546Sopenharmony_ci 664bf215546Sopenharmony_ci PUSH_SPACE(push, nr + 1); 665bf215546Sopenharmony_ci BEGIN_NIC0(push, NVC0_3D(VB_ELEMENT_U32), nr); 666bf215546Sopenharmony_ci PUSH_DATAp(push, map, nr); 667bf215546Sopenharmony_ci 668bf215546Sopenharmony_ci map += nr; 669bf215546Sopenharmony_ci count -= nr; 670bf215546Sopenharmony_ci } 671bf215546Sopenharmony_ci} 672bf215546Sopenharmony_ci 673bf215546Sopenharmony_cistatic void 674bf215546Sopenharmony_cinvc0_draw_elements_inline_u32_short(struct nouveau_pushbuf *push, 675bf215546Sopenharmony_ci const uint32_t *map, 676bf215546Sopenharmony_ci unsigned start, unsigned count) 677bf215546Sopenharmony_ci{ 678bf215546Sopenharmony_ci map += start; 679bf215546Sopenharmony_ci 680bf215546Sopenharmony_ci if (count & 1) { 681bf215546Sopenharmony_ci count--; 682bf215546Sopenharmony_ci PUSH_SPACE(push, 2); 683bf215546Sopenharmony_ci BEGIN_NVC0(push, NVC0_3D(VB_ELEMENT_U32), 1); 684bf215546Sopenharmony_ci PUSH_DATA (push, *map++); 685bf215546Sopenharmony_ci } 686bf215546Sopenharmony_ci while (count) { 687bf215546Sopenharmony_ci unsigned i, nr = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN * 2) / 2; 688bf215546Sopenharmony_ci 689bf215546Sopenharmony_ci PUSH_SPACE(push, nr + 1); 690bf215546Sopenharmony_ci BEGIN_NIC0(push, NVC0_3D(VB_ELEMENT_U16), nr); 691bf215546Sopenharmony_ci for (i = 0; i < nr; ++i) { 692bf215546Sopenharmony_ci PUSH_DATA(push, (map[1] << 16) | map[0]); 693bf215546Sopenharmony_ci map += 2; 694bf215546Sopenharmony_ci } 695bf215546Sopenharmony_ci count -= nr * 2; 696bf215546Sopenharmony_ci } 697bf215546Sopenharmony_ci} 698bf215546Sopenharmony_ci 699bf215546Sopenharmony_cistatic void 700bf215546Sopenharmony_cinvc0_draw_elements(struct nvc0_context *nvc0, bool shorten, 701bf215546Sopenharmony_ci const struct pipe_draw_info *info, 702bf215546Sopenharmony_ci unsigned mode, unsigned start, unsigned count, 703bf215546Sopenharmony_ci unsigned instance_count, int32_t index_bias, 704bf215546Sopenharmony_ci unsigned index_size) 705bf215546Sopenharmony_ci{ 706bf215546Sopenharmony_ci struct nouveau_pushbuf *push = nvc0->base.pushbuf; 707bf215546Sopenharmony_ci unsigned prim; 708bf215546Sopenharmony_ci 709bf215546Sopenharmony_ci prim = nvc0_prim_gl(mode); 710bf215546Sopenharmony_ci 711bf215546Sopenharmony_ci if (index_bias != nvc0->state.index_bias) { 712bf215546Sopenharmony_ci PUSH_SPACE(push, 4); 713bf215546Sopenharmony_ci BEGIN_NVC0(push, NVC0_3D(VB_ELEMENT_BASE), 1); 714bf215546Sopenharmony_ci PUSH_DATA (push, index_bias); 715bf215546Sopenharmony_ci BEGIN_NVC0(push, NVC0_3D(VERTEX_ID_BASE), 1); 716bf215546Sopenharmony_ci PUSH_DATA (push, index_bias); 717bf215546Sopenharmony_ci nvc0->state.index_bias = index_bias; 718bf215546Sopenharmony_ci } 719bf215546Sopenharmony_ci 720bf215546Sopenharmony_ci if (!info->has_user_indices) { 721bf215546Sopenharmony_ci PUSH_SPACE(push, 1); 722bf215546Sopenharmony_ci IMMED_NVC0(push, NVC0_3D(VERTEX_BEGIN_GL), prim); 723bf215546Sopenharmony_ci do { 724bf215546Sopenharmony_ci PUSH_SPACE(push, 7); 725bf215546Sopenharmony_ci BEGIN_NVC0(push, NVC0_3D(INDEX_BATCH_FIRST), 2); 726bf215546Sopenharmony_ci PUSH_DATA (push, start); 727bf215546Sopenharmony_ci PUSH_DATA (push, count); 728bf215546Sopenharmony_ci if (--instance_count) { 729bf215546Sopenharmony_ci BEGIN_NVC0(push, NVC0_3D(VERTEX_END_GL), 2); 730bf215546Sopenharmony_ci PUSH_DATA (push, 0); 731bf215546Sopenharmony_ci PUSH_DATA (push, prim | NVC0_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT); 732bf215546Sopenharmony_ci } 733bf215546Sopenharmony_ci } while (instance_count); 734bf215546Sopenharmony_ci IMMED_NVC0(push, NVC0_3D(VERTEX_END_GL), 0); 735bf215546Sopenharmony_ci } else { 736bf215546Sopenharmony_ci const void *data = info->index.user; 737bf215546Sopenharmony_ci 738bf215546Sopenharmony_ci while (instance_count--) { 739bf215546Sopenharmony_ci PUSH_SPACE(push, 2); 740bf215546Sopenharmony_ci BEGIN_NVC0(push, NVC0_3D(VERTEX_BEGIN_GL), 1); 741bf215546Sopenharmony_ci PUSH_DATA (push, prim); 742bf215546Sopenharmony_ci switch (index_size) { 743bf215546Sopenharmony_ci case 1: 744bf215546Sopenharmony_ci nvc0_draw_elements_inline_u08(push, data, start, count); 745bf215546Sopenharmony_ci break; 746bf215546Sopenharmony_ci case 2: 747bf215546Sopenharmony_ci nvc0_draw_elements_inline_u16(push, data, start, count); 748bf215546Sopenharmony_ci break; 749bf215546Sopenharmony_ci case 4: 750bf215546Sopenharmony_ci if (shorten) 751bf215546Sopenharmony_ci nvc0_draw_elements_inline_u32_short(push, data, start, count); 752bf215546Sopenharmony_ci else 753bf215546Sopenharmony_ci nvc0_draw_elements_inline_u32(push, data, start, count); 754bf215546Sopenharmony_ci break; 755bf215546Sopenharmony_ci default: 756bf215546Sopenharmony_ci assert(0); 757bf215546Sopenharmony_ci return; 758bf215546Sopenharmony_ci } 759bf215546Sopenharmony_ci PUSH_SPACE(push, 1); 760bf215546Sopenharmony_ci IMMED_NVC0(push, NVC0_3D(VERTEX_END_GL), 0); 761bf215546Sopenharmony_ci 762bf215546Sopenharmony_ci prim |= NVC0_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT; 763bf215546Sopenharmony_ci } 764bf215546Sopenharmony_ci } 765bf215546Sopenharmony_ci NOUVEAU_DRV_STAT(&nvc0->screen->base, draw_calls_indexed, 1); 766bf215546Sopenharmony_ci} 767bf215546Sopenharmony_ci 768bf215546Sopenharmony_cistatic void 769bf215546Sopenharmony_cinvc0_draw_stream_output(struct nvc0_context *nvc0, 770bf215546Sopenharmony_ci const struct pipe_draw_info *info, 771bf215546Sopenharmony_ci const struct pipe_draw_indirect_info *indirect) 772bf215546Sopenharmony_ci{ 773bf215546Sopenharmony_ci struct nouveau_pushbuf *push = nvc0->base.pushbuf; 774bf215546Sopenharmony_ci struct nvc0_so_target *so = nvc0_so_target(indirect->count_from_stream_output); 775bf215546Sopenharmony_ci struct nv04_resource *res = nv04_resource(so->pipe.buffer); 776bf215546Sopenharmony_ci unsigned mode = nvc0_prim_gl(info->mode); 777bf215546Sopenharmony_ci unsigned num_instances = info->instance_count; 778bf215546Sopenharmony_ci 779bf215546Sopenharmony_ci if (res->status & NOUVEAU_BUFFER_STATUS_GPU_WRITING) { 780bf215546Sopenharmony_ci res->status &= ~NOUVEAU_BUFFER_STATUS_GPU_WRITING; 781bf215546Sopenharmony_ci PUSH_SPACE(push, 2); 782bf215546Sopenharmony_ci IMMED_NVC0(push, NVC0_3D(SERIALIZE), 0); 783bf215546Sopenharmony_ci nvc0_hw_query_fifo_wait(nvc0, nvc0_query(so->pq)); 784bf215546Sopenharmony_ci if (nvc0->screen->eng3d->oclass < GM107_3D_CLASS) 785bf215546Sopenharmony_ci IMMED_NVC0(push, NVC0_3D(VERTEX_ARRAY_FLUSH), 0); 786bf215546Sopenharmony_ci 787bf215546Sopenharmony_ci NOUVEAU_DRV_STAT(&nvc0->screen->base, gpu_serialize_count, 1); 788bf215546Sopenharmony_ci } 789bf215546Sopenharmony_ci 790bf215546Sopenharmony_ci while (num_instances--) { 791bf215546Sopenharmony_ci nouveau_pushbuf_space(push, 16, 0, 1); 792bf215546Sopenharmony_ci BEGIN_NVC0(push, NVC0_3D(VERTEX_BEGIN_GL), 1); 793bf215546Sopenharmony_ci PUSH_DATA (push, mode); 794bf215546Sopenharmony_ci BEGIN_NVC0(push, NVC0_3D(DRAW_TFB_BASE), 1); 795bf215546Sopenharmony_ci PUSH_DATA (push, 0); 796bf215546Sopenharmony_ci BEGIN_NVC0(push, NVC0_3D(DRAW_TFB_STRIDE), 1); 797bf215546Sopenharmony_ci PUSH_DATA (push, so->stride); 798bf215546Sopenharmony_ci BEGIN_NVC0(push, NVC0_3D(DRAW_TFB_BYTES), 1); 799bf215546Sopenharmony_ci nvc0_hw_query_pushbuf_submit(push, nvc0_query(so->pq), 0x4); 800bf215546Sopenharmony_ci IMMED_NVC0(push, NVC0_3D(VERTEX_END_GL), 0); 801bf215546Sopenharmony_ci 802bf215546Sopenharmony_ci mode |= NVC0_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT; 803bf215546Sopenharmony_ci } 804bf215546Sopenharmony_ci} 805bf215546Sopenharmony_ci 806bf215546Sopenharmony_cistatic void 807bf215546Sopenharmony_cinvc0_draw_indirect(struct nvc0_context *nvc0, const struct pipe_draw_info *info, 808bf215546Sopenharmony_ci unsigned drawid_offset, 809bf215546Sopenharmony_ci const struct pipe_draw_indirect_info *indirect) 810bf215546Sopenharmony_ci{ 811bf215546Sopenharmony_ci struct nouveau_pushbuf *push = nvc0->base.pushbuf; 812bf215546Sopenharmony_ci struct nv04_resource *buf = nv04_resource(indirect->buffer); 813bf215546Sopenharmony_ci struct nv04_resource *buf_count = nv04_resource(indirect->indirect_draw_count); 814bf215546Sopenharmony_ci unsigned size, macro, count = indirect->draw_count, drawid = drawid_offset; 815bf215546Sopenharmony_ci uint32_t offset = buf->offset + indirect->offset; 816bf215546Sopenharmony_ci struct nvc0_screen *screen = nvc0->screen; 817bf215546Sopenharmony_ci 818bf215546Sopenharmony_ci PUSH_SPACE(push, 7); 819bf215546Sopenharmony_ci 820bf215546Sopenharmony_ci /* must make FIFO wait for engines idle before continuing to process */ 821bf215546Sopenharmony_ci if ((buf->fence_wr && !nouveau_fence_signalled(buf->fence_wr)) || 822bf215546Sopenharmony_ci (buf_count && buf_count->fence_wr && 823bf215546Sopenharmony_ci !nouveau_fence_signalled(buf_count->fence_wr))) { 824bf215546Sopenharmony_ci IMMED_NVC0(push, SUBC_3D(NV10_SUBCHAN_REF_CNT), 0); 825bf215546Sopenharmony_ci } 826bf215546Sopenharmony_ci 827bf215546Sopenharmony_ci /* Queue things up to let the macros write params to the driver constbuf */ 828bf215546Sopenharmony_ci BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 3); 829bf215546Sopenharmony_ci PUSH_DATA (push, NVC0_CB_AUX_SIZE); 830bf215546Sopenharmony_ci PUSH_DATAh(push, screen->uniform_bo->offset + NVC0_CB_AUX_INFO(0)); 831bf215546Sopenharmony_ci PUSH_DATA (push, screen->uniform_bo->offset + NVC0_CB_AUX_INFO(0)); 832bf215546Sopenharmony_ci BEGIN_NVC0(push, NVC0_3D(CB_POS), 1); 833bf215546Sopenharmony_ci PUSH_DATA (push, NVC0_CB_AUX_DRAW_INFO); 834bf215546Sopenharmony_ci 835bf215546Sopenharmony_ci if (info->index_size) { 836bf215546Sopenharmony_ci assert(!info->has_user_indices); 837bf215546Sopenharmony_ci assert(nouveau_resource_mapped_by_gpu(info->index.resource)); 838bf215546Sopenharmony_ci size = 5; 839bf215546Sopenharmony_ci if (buf_count) 840bf215546Sopenharmony_ci macro = NVC0_3D_MACRO_DRAW_ELEMENTS_INDIRECT_COUNT; 841bf215546Sopenharmony_ci else 842bf215546Sopenharmony_ci macro = NVC0_3D_MACRO_DRAW_ELEMENTS_INDIRECT; 843bf215546Sopenharmony_ci } else { 844bf215546Sopenharmony_ci if (nvc0->state.index_bias) { 845bf215546Sopenharmony_ci /* index_bias is implied 0 if !info->index_size (really ?) */ 846bf215546Sopenharmony_ci IMMED_NVC0(push, NVC0_3D(VB_ELEMENT_BASE), 0); 847bf215546Sopenharmony_ci IMMED_NVC0(push, NVC0_3D(VERTEX_ID_BASE), 0); 848bf215546Sopenharmony_ci nvc0->state.index_bias = 0; 849bf215546Sopenharmony_ci } 850bf215546Sopenharmony_ci size = 4; 851bf215546Sopenharmony_ci if (buf_count) 852bf215546Sopenharmony_ci macro = NVC0_3D_MACRO_DRAW_ARRAYS_INDIRECT_COUNT; 853bf215546Sopenharmony_ci else 854bf215546Sopenharmony_ci macro = NVC0_3D_MACRO_DRAW_ARRAYS_INDIRECT; 855bf215546Sopenharmony_ci } 856bf215546Sopenharmony_ci 857bf215546Sopenharmony_ci /* If the stride is not the natural stride, we have to stick a separate 858bf215546Sopenharmony_ci * push data reference for each draw. Otherwise it can all go in as one. 859bf215546Sopenharmony_ci * Of course there is a maximum packet size, so we have to break things up 860bf215546Sopenharmony_ci * along those borders as well. 861bf215546Sopenharmony_ci */ 862bf215546Sopenharmony_ci while (count) { 863bf215546Sopenharmony_ci unsigned draws = count, pushes, i; 864bf215546Sopenharmony_ci if (indirect->stride == size * 4) { 865bf215546Sopenharmony_ci draws = MIN2(draws, (NV04_PFIFO_MAX_PACKET_LEN - 4) / size); 866bf215546Sopenharmony_ci pushes = 1; 867bf215546Sopenharmony_ci } else { 868bf215546Sopenharmony_ci draws = MIN2(draws, 32); 869bf215546Sopenharmony_ci pushes = draws; 870bf215546Sopenharmony_ci } 871bf215546Sopenharmony_ci 872bf215546Sopenharmony_ci nouveau_pushbuf_space(push, 16, 0, pushes + !!buf_count); 873bf215546Sopenharmony_ci PUSH_REFN(push, buf->bo, NOUVEAU_BO_RD | buf->domain); 874bf215546Sopenharmony_ci if (buf_count) 875bf215546Sopenharmony_ci PUSH_REFN(push, buf_count->bo, NOUVEAU_BO_RD | buf_count->domain); 876bf215546Sopenharmony_ci PUSH_DATA(push, 877bf215546Sopenharmony_ci NVC0_FIFO_PKHDR_1I(0, macro, 3 + !!buf_count + draws * size)); 878bf215546Sopenharmony_ci PUSH_DATA(push, nvc0_prim_gl(info->mode)); 879bf215546Sopenharmony_ci PUSH_DATA(push, drawid); 880bf215546Sopenharmony_ci PUSH_DATA(push, draws); 881bf215546Sopenharmony_ci if (buf_count) { 882bf215546Sopenharmony_ci nouveau_pushbuf_data(push, 883bf215546Sopenharmony_ci buf_count->bo, 884bf215546Sopenharmony_ci buf_count->offset + indirect->indirect_draw_count_offset, 885bf215546Sopenharmony_ci NVC0_IB_ENTRY_1_NO_PREFETCH | 4); 886bf215546Sopenharmony_ci } 887bf215546Sopenharmony_ci if (pushes == 1) { 888bf215546Sopenharmony_ci nouveau_pushbuf_data(push, 889bf215546Sopenharmony_ci buf->bo, offset, 890bf215546Sopenharmony_ci NVC0_IB_ENTRY_1_NO_PREFETCH | (size * 4 * draws)); 891bf215546Sopenharmony_ci offset += draws * indirect->stride; 892bf215546Sopenharmony_ci } else { 893bf215546Sopenharmony_ci for (i = 0; i < pushes; i++) { 894bf215546Sopenharmony_ci nouveau_pushbuf_data(push, 895bf215546Sopenharmony_ci buf->bo, offset, 896bf215546Sopenharmony_ci NVC0_IB_ENTRY_1_NO_PREFETCH | (size * 4)); 897bf215546Sopenharmony_ci offset += indirect->stride; 898bf215546Sopenharmony_ci } 899bf215546Sopenharmony_ci } 900bf215546Sopenharmony_ci count -= draws; 901bf215546Sopenharmony_ci drawid += draws; 902bf215546Sopenharmony_ci } 903bf215546Sopenharmony_ci} 904bf215546Sopenharmony_ci 905bf215546Sopenharmony_cistatic inline void 906bf215546Sopenharmony_cinvc0_update_prim_restart(struct nvc0_context *nvc0, bool en, uint32_t index) 907bf215546Sopenharmony_ci{ 908bf215546Sopenharmony_ci struct nouveau_pushbuf *push = nvc0->base.pushbuf; 909bf215546Sopenharmony_ci 910bf215546Sopenharmony_ci if (en != nvc0->state.prim_restart) { 911bf215546Sopenharmony_ci if (en) { 912bf215546Sopenharmony_ci BEGIN_NVC0(push, NVC0_3D(PRIM_RESTART_ENABLE), 2); 913bf215546Sopenharmony_ci PUSH_DATA (push, 1); 914bf215546Sopenharmony_ci PUSH_DATA (push, index); 915bf215546Sopenharmony_ci } else { 916bf215546Sopenharmony_ci IMMED_NVC0(push, NVC0_3D(PRIM_RESTART_ENABLE), 0); 917bf215546Sopenharmony_ci } 918bf215546Sopenharmony_ci nvc0->state.prim_restart = en; 919bf215546Sopenharmony_ci } else 920bf215546Sopenharmony_ci if (en) { 921bf215546Sopenharmony_ci BEGIN_NVC0(push, NVC0_3D(PRIM_RESTART_INDEX), 1); 922bf215546Sopenharmony_ci PUSH_DATA (push, index); 923bf215546Sopenharmony_ci } 924bf215546Sopenharmony_ci} 925bf215546Sopenharmony_ci 926bf215546Sopenharmony_civoid 927bf215546Sopenharmony_cinvc0_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info, 928bf215546Sopenharmony_ci unsigned drawid_offset, 929bf215546Sopenharmony_ci const struct pipe_draw_indirect_info *indirect, 930bf215546Sopenharmony_ci const struct pipe_draw_start_count_bias *draws, 931bf215546Sopenharmony_ci unsigned num_draws) 932bf215546Sopenharmony_ci{ 933bf215546Sopenharmony_ci if (num_draws > 1) { 934bf215546Sopenharmony_ci util_draw_multi(pipe, info, drawid_offset, indirect, draws, num_draws); 935bf215546Sopenharmony_ci return; 936bf215546Sopenharmony_ci } 937bf215546Sopenharmony_ci 938bf215546Sopenharmony_ci if (!indirect && (!draws[0].count || !info->instance_count)) 939bf215546Sopenharmony_ci return; 940bf215546Sopenharmony_ci 941bf215546Sopenharmony_ci struct nvc0_context *nvc0 = nvc0_context(pipe); 942bf215546Sopenharmony_ci struct nouveau_pushbuf *push = nvc0->base.pushbuf; 943bf215546Sopenharmony_ci struct nvc0_screen *screen = nvc0->screen; 944bf215546Sopenharmony_ci unsigned vram_domain = NV_VRAM_DOMAIN(&screen->base); 945bf215546Sopenharmony_ci int s; 946bf215546Sopenharmony_ci 947bf215546Sopenharmony_ci /* NOTE: caller must ensure that (min_index + index_bias) is >= 0 */ 948bf215546Sopenharmony_ci if (info->index_bounds_valid) { 949bf215546Sopenharmony_ci nvc0->vb_elt_first = info->min_index + (info->index_size ? draws->index_bias : 0); 950bf215546Sopenharmony_ci nvc0->vb_elt_limit = info->max_index - info->min_index; 951bf215546Sopenharmony_ci } else { 952bf215546Sopenharmony_ci nvc0->vb_elt_first = 0; 953bf215546Sopenharmony_ci nvc0->vb_elt_limit = ~0; 954bf215546Sopenharmony_ci } 955bf215546Sopenharmony_ci nvc0->instance_off = info->start_instance; 956bf215546Sopenharmony_ci nvc0->instance_max = info->instance_count - 1; 957bf215546Sopenharmony_ci 958bf215546Sopenharmony_ci /* For picking only a few vertices from a large user buffer, push is better, 959bf215546Sopenharmony_ci * if index count is larger and we expect repeated vertices, suggest upload. 960bf215546Sopenharmony_ci */ 961bf215546Sopenharmony_ci nvc0->vbo_push_hint = 962bf215546Sopenharmony_ci (!indirect || indirect->count_from_stream_output) && info->index_size && 963bf215546Sopenharmony_ci (nvc0->vb_elt_limit >= (draws[0].count * 2)); 964bf215546Sopenharmony_ci 965bf215546Sopenharmony_ci /* Check whether we want to switch vertex-submission mode. */ 966bf215546Sopenharmony_ci if (nvc0->vbo_user && !(nvc0->dirty_3d & (NVC0_NEW_3D_ARRAYS | NVC0_NEW_3D_VERTEX))) { 967bf215546Sopenharmony_ci if (nvc0->vbo_push_hint != !!nvc0->state.vbo_mode) 968bf215546Sopenharmony_ci if (nvc0->state.vbo_mode != 3) 969bf215546Sopenharmony_ci nvc0->dirty_3d |= NVC0_NEW_3D_ARRAYS; 970bf215546Sopenharmony_ci 971bf215546Sopenharmony_ci if (!(nvc0->dirty_3d & NVC0_NEW_3D_ARRAYS) && nvc0->state.vbo_mode == 0) { 972bf215546Sopenharmony_ci if (nvc0->vertex->shared_slots) 973bf215546Sopenharmony_ci nvc0_update_user_vbufs_shared(nvc0); 974bf215546Sopenharmony_ci else 975bf215546Sopenharmony_ci nvc0_update_user_vbufs(nvc0); 976bf215546Sopenharmony_ci } 977bf215546Sopenharmony_ci } 978bf215546Sopenharmony_ci 979bf215546Sopenharmony_ci if (info->mode == PIPE_PRIM_PATCHES && 980bf215546Sopenharmony_ci nvc0->state.patch_vertices != nvc0->patch_vertices) { 981bf215546Sopenharmony_ci nvc0->state.patch_vertices = nvc0->patch_vertices; 982bf215546Sopenharmony_ci PUSH_SPACE(push, 1); 983bf215546Sopenharmony_ci IMMED_NVC0(push, NVC0_3D(PATCH_VERTICES), nvc0->state.patch_vertices); 984bf215546Sopenharmony_ci } 985bf215546Sopenharmony_ci 986bf215546Sopenharmony_ci if (info->index_size && !info->has_user_indices) { 987bf215546Sopenharmony_ci struct nv04_resource *buf = nv04_resource(info->index.resource); 988bf215546Sopenharmony_ci 989bf215546Sopenharmony_ci assert(buf); 990bf215546Sopenharmony_ci assert(nouveau_resource_mapped_by_gpu(&buf->base)); 991bf215546Sopenharmony_ci 992bf215546Sopenharmony_ci PUSH_SPACE(push, 6); 993bf215546Sopenharmony_ci if (nvc0->screen->eng3d->oclass < TU102_3D_CLASS) { 994bf215546Sopenharmony_ci BEGIN_NVC0(push, NVC0_3D(INDEX_ARRAY_START_HIGH), 5); 995bf215546Sopenharmony_ci PUSH_DATAh(push, buf->address); 996bf215546Sopenharmony_ci PUSH_DATA (push, buf->address); 997bf215546Sopenharmony_ci PUSH_DATAh(push, buf->address + buf->base.width0 - 1); 998bf215546Sopenharmony_ci PUSH_DATA (push, buf->address + buf->base.width0 - 1); 999bf215546Sopenharmony_ci PUSH_DATA (push, info->index_size >> 1); 1000bf215546Sopenharmony_ci } else { 1001bf215546Sopenharmony_ci BEGIN_NVC0(push, NVC0_3D(INDEX_ARRAY_START_HIGH), 2); 1002bf215546Sopenharmony_ci PUSH_DATAh(push, buf->address); 1003bf215546Sopenharmony_ci PUSH_DATA (push, buf->address); 1004bf215546Sopenharmony_ci BEGIN_NVC0(push, SUBC_3D(TU102_3D_INDEX_ARRAY_LIMIT_HIGH), 2); 1005bf215546Sopenharmony_ci PUSH_DATAh(push, buf->address + buf->base.width0 - 1); 1006bf215546Sopenharmony_ci PUSH_DATA (push, buf->address + buf->base.width0 - 1); 1007bf215546Sopenharmony_ci BEGIN_NVC0(push, NVC0_3D(INDEX_FORMAT), 1); 1008bf215546Sopenharmony_ci PUSH_DATA (push, info->index_size >> 1); 1009bf215546Sopenharmony_ci } 1010bf215546Sopenharmony_ci 1011bf215546Sopenharmony_ci BCTX_REFN(nvc0->bufctx_3d, 3D_IDX, buf, RD); 1012bf215546Sopenharmony_ci } 1013bf215546Sopenharmony_ci 1014bf215546Sopenharmony_ci list_for_each_entry(struct nvc0_resident, resident, &nvc0->tex_head, list) { 1015bf215546Sopenharmony_ci nvc0_add_resident(nvc0->bufctx_3d, NVC0_BIND_3D_BINDLESS, resident->buf, 1016bf215546Sopenharmony_ci resident->flags); 1017bf215546Sopenharmony_ci } 1018bf215546Sopenharmony_ci 1019bf215546Sopenharmony_ci list_for_each_entry(struct nvc0_resident, resident, &nvc0->img_head, list) { 1020bf215546Sopenharmony_ci nvc0_add_resident(nvc0->bufctx_3d, NVC0_BIND_3D_BINDLESS, resident->buf, 1021bf215546Sopenharmony_ci resident->flags); 1022bf215546Sopenharmony_ci } 1023bf215546Sopenharmony_ci 1024bf215546Sopenharmony_ci BCTX_REFN_bo(nvc0->bufctx_3d, 3D_TEXT, vram_domain | NOUVEAU_BO_RD, 1025bf215546Sopenharmony_ci screen->text); 1026bf215546Sopenharmony_ci 1027bf215546Sopenharmony_ci nvc0_state_validate_3d(nvc0, ~0); 1028bf215546Sopenharmony_ci 1029bf215546Sopenharmony_ci if (nvc0->vertprog->vp.need_draw_parameters && (!indirect || indirect->count_from_stream_output)) { 1030bf215546Sopenharmony_ci PUSH_SPACE(push, 9); 1031bf215546Sopenharmony_ci BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 3); 1032bf215546Sopenharmony_ci PUSH_DATA (push, NVC0_CB_AUX_SIZE); 1033bf215546Sopenharmony_ci PUSH_DATAh(push, screen->uniform_bo->offset + NVC0_CB_AUX_INFO(0)); 1034bf215546Sopenharmony_ci PUSH_DATA (push, screen->uniform_bo->offset + NVC0_CB_AUX_INFO(0)); 1035bf215546Sopenharmony_ci BEGIN_1IC0(push, NVC0_3D(CB_POS), 1 + 3); 1036bf215546Sopenharmony_ci PUSH_DATA (push, NVC0_CB_AUX_DRAW_INFO); 1037bf215546Sopenharmony_ci PUSH_DATA (push, info->index_size ? draws->index_bias : 0); 1038bf215546Sopenharmony_ci PUSH_DATA (push, info->start_instance); 1039bf215546Sopenharmony_ci PUSH_DATA (push, drawid_offset); 1040bf215546Sopenharmony_ci } 1041bf215546Sopenharmony_ci 1042bf215546Sopenharmony_ci if (nvc0->screen->base.class_3d < NVE4_3D_CLASS && 1043bf215546Sopenharmony_ci nvc0->seamless_cube_map != nvc0->state.seamless_cube_map) { 1044bf215546Sopenharmony_ci nvc0->state.seamless_cube_map = nvc0->seamless_cube_map; 1045bf215546Sopenharmony_ci PUSH_SPACE(push, 1); 1046bf215546Sopenharmony_ci IMMED_NVC0(push, NVC0_3D(TEX_MISC), 1047bf215546Sopenharmony_ci nvc0->seamless_cube_map ? NVC0_3D_TEX_MISC_SEAMLESS_CUBE_MAP : 0); 1048bf215546Sopenharmony_ci } 1049bf215546Sopenharmony_ci 1050bf215546Sopenharmony_ci push->kick_notify = nvc0_draw_vbo_kick_notify; 1051bf215546Sopenharmony_ci 1052bf215546Sopenharmony_ci for (s = 0; s < 5 && !nvc0->cb_dirty; ++s) { 1053bf215546Sopenharmony_ci if (nvc0->constbuf_coherent[s]) 1054bf215546Sopenharmony_ci nvc0->cb_dirty = true; 1055bf215546Sopenharmony_ci } 1056bf215546Sopenharmony_ci 1057bf215546Sopenharmony_ci if (nvc0->cb_dirty) { 1058bf215546Sopenharmony_ci PUSH_SPACE(push, 1); 1059bf215546Sopenharmony_ci IMMED_NVC0(push, NVC0_3D(MEM_BARRIER), 0x1011); 1060bf215546Sopenharmony_ci nvc0->cb_dirty = false; 1061bf215546Sopenharmony_ci } 1062bf215546Sopenharmony_ci 1063bf215546Sopenharmony_ci for (s = 0; s < 5; ++s) { 1064bf215546Sopenharmony_ci if (!nvc0->textures_coherent[s]) 1065bf215546Sopenharmony_ci continue; 1066bf215546Sopenharmony_ci 1067bf215546Sopenharmony_ci PUSH_SPACE(push, nvc0->num_textures[s] * 2); 1068bf215546Sopenharmony_ci 1069bf215546Sopenharmony_ci for (int i = 0; i < nvc0->num_textures[s]; ++i) { 1070bf215546Sopenharmony_ci struct nv50_tic_entry *tic = nv50_tic_entry(nvc0->textures[s][i]); 1071bf215546Sopenharmony_ci if (!(nvc0->textures_coherent[s] & (1 << i))) 1072bf215546Sopenharmony_ci continue; 1073bf215546Sopenharmony_ci 1074bf215546Sopenharmony_ci BEGIN_NVC0(push, NVC0_3D(TEX_CACHE_CTL), 1); 1075bf215546Sopenharmony_ci PUSH_DATA (push, (tic->id << 4) | 1); 1076bf215546Sopenharmony_ci NOUVEAU_DRV_STAT(&nvc0->screen->base, tex_cache_flush_count, 1); 1077bf215546Sopenharmony_ci } 1078bf215546Sopenharmony_ci } 1079bf215546Sopenharmony_ci 1080bf215546Sopenharmony_ci if (nvc0->state.vbo_mode) { 1081bf215546Sopenharmony_ci if (indirect && indirect->buffer) 1082bf215546Sopenharmony_ci nvc0_push_vbo_indirect(nvc0, info, drawid_offset, indirect, &draws[0]); 1083bf215546Sopenharmony_ci else 1084bf215546Sopenharmony_ci nvc0_push_vbo(nvc0, info, indirect, &draws[0]); 1085bf215546Sopenharmony_ci goto cleanup; 1086bf215546Sopenharmony_ci } 1087bf215546Sopenharmony_ci 1088bf215546Sopenharmony_ci /* space for base instance, flush, and prim restart */ 1089bf215546Sopenharmony_ci PUSH_SPACE(push, 8); 1090bf215546Sopenharmony_ci 1091bf215546Sopenharmony_ci if (nvc0->state.instance_base != info->start_instance) { 1092bf215546Sopenharmony_ci nvc0->state.instance_base = info->start_instance; 1093bf215546Sopenharmony_ci /* NOTE: this does not affect the shader input, should it ? */ 1094bf215546Sopenharmony_ci BEGIN_NVC0(push, NVC0_3D(VB_INSTANCE_BASE), 1); 1095bf215546Sopenharmony_ci PUSH_DATA (push, info->start_instance); 1096bf215546Sopenharmony_ci } 1097bf215546Sopenharmony_ci 1098bf215546Sopenharmony_ci nvc0->base.vbo_dirty |= !!nvc0->vtxbufs_coherent; 1099bf215546Sopenharmony_ci 1100bf215546Sopenharmony_ci if (!nvc0->base.vbo_dirty && info->index_size && !info->has_user_indices && 1101bf215546Sopenharmony_ci info->index.resource->flags & PIPE_RESOURCE_FLAG_MAP_COHERENT) 1102bf215546Sopenharmony_ci nvc0->base.vbo_dirty = true; 1103bf215546Sopenharmony_ci 1104bf215546Sopenharmony_ci nvc0_update_prim_restart(nvc0, info->primitive_restart, info->restart_index); 1105bf215546Sopenharmony_ci 1106bf215546Sopenharmony_ci if (nvc0->base.vbo_dirty) { 1107bf215546Sopenharmony_ci if (nvc0->screen->eng3d->oclass < GM107_3D_CLASS) 1108bf215546Sopenharmony_ci IMMED_NVC0(push, NVC0_3D(VERTEX_ARRAY_FLUSH), 0); 1109bf215546Sopenharmony_ci nvc0->base.vbo_dirty = false; 1110bf215546Sopenharmony_ci } 1111bf215546Sopenharmony_ci 1112bf215546Sopenharmony_ci if (unlikely(indirect && indirect->buffer)) { 1113bf215546Sopenharmony_ci nvc0_draw_indirect(nvc0, info, drawid_offset, indirect); 1114bf215546Sopenharmony_ci } else 1115bf215546Sopenharmony_ci if (unlikely(indirect && indirect->count_from_stream_output)) { 1116bf215546Sopenharmony_ci nvc0_draw_stream_output(nvc0, info, indirect); 1117bf215546Sopenharmony_ci } else 1118bf215546Sopenharmony_ci if (info->index_size) { 1119bf215546Sopenharmony_ci bool shorten = info->index_bounds_valid && info->max_index <= 65535; 1120bf215546Sopenharmony_ci 1121bf215546Sopenharmony_ci if (info->primitive_restart && info->restart_index > 65535) 1122bf215546Sopenharmony_ci shorten = false; 1123bf215546Sopenharmony_ci 1124bf215546Sopenharmony_ci nvc0_draw_elements(nvc0, shorten, info, 1125bf215546Sopenharmony_ci info->mode, draws[0].start, draws[0].count, 1126bf215546Sopenharmony_ci info->instance_count, draws->index_bias, info->index_size); 1127bf215546Sopenharmony_ci } else { 1128bf215546Sopenharmony_ci nvc0_draw_arrays(nvc0, 1129bf215546Sopenharmony_ci info->mode, draws[0].start, draws[0].count, 1130bf215546Sopenharmony_ci info->instance_count); 1131bf215546Sopenharmony_ci } 1132bf215546Sopenharmony_ci 1133bf215546Sopenharmony_cicleanup: 1134bf215546Sopenharmony_ci push->kick_notify = nvc0_default_kick_notify; 1135bf215546Sopenharmony_ci 1136bf215546Sopenharmony_ci nvc0_release_user_vbufs(nvc0); 1137bf215546Sopenharmony_ci 1138bf215546Sopenharmony_ci nouveau_pushbuf_bufctx(push, NULL); 1139bf215546Sopenharmony_ci 1140bf215546Sopenharmony_ci nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_TEXT); 1141bf215546Sopenharmony_ci nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_IDX); 1142bf215546Sopenharmony_ci nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_BINDLESS); 1143bf215546Sopenharmony_ci} 1144