+ /* The simulator throws a fit if VS or CS don't read an attribute, so
+ * we emit a dummy read.
+ */
+ uint32_t num_elements_emit = MAX2(vtx->num_elements, 1);
+ /* Emit the shader record. */
+ struct vc4_cl_out *shader_rec =
+ cl_start_shader_reloc(&vc4->shader_rec, 3 + num_elements_emit);
+ /* VC4_DIRTY_PRIM_MODE | VC4_DIRTY_RASTERIZER */
+ cl_u16(&shader_rec,
+ VC4_SHADER_FLAG_ENABLE_CLIPPING |
+ VC4_SHADER_FLAG_FS_SINGLE_THREAD |
+ ((info->mode == PIPE_PRIM_POINTS &&
+ vc4->rasterizer->base.point_size_per_vertex) ?
+ VC4_SHADER_FLAG_VS_POINT_SIZE : 0));
+
+ /* VC4_DIRTY_COMPILED_FS */
+ cl_u8(&shader_rec, 0); /* fs num uniforms (unused) */
+ cl_u8(&shader_rec, vc4->prog.fs->num_inputs);
+ cl_reloc(vc4, &vc4->shader_rec, &shader_rec, vc4->prog.fs->bo, 0);
+ cl_u32(&shader_rec, 0); /* UBO offset written by kernel */
+
+ /* VC4_DIRTY_COMPILED_VS */
+ cl_u16(&shader_rec, 0); /* vs num uniforms */
+ cl_u8(&shader_rec, vc4->prog.vs->vattrs_live);
+ cl_u8(&shader_rec, vc4->prog.vs->vattr_offsets[8]);
+ cl_reloc(vc4, &vc4->shader_rec, &shader_rec, vc4->prog.vs->bo, 0);
+ cl_u32(&shader_rec, 0); /* UBO offset written by kernel */
+
+ /* VC4_DIRTY_COMPILED_CS */
+ cl_u16(&shader_rec, 0); /* cs num uniforms */
+ cl_u8(&shader_rec, vc4->prog.cs->vattrs_live);
+ cl_u8(&shader_rec, vc4->prog.cs->vattr_offsets[8]);
+ cl_reloc(vc4, &vc4->shader_rec, &shader_rec, vc4->prog.cs->bo, 0);
+ cl_u32(&shader_rec, 0); /* UBO offset written by kernel */
+
+ uint32_t max_index = 0xffff;
+ for (int i = 0; i < vtx->num_elements; i++) {
+ struct pipe_vertex_element *elem = &vtx->pipe[i];
+ struct pipe_vertex_buffer *vb =
+ &vertexbuf->vb[elem->vertex_buffer_index];
+ struct vc4_resource *rsc = vc4_resource(vb->buffer);
+ /* not vc4->dirty tracked: vc4->last_index_bias */
+ uint32_t offset = (vb->buffer_offset +
+ elem->src_offset +
+ vb->stride * info->index_bias);
+ uint32_t vb_size = rsc->bo->size - offset;
+ uint32_t elem_size =
+ util_format_get_blocksize(elem->src_format);
+
+ cl_reloc(vc4, &vc4->shader_rec, &shader_rec, rsc->bo, offset);
+ cl_u8(&shader_rec, elem_size - 1);
+ cl_u8(&shader_rec, vb->stride);
+ cl_u8(&shader_rec, vc4->prog.vs->vattr_offsets[i]);
+ cl_u8(&shader_rec, vc4->prog.cs->vattr_offsets[i]);
+
+ if (vb->stride > 0) {
+ max_index = MIN2(max_index,
+ (vb_size - elem_size) / vb->stride);
+ }
+ }
+
+ if (vtx->num_elements == 0) {
+ assert(num_elements_emit == 1);
+ struct vc4_bo *bo = vc4_bo_alloc(vc4->screen, 4096, "scratch VBO");
+ cl_reloc(vc4, &vc4->shader_rec, &shader_rec, bo, 0);
+ cl_u8(&shader_rec, 16 - 1); /* element size */
+ cl_u8(&shader_rec, 0); /* stride */
+ cl_u8(&shader_rec, 0); /* VS VPM offset */
+ cl_u8(&shader_rec, 0); /* CS VPM offset */
+ vc4_bo_unreference(&bo);
+ }
+ cl_end(&vc4->shader_rec, shader_rec);