vc4: Move render command list calls to vc4_flush()
[mesa.git] / src / gallium / drivers / vc4 / vc4_draw.c
1 /*
2 * Copyright (c) 2014 Scott Mansell
3 * Copyright © 2014 Broadcom
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 * IN THE SOFTWARE.
23 */
24
25 #include <stdio.h>
26
27 #include "util/u_format.h"
28 #include "indices/u_primconvert.h"
29
30 #include "vc4_context.h"
31 #include "vc4_resource.h"
32
33 static void
34 vc4_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info)
35 {
36 struct vc4_context *vc4 = vc4_context(pctx);
37
38 if (info->mode >= PIPE_PRIM_QUADS) {
39 util_primconvert_save_index_buffer(vc4->primconvert, &vc4->indexbuf);
40 util_primconvert_save_rasterizer_state(vc4->primconvert, &vc4->rasterizer->base);
41 util_primconvert_draw_vbo(vc4->primconvert, info);
42 return;
43 }
44
45 uint32_t width = vc4->framebuffer.width;
46 uint32_t height = vc4->framebuffer.height;
47 uint32_t tilew = align(width, 64) / 64;
48 uint32_t tileh = align(height, 64) / 64;
49
50 uint32_t tile_alloc_size = 32 * tilew * tileh * 16;
51 uint32_t tile_state_size = 48 * tilew * tileh;
52 if (!vc4->tile_alloc || vc4->tile_alloc->size < tile_alloc_size) {
53 vc4_bo_unreference(&vc4->tile_alloc);
54 vc4->tile_alloc = vc4_bo_alloc(vc4->screen, tile_alloc_size,
55 "tile_alloc");
56 }
57 if (!vc4->tile_state || vc4->tile_state->size < tile_state_size) {
58 vc4_bo_unreference(&vc4->tile_state);
59 vc4->tile_state = vc4_bo_alloc(vc4->screen, tile_state_size,
60 "tile_state");
61 }
62
63 vc4_update_compiled_shaders(vc4);
64
65 vc4->needs_flush = true;
66
67 // Tile state data is 48 bytes per tile, I think it can be thrown away
68 // as soon as binning is finished.
69 cl_start_reloc(&vc4->bcl, 2);
70 cl_u8(&vc4->bcl, VC4_PACKET_TILE_BINNING_MODE_CONFIG);
71 cl_reloc(vc4, &vc4->bcl, vc4->tile_alloc, 0);
72 cl_u32(&vc4->bcl, vc4->tile_alloc->size);
73 cl_reloc(vc4, &vc4->bcl, vc4->tile_state, 0);
74 cl_u8(&vc4->bcl, tilew);
75 cl_u8(&vc4->bcl, tileh);
76 cl_u8(&vc4->bcl, VC4_BIN_CONFIG_AUTO_INIT_TSDA);
77
78 cl_u8(&vc4->bcl, VC4_PACKET_START_TILE_BINNING);
79
80 cl_u8(&vc4->bcl, VC4_PACKET_PRIMITIVE_LIST_FORMAT);
81 cl_u8(&vc4->bcl, 0x12); // 16 bit triangle
82
83 vc4_emit_state(pctx);
84
85 /* the actual draw call. */
86 struct vc4_vertex_stateobj *vtx = vc4->vtx;
87 struct vc4_vertexbuf_stateobj *vertexbuf = &vc4->vertexbuf;
88 cl_u8(&vc4->bcl, VC4_PACKET_GL_SHADER_STATE);
89 assert(vtx->num_elements <= 8);
90 /* Note that number of attributes == 0 in the packet means 8
91 * attributes. This field also contains the offset into shader_rec.
92 */
93 cl_u32(&vc4->bcl, vtx->num_elements & 0x7);
94
95 /* Note that the primitive type fields match with OpenGL/gallium
96 * definitions, up to but not including QUADS.
97 */
98 if (info->indexed) {
99 struct vc4_resource *rsc = vc4_resource(vc4->indexbuf.buffer);
100
101 assert(vc4->indexbuf.index_size == 1 ||
102 vc4->indexbuf.index_size == 2);
103
104 cl_start_reloc(&vc4->bcl, 1);
105 cl_u8(&vc4->bcl, VC4_PACKET_GL_INDEXED_PRIMITIVE);
106 cl_u8(&vc4->bcl,
107 info->mode |
108 (vc4->indexbuf.index_size == 2 ?
109 VC4_INDEX_BUFFER_U16:
110 VC4_INDEX_BUFFER_U8));
111 cl_u32(&vc4->bcl, info->count);
112 cl_reloc(vc4, &vc4->bcl, rsc->bo, vc4->indexbuf.offset);
113 cl_u32(&vc4->bcl, info->max_index);
114 } else {
115 cl_u8(&vc4->bcl, VC4_PACKET_GL_ARRAY_PRIMITIVE);
116 cl_u8(&vc4->bcl, info->mode);
117 cl_u32(&vc4->bcl, info->count);
118 cl_u32(&vc4->bcl, info->start);
119 }
120
121 // Shader Record
122
123 vc4_write_uniforms(vc4, vc4->prog.fs,
124 &vc4->constbuf[PIPE_SHADER_FRAGMENT],
125 &vc4->fragtex,
126 0);
127 vc4_write_uniforms(vc4, vc4->prog.vs,
128 &vc4->constbuf[PIPE_SHADER_VERTEX],
129 &vc4->verttex,
130 0);
131 vc4_write_uniforms(vc4, vc4->prog.vs,
132 &vc4->constbuf[PIPE_SHADER_VERTEX],
133 &vc4->verttex,
134 1);
135
136 cl_start_shader_reloc(&vc4->shader_rec, 3 + vtx->num_elements);
137 cl_u16(&vc4->shader_rec, VC4_SHADER_FLAG_ENABLE_CLIPPING);
138 cl_u8(&vc4->shader_rec, 0); /* fs num uniforms (unused) */
139 cl_u8(&vc4->shader_rec, vc4->prog.fs->num_inputs);
140 cl_reloc(vc4, &vc4->shader_rec, vc4->prog.fs->bo, 0);
141 cl_u32(&vc4->shader_rec, 0); /* UBO offset written by kernel */
142
143 cl_u16(&vc4->shader_rec, 0); /* vs num uniforms */
144 cl_u8(&vc4->shader_rec, (1 << vtx->num_elements) - 1); /* vs attribute array bitfield */
145 cl_u8(&vc4->shader_rec, 16 * vtx->num_elements); /* vs total attribute size */
146 cl_reloc(vc4, &vc4->shader_rec, vc4->prog.vs->bo, 0);
147 cl_u32(&vc4->shader_rec, 0); /* UBO offset written by kernel */
148
149 cl_u16(&vc4->shader_rec, 0); /* cs num uniforms */
150 cl_u8(&vc4->shader_rec, (1 << vtx->num_elements) - 1); /* cs attribute array bitfield */
151 cl_u8(&vc4->shader_rec, 16 * vtx->num_elements); /* vs total attribute size */
152 cl_reloc(vc4, &vc4->shader_rec, vc4->prog.vs->bo,
153 vc4->prog.vs->coord_shader_offset);
154 cl_u32(&vc4->shader_rec, 0); /* UBO offset written by kernel */
155
156 for (int i = 0; i < vtx->num_elements; i++) {
157 struct pipe_vertex_element *elem = &vtx->pipe[i];
158 struct pipe_vertex_buffer *vb =
159 &vertexbuf->vb[elem->vertex_buffer_index];
160 struct vc4_resource *rsc = vc4_resource(vb->buffer);
161
162 cl_reloc(vc4, &vc4->shader_rec, rsc->bo,
163 vb->buffer_offset + elem->src_offset);
164 cl_u8(&vc4->shader_rec,
165 util_format_get_blocksize(elem->src_format) - 1);
166 cl_u8(&vc4->shader_rec, vb->stride);
167 cl_u8(&vc4->shader_rec, i * 16); /* VS VPM offset */
168 cl_u8(&vc4->shader_rec, i * 16); /* CS VPM offset */
169 }
170
171
172 vc4->shader_rec_count++;
173
174 cl_u8(&vc4->rcl, VC4_PACKET_CLEAR_COLORS);
175 cl_u32(&vc4->rcl, 0xff000000); // Opaque Black
176 cl_u32(&vc4->rcl, 0xff000000); // 32 bit clear colours need to be repeated twice
177 cl_u32(&vc4->rcl, 0);
178 cl_u8(&vc4->rcl, 0);
179
180 struct vc4_surface *csurf = vc4_surface(vc4->framebuffer.cbufs[0]);
181 struct vc4_resource *ctex = vc4_resource(csurf->base.texture);
182
183 cl_start_reloc(&vc4->rcl, 1);
184 cl_u8(&vc4->rcl, VC4_PACKET_TILE_RENDERING_MODE_CONFIG);
185 cl_reloc(vc4, &vc4->rcl, ctex->bo, csurf->offset);
186 cl_u16(&vc4->rcl, width);
187 cl_u16(&vc4->rcl, height);
188 cl_u8(&vc4->rcl, (VC4_RENDER_CONFIG_MEMORY_FORMAT_LINEAR |
189 VC4_RENDER_CONFIG_FORMAT_RGBA8888));
190 cl_u8(&vc4->rcl, 0);
191
192 // Do a store of the first tile to force the tile buffer to be cleared
193 /* XXX: I think these two packets may be unnecessary. */
194 if (0) {
195 cl_u8(&vc4->rcl, VC4_PACKET_TILE_COORDINATES);
196 cl_u8(&vc4->rcl, 0);
197 cl_u8(&vc4->rcl, 0);
198
199 cl_u8(&vc4->rcl, VC4_PACKET_STORE_TILE_BUFFER_GENERAL);
200 cl_u16(&vc4->rcl, 0); // Store nothing (just clear)
201 cl_u32(&vc4->rcl, 0); // no address is needed
202 }
203
204 vc4_flush(pctx);
205 }
206
207 static void
208 vc4_clear(struct pipe_context *pctx, unsigned buffers,
209 const union pipe_color_union *color, double depth, unsigned stencil)
210 {
211 struct vc4_context *vc4 = vc4_context(pctx);
212
213 vc4->needs_flush = true;
214 }
215
216 static void
217 vc4_clear_render_target(struct pipe_context *pctx, struct pipe_surface *ps,
218 const union pipe_color_union *color,
219 unsigned x, unsigned y, unsigned w, unsigned h)
220 {
221 fprintf(stderr, "unimpl: clear RT\n");
222 }
223
224 static void
225 vc4_clear_depth_stencil(struct pipe_context *pctx, struct pipe_surface *ps,
226 unsigned buffers, double depth, unsigned stencil,
227 unsigned x, unsigned y, unsigned w, unsigned h)
228 {
229 fprintf(stderr, "unimpl: clear DS\n");
230 }
231
232 void
233 vc4_draw_init(struct pipe_context *pctx)
234 {
235 pctx->draw_vbo = vc4_draw_vbo;
236 pctx->clear = vc4_clear;
237 pctx->clear_render_target = vc4_clear_render_target;
238 pctx->clear_depth_stencil = vc4_clear_depth_stencil;
239 }