af5954663795c2ae36c5cdcca2745381c1b95057
[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 "util/u_pack_color.h"
29 #include "indices/u_primconvert.h"
30
31 #include "vc4_context.h"
32 #include "vc4_resource.h"
33
34 /**
35 * Does the initial bining command list setup for drawing to a given FBO.
36 */
37 static void
38 vc4_start_draw(struct vc4_context *vc4)
39 {
40 if (vc4->needs_flush)
41 return;
42
43 uint32_t width = vc4->framebuffer.width;
44 uint32_t height = vc4->framebuffer.height;
45 uint32_t tilew = align(width, 64) / 64;
46 uint32_t tileh = align(height, 64) / 64;
47
48 uint32_t tile_alloc_size = 32 * tilew * tileh * 16;
49 uint32_t tile_state_size = 48 * tilew * tileh;
50 if (!vc4->tile_alloc || vc4->tile_alloc->size < tile_alloc_size) {
51 vc4_bo_unreference(&vc4->tile_alloc);
52 vc4->tile_alloc = vc4_bo_alloc(vc4->screen, tile_alloc_size,
53 "tile_alloc");
54 }
55 if (!vc4->tile_state || vc4->tile_state->size < tile_state_size) {
56 vc4_bo_unreference(&vc4->tile_state);
57 vc4->tile_state = vc4_bo_alloc(vc4->screen, tile_state_size,
58 "tile_state");
59 }
60
61 // Tile state data is 48 bytes per tile, I think it can be thrown away
62 // as soon as binning is finished.
63 cl_start_reloc(&vc4->bcl, 2);
64 cl_u8(&vc4->bcl, VC4_PACKET_TILE_BINNING_MODE_CONFIG);
65 cl_reloc(vc4, &vc4->bcl, vc4->tile_alloc, 0);
66 cl_u32(&vc4->bcl, vc4->tile_alloc->size);
67 cl_reloc(vc4, &vc4->bcl, vc4->tile_state, 0);
68 cl_u8(&vc4->bcl, tilew);
69 cl_u8(&vc4->bcl, tileh);
70 cl_u8(&vc4->bcl, VC4_BIN_CONFIG_AUTO_INIT_TSDA);
71
72 cl_u8(&vc4->bcl, VC4_PACKET_START_TILE_BINNING);
73
74 cl_u8(&vc4->bcl, VC4_PACKET_PRIMITIVE_LIST_FORMAT);
75 cl_u8(&vc4->bcl, 0x12); // 16 bit triangle
76
77 vc4->needs_flush = true;
78 vc4->draw_call_queued = true;
79 }
80
81 static void
82 vc4_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info)
83 {
84 struct vc4_context *vc4 = vc4_context(pctx);
85
86 if (info->mode >= PIPE_PRIM_QUADS) {
87 util_primconvert_save_index_buffer(vc4->primconvert, &vc4->indexbuf);
88 util_primconvert_save_rasterizer_state(vc4->primconvert, &vc4->rasterizer->base);
89 util_primconvert_draw_vbo(vc4->primconvert, info);
90 return;
91 }
92
93 vc4_start_draw(vc4);
94 vc4_update_compiled_shaders(vc4);
95
96 vc4_emit_state(pctx);
97
98 /* the actual draw call. */
99 struct vc4_vertex_stateobj *vtx = vc4->vtx;
100 struct vc4_vertexbuf_stateobj *vertexbuf = &vc4->vertexbuf;
101 cl_u8(&vc4->bcl, VC4_PACKET_GL_SHADER_STATE);
102 assert(vtx->num_elements <= 8);
103 /* Note that number of attributes == 0 in the packet means 8
104 * attributes. This field also contains the offset into shader_rec.
105 */
106 cl_u32(&vc4->bcl, vtx->num_elements & 0x7);
107
108 /* Note that the primitive type fields match with OpenGL/gallium
109 * definitions, up to but not including QUADS.
110 */
111 if (info->indexed) {
112 struct vc4_resource *rsc = vc4_resource(vc4->indexbuf.buffer);
113
114 assert(vc4->indexbuf.index_size == 1 ||
115 vc4->indexbuf.index_size == 2);
116
117 cl_start_reloc(&vc4->bcl, 1);
118 cl_u8(&vc4->bcl, VC4_PACKET_GL_INDEXED_PRIMITIVE);
119 cl_u8(&vc4->bcl,
120 info->mode |
121 (vc4->indexbuf.index_size == 2 ?
122 VC4_INDEX_BUFFER_U16:
123 VC4_INDEX_BUFFER_U8));
124 cl_u32(&vc4->bcl, info->count);
125 cl_reloc(vc4, &vc4->bcl, rsc->bo, vc4->indexbuf.offset);
126 cl_u32(&vc4->bcl, info->max_index);
127 } else {
128 cl_u8(&vc4->bcl, VC4_PACKET_GL_ARRAY_PRIMITIVE);
129 cl_u8(&vc4->bcl, info->mode);
130 cl_u32(&vc4->bcl, info->count);
131 cl_u32(&vc4->bcl, info->start);
132 }
133
134 // Shader Record
135
136 vc4_write_uniforms(vc4, vc4->prog.fs,
137 &vc4->constbuf[PIPE_SHADER_FRAGMENT],
138 &vc4->fragtex,
139 0);
140 vc4_write_uniforms(vc4, vc4->prog.vs,
141 &vc4->constbuf[PIPE_SHADER_VERTEX],
142 &vc4->verttex,
143 0);
144 vc4_write_uniforms(vc4, vc4->prog.vs,
145 &vc4->constbuf[PIPE_SHADER_VERTEX],
146 &vc4->verttex,
147 1);
148
149 cl_start_shader_reloc(&vc4->shader_rec, 3 + vtx->num_elements);
150 cl_u16(&vc4->shader_rec, VC4_SHADER_FLAG_ENABLE_CLIPPING);
151 cl_u8(&vc4->shader_rec, 0); /* fs num uniforms (unused) */
152 cl_u8(&vc4->shader_rec, vc4->prog.fs->num_inputs);
153 cl_reloc(vc4, &vc4->shader_rec, vc4->prog.fs->bo, 0);
154 cl_u32(&vc4->shader_rec, 0); /* UBO offset written by kernel */
155
156 cl_u16(&vc4->shader_rec, 0); /* vs num uniforms */
157 cl_u8(&vc4->shader_rec, (1 << vtx->num_elements) - 1); /* vs attribute array bitfield */
158 cl_u8(&vc4->shader_rec, 16 * vtx->num_elements); /* vs total attribute size */
159 cl_reloc(vc4, &vc4->shader_rec, vc4->prog.vs->bo, 0);
160 cl_u32(&vc4->shader_rec, 0); /* UBO offset written by kernel */
161
162 cl_u16(&vc4->shader_rec, 0); /* cs num uniforms */
163 cl_u8(&vc4->shader_rec, (1 << vtx->num_elements) - 1); /* cs attribute array bitfield */
164 cl_u8(&vc4->shader_rec, 16 * vtx->num_elements); /* vs total attribute size */
165 cl_reloc(vc4, &vc4->shader_rec, vc4->prog.vs->bo,
166 vc4->prog.vs->coord_shader_offset);
167 cl_u32(&vc4->shader_rec, 0); /* UBO offset written by kernel */
168
169 for (int i = 0; i < vtx->num_elements; i++) {
170 struct pipe_vertex_element *elem = &vtx->pipe[i];
171 struct pipe_vertex_buffer *vb =
172 &vertexbuf->vb[elem->vertex_buffer_index];
173 struct vc4_resource *rsc = vc4_resource(vb->buffer);
174
175 cl_reloc(vc4, &vc4->shader_rec, rsc->bo,
176 vb->buffer_offset + elem->src_offset);
177 cl_u8(&vc4->shader_rec,
178 util_format_get_blocksize(elem->src_format) - 1);
179 cl_u8(&vc4->shader_rec, vb->stride);
180 cl_u8(&vc4->shader_rec, i * 16); /* VS VPM offset */
181 cl_u8(&vc4->shader_rec, i * 16); /* CS VPM offset */
182 }
183
184 if (vc4->zsa && vc4->zsa->depth.enabled) {
185 vc4->resolve |= PIPE_CLEAR_DEPTH;
186 }
187 vc4->resolve |= PIPE_CLEAR_COLOR0;
188
189 vc4->shader_rec_count++;
190
191 vc4_flush(pctx);
192 }
193
194 static uint32_t
195 pack_rgba(enum pipe_format format, const float *rgba)
196 {
197 union util_color uc;
198 util_pack_color(rgba, format, &uc);
199 return uc.ui[0];
200 }
201
202 static void
203 vc4_clear(struct pipe_context *pctx, unsigned buffers,
204 const union pipe_color_union *color, double depth, unsigned stencil)
205 {
206 struct vc4_context *vc4 = vc4_context(pctx);
207
208 /* We can't flag new buffers for clearing once we've queued draws. We
209 * could avoid this by using the 3d engine to clear.
210 */
211 if (vc4->draw_call_queued)
212 vc4_flush(pctx);
213
214 if (buffers & PIPE_CLEAR_COLOR0) {
215 vc4->clear_color[0] = vc4->clear_color[1] =
216 pack_rgba(vc4->framebuffer.cbufs[0]->format,
217 color->f);
218 }
219
220 vc4->cleared |= buffers;
221 vc4->resolve |= buffers;
222
223 vc4_start_draw(vc4);
224 }
225
226 static void
227 vc4_clear_render_target(struct pipe_context *pctx, struct pipe_surface *ps,
228 const union pipe_color_union *color,
229 unsigned x, unsigned y, unsigned w, unsigned h)
230 {
231 fprintf(stderr, "unimpl: clear RT\n");
232 }
233
234 static void
235 vc4_clear_depth_stencil(struct pipe_context *pctx, struct pipe_surface *ps,
236 unsigned buffers, double depth, unsigned stencil,
237 unsigned x, unsigned y, unsigned w, unsigned h)
238 {
239 fprintf(stderr, "unimpl: clear DS\n");
240 }
241
242 void
243 vc4_draw_init(struct pipe_context *pctx)
244 {
245 pctx->draw_vbo = vc4_draw_vbo;
246 pctx->clear = vc4_clear;
247 pctx->clear_render_target = vc4_clear_render_target;
248 pctx->clear_depth_stencil = vc4_clear_depth_stencil;
249 }