• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 Rob Clark <robclark@freedesktop.org>
3  * Copyright © 2018 Google, Inc.
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 FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24 
25 #include "fd6_const.h"
26 #include "fd6_pack.h"
27 
28 #define emit_const_user fd6_emit_const_user
29 #define emit_const_bo fd6_emit_const_bo
30 #include "ir3_const.h"
31 
32 /* regid:          base const register
33  * prsc or dwords: buffer containing constant values
34  * sizedwords:     size of const value buffer
35  */
36 void
fd6_emit_const_user(struct fd_ringbuffer * ring,const struct ir3_shader_variant * v,uint32_t regid,uint32_t sizedwords,const uint32_t * dwords)37 fd6_emit_const_user(struct fd_ringbuffer *ring,
38 		const struct ir3_shader_variant *v, uint32_t regid,
39 		uint32_t sizedwords, const uint32_t *dwords)
40 {
41 	emit_const_asserts(ring, v, regid, sizedwords);
42 
43 	/* NOTE we cheat a bit here, since we know mesa is aligning
44 	 * the size of the user buffer to 16 bytes.  And we want to
45 	 * cut cycles in a hot path.
46 	 */
47 	uint32_t align_sz = align(sizedwords, 4);
48 
49 	if (fd6_geom_stage(v->type)) {
50 		OUT_PKTBUF(ring, CP_LOAD_STATE6_GEOM, dwords, align_sz,
51 				CP_LOAD_STATE6_0(
52 					.dst_off     = regid/4,
53 					.state_type  = ST6_CONSTANTS,
54 					.state_src   = SS6_DIRECT,
55 					.state_block = fd6_stage2shadersb(v->type),
56 					.num_unit    = DIV_ROUND_UP(sizedwords, 4)
57 					),
58 				CP_LOAD_STATE6_1(),
59 				CP_LOAD_STATE6_2()
60 			);
61 	} else {
62 		OUT_PKTBUF(ring, CP_LOAD_STATE6_FRAG, dwords, align_sz,
63 				CP_LOAD_STATE6_0(
64 					.dst_off     = regid/4,
65 					.state_type  = ST6_CONSTANTS,
66 					.state_src   = SS6_DIRECT,
67 					.state_block = fd6_stage2shadersb(v->type),
68 					.num_unit    = DIV_ROUND_UP(sizedwords, 4)
69 					),
70 				CP_LOAD_STATE6_1(),
71 				CP_LOAD_STATE6_2()
72 			);
73 	}
74 }
75 void
fd6_emit_const_bo(struct fd_ringbuffer * ring,const struct ir3_shader_variant * v,uint32_t regid,uint32_t offset,uint32_t sizedwords,struct fd_bo * bo)76 fd6_emit_const_bo(struct fd_ringbuffer *ring,
77 		const struct ir3_shader_variant *v, uint32_t regid,
78 		uint32_t offset, uint32_t sizedwords, struct fd_bo *bo)
79 {
80 	uint32_t dst_off = regid / 4;
81 	assert(dst_off % 4 == 0);
82 	uint32_t num_unit = DIV_ROUND_UP(sizedwords, 4);
83 	assert(num_unit % 4 == 0);
84 
85 	emit_const_asserts(ring, v, regid, sizedwords);
86 
87 	if (fd6_geom_stage(v->type)) {
88 		OUT_PKT(ring, CP_LOAD_STATE6_GEOM,
89 				CP_LOAD_STATE6_0(
90 					.dst_off     = dst_off,
91 					.state_type  = ST6_CONSTANTS,
92 					.state_src   = SS6_INDIRECT,
93 					.state_block = fd6_stage2shadersb(v->type),
94 					.num_unit    = num_unit,
95 					),
96 				CP_LOAD_STATE6_EXT_SRC_ADDR(
97 					.bo          = bo,
98 					.bo_offset   = offset
99 					)
100 			);
101 	} else {
102 		OUT_PKT(ring, CP_LOAD_STATE6_FRAG,
103 				CP_LOAD_STATE6_0(
104 					.dst_off     = dst_off,
105 					.state_type  = ST6_CONSTANTS,
106 					.state_src   = SS6_INDIRECT,
107 					.state_block = fd6_stage2shadersb(v->type),
108 					.num_unit    = num_unit,
109 					),
110 				CP_LOAD_STATE6_EXT_SRC_ADDR(
111 					.bo          = bo,
112 					.bo_offset   = offset
113 					)
114 			);
115 	}
116 }
117 
118 static bool
is_stateobj(struct fd_ringbuffer * ring)119 is_stateobj(struct fd_ringbuffer *ring)
120 {
121 	return true;
122 }
123 
124 static void
emit_const_ptrs(struct fd_ringbuffer * ring,const struct ir3_shader_variant * v,uint32_t dst_offset,uint32_t num,struct pipe_resource ** prscs,uint32_t * offsets)125 emit_const_ptrs(struct fd_ringbuffer *ring,
126 		const struct ir3_shader_variant *v, uint32_t dst_offset,
127 		uint32_t num, struct pipe_resource **prscs, uint32_t *offsets)
128 {
129 	unreachable("shouldn't be called on a6xx");
130 }
131 
132 static void
emit_tess_bos(struct fd_ringbuffer * ring,struct fd6_emit * emit,struct ir3_shader_variant * s)133 emit_tess_bos(struct fd_ringbuffer *ring, struct fd6_emit *emit, struct ir3_shader_variant *s)
134 {
135 	struct fd_context *ctx = emit->ctx;
136 	const struct ir3_const_state *const_state = ir3_const_state(s);
137 	const unsigned regid = const_state->offsets.primitive_param * 4 + 4;
138 	uint32_t dwords = 16;
139 
140 	OUT_PKT7(ring, fd6_stage2opcode(s->type), 3);
141 	OUT_RING(ring, CP_LOAD_STATE6_0_DST_OFF(regid / 4) |
142 			CP_LOAD_STATE6_0_STATE_TYPE(ST6_CONSTANTS)|
143 			CP_LOAD_STATE6_0_STATE_SRC(SS6_INDIRECT) |
144 			CP_LOAD_STATE6_0_STATE_BLOCK(fd6_stage2shadersb(s->type)) |
145 			CP_LOAD_STATE6_0_NUM_UNIT(dwords / 4));
146 	OUT_RB(ring, ctx->batch->tess_addrs_constobj);
147 }
148 
149 static void
emit_stage_tess_consts(struct fd_ringbuffer * ring,struct ir3_shader_variant * v,uint32_t * params,int num_params)150 emit_stage_tess_consts(struct fd_ringbuffer *ring, struct ir3_shader_variant *v,
151 		uint32_t *params, int num_params)
152 {
153 	const struct ir3_const_state *const_state = ir3_const_state(v);
154 	const unsigned regid = const_state->offsets.primitive_param;
155 	int size = MIN2(1 + regid, v->constlen) - regid;
156 	if (size > 0)
157 		fd6_emit_const_user(ring, v, regid * 4, num_params, params);
158 }
159 
160 static void
emit_tess_consts(struct fd6_emit * emit)161 emit_tess_consts(struct fd6_emit *emit)
162 {
163 	struct fd_context *ctx = emit->ctx;
164 
165 	struct fd_ringbuffer *constobj = fd_submit_new_ringbuffer(
166 		ctx->batch->submit, 0x1000, FD_RINGBUFFER_STREAMING);
167 
168 	/* VS sizes are in bytes since that's what STLW/LDLW use, while the HS
169 	 * size is dwords, since that's what LDG/STG use.
170 	 */
171 	unsigned num_vertices =
172 		emit->hs ?
173 		emit->info->vertices_per_patch :
174 		emit->gs->shader->nir->info.gs.vertices_in;
175 
176 	uint32_t vs_params[4] = {
177 		emit->vs->output_size * num_vertices * 4,	/* vs primitive stride */
178 		emit->vs->output_size * 4,					/* vs vertex stride */
179 		0,
180 		0
181 	};
182 
183 	emit_stage_tess_consts(constobj, emit->vs, vs_params, ARRAY_SIZE(vs_params));
184 
185 	if (emit->hs) {
186 		uint32_t hs_params[4] = {
187 			emit->vs->output_size * num_vertices * 4,	/* vs primitive stride */
188 			emit->vs->output_size * 4,					/* vs vertex stride */
189 			emit->hs->output_size,
190 			emit->info->vertices_per_patch
191 		};
192 
193 		emit_stage_tess_consts(constobj, emit->hs, hs_params, ARRAY_SIZE(hs_params));
194 		emit_tess_bos(constobj, emit, emit->hs);
195 
196 		if (emit->gs)
197 			num_vertices = emit->gs->shader->nir->info.gs.vertices_in;
198 
199 		uint32_t ds_params[4] = {
200 			emit->ds->output_size * num_vertices * 4,	/* ds primitive stride */
201 			emit->ds->output_size * 4,					/* ds vertex stride */
202 			emit->hs->output_size,                      /* hs vertex stride (dwords) */
203 			emit->hs->shader->nir->info.tess.tcs_vertices_out
204 		};
205 
206 		emit_stage_tess_consts(constobj, emit->ds, ds_params, ARRAY_SIZE(ds_params));
207 		emit_tess_bos(constobj, emit, emit->ds);
208 	}
209 
210 	if (emit->gs) {
211 		struct ir3_shader_variant *prev;
212 		if (emit->ds)
213 			prev = emit->ds;
214 		else
215 			prev = emit->vs;
216 
217 		uint32_t gs_params[4] = {
218 			prev->output_size * num_vertices * 4,	/* ds primitive stride */
219 			prev->output_size * 4,					/* ds vertex stride */
220 			0,
221 			0,
222 		};
223 
224 		num_vertices = emit->gs->shader->nir->info.gs.vertices_in;
225 		emit_stage_tess_consts(constobj, emit->gs, gs_params, ARRAY_SIZE(gs_params));
226 	}
227 
228 	fd6_emit_take_group(emit, constobj, FD6_GROUP_PRIMITIVE_PARAMS, ENABLE_ALL);
229 }
230 
231 static void
fd6_emit_ubos(struct fd_context * ctx,const struct ir3_shader_variant * v,struct fd_ringbuffer * ring,struct fd_constbuf_stateobj * constbuf)232 fd6_emit_ubos(struct fd_context *ctx, const struct ir3_shader_variant *v,
233 		struct fd_ringbuffer *ring, struct fd_constbuf_stateobj *constbuf)
234 {
235 	const struct ir3_const_state *const_state = ir3_const_state(v);
236 	int num_ubos = const_state->num_ubos;
237 
238 	if (!num_ubos)
239 		return;
240 
241 	OUT_PKT7(ring, fd6_stage2opcode(v->type), 3 + (2 * num_ubos));
242 	OUT_RING(ring, CP_LOAD_STATE6_0_DST_OFF(0) |
243 			CP_LOAD_STATE6_0_STATE_TYPE(ST6_UBO)|
244 			CP_LOAD_STATE6_0_STATE_SRC(SS6_DIRECT) |
245 			CP_LOAD_STATE6_0_STATE_BLOCK(fd6_stage2shadersb(v->type)) |
246 			CP_LOAD_STATE6_0_NUM_UNIT(num_ubos));
247 	OUT_RING(ring, CP_LOAD_STATE6_1_EXT_SRC_ADDR(0));
248 	OUT_RING(ring, CP_LOAD_STATE6_2_EXT_SRC_ADDR_HI(0));
249 
250 	for (int i = 0; i < num_ubos; i++) {
251 		struct pipe_constant_buffer *cb = &constbuf->cb[i];
252 
253 		/* If we have user pointers (constbuf 0, aka GL uniforms), upload them
254 		 * to a buffer now, and save it in the constbuf so that we don't have
255 		 * to reupload until they get changed.
256 		 */
257 		if (cb->user_buffer) {
258 			struct pipe_context *pctx = &ctx->base;
259 			u_upload_data(pctx->stream_uploader, 0,
260 					cb->buffer_size,
261 					64,
262 					cb->user_buffer,
263 					&cb->buffer_offset, &cb->buffer);
264 			cb->user_buffer = NULL;
265 		}
266 
267 		if (cb->buffer) {
268 			int size_vec4s = DIV_ROUND_UP(cb->buffer_size, 16);
269 			OUT_RELOC(ring, fd_resource(cb->buffer)->bo,
270 					cb->buffer_offset,
271 					(uint64_t)A6XX_UBO_1_SIZE(size_vec4s) << 32,
272 					0);
273 		} else {
274 			OUT_RING(ring, 0xbad00000 | (i << 16));
275 			OUT_RING(ring, A6XX_UBO_1_SIZE(0));
276 		}
277 	}
278 }
279 
280 static unsigned
user_consts_cmdstream_size(struct ir3_shader_variant * v)281 user_consts_cmdstream_size(struct ir3_shader_variant *v)
282 {
283 	struct ir3_const_state *const_state = ir3_const_state(v);
284 	struct ir3_ubo_analysis_state *ubo_state = &const_state->ubo_state;
285 
286 	if (unlikely(!ubo_state->cmdstream_size)) {
287 		unsigned packets, size;
288 
289 		/* pre-calculate size required for userconst stateobj: */
290 		ir3_user_consts_size(ubo_state, &packets, &size);
291 
292 		/* also account for UBO addresses: */
293 		packets += 1;
294 		size += 2 * const_state->num_ubos;
295 
296 		unsigned sizedwords = (4 * packets) + size;
297 		ubo_state->cmdstream_size = sizedwords * 4;
298 	}
299 
300 	return ubo_state->cmdstream_size;
301 }
302 
303 static void
emit_user_consts(struct fd6_emit * emit)304 emit_user_consts(struct fd6_emit *emit)
305 {
306 	static const enum pipe_shader_type types[] = {
307 			PIPE_SHADER_VERTEX, PIPE_SHADER_TESS_CTRL, PIPE_SHADER_TESS_EVAL,
308 			PIPE_SHADER_GEOMETRY, PIPE_SHADER_FRAGMENT,
309 	};
310 	struct ir3_shader_variant *variants[] = {
311 			emit->vs, emit->hs, emit->ds, emit->gs, emit->fs,
312 	};
313 	struct fd_context *ctx = emit->ctx;
314 	unsigned sz = 0;
315 
316 	for (unsigned i = 0; i < ARRAY_SIZE(types); i++) {
317 		if (!variants[i])
318 			continue;
319 		sz += user_consts_cmdstream_size(variants[i]);
320 	}
321 
322 	struct fd_ringbuffer *constobj = fd_submit_new_ringbuffer(
323 			ctx->batch->submit, sz, FD_RINGBUFFER_STREAMING);
324 
325 	for (unsigned i = 0; i < ARRAY_SIZE(types); i++) {
326 		if (!variants[i])
327 			continue;
328 		ir3_emit_user_consts(ctx->screen, variants[i], constobj, &ctx->constbuf[types[i]]);
329 		fd6_emit_ubos(ctx, variants[i], constobj, &ctx->constbuf[types[i]]);
330 	}
331 
332 	fd6_emit_take_group(emit, constobj, FD6_GROUP_CONST, ENABLE_ALL);
333 }
334 
335 void
fd6_emit_consts(struct fd6_emit * emit)336 fd6_emit_consts(struct fd6_emit *emit)
337 {
338 	struct fd_context *ctx = emit->ctx;
339 	struct fd6_context *fd6_ctx = fd6_context(ctx);
340 
341 	if (emit->dirty & (FD_DIRTY_CONST | FD_DIRTY_PROG))
342 		emit_user_consts(emit);
343 
344 	if (emit->key.key.has_gs || emit->key.key.tessellation)
345 		emit_tess_consts(emit);
346 
347 	/* if driver-params are needed, emit each time: */
348 	const struct ir3_shader_variant *vs = emit->vs;
349 	if (ir3_needs_vs_driver_params(vs)) {
350 		struct fd_ringbuffer *dpconstobj = fd_submit_new_ringbuffer(
351 				ctx->batch->submit, IR3_DP_VS_COUNT * 4, FD_RINGBUFFER_STREAMING);
352 		ir3_emit_vs_driver_params(vs, dpconstobj, ctx, emit->info);
353 		fd6_emit_take_group(emit, dpconstobj, FD6_GROUP_VS_DRIVER_PARAMS, ENABLE_ALL);
354 		fd6_ctx->has_dp_state = true;
355 	} else if (fd6_ctx->has_dp_state) {
356 		fd6_emit_take_group(emit, NULL, FD6_GROUP_VS_DRIVER_PARAMS, ENABLE_ALL);
357 		fd6_ctx->has_dp_state = false;
358 	}
359 }
360 
361 void
fd6_emit_ibo_consts(struct fd6_emit * emit,const struct ir3_shader_variant * v,enum pipe_shader_type stage,struct fd_ringbuffer * ring)362 fd6_emit_ibo_consts(struct fd6_emit *emit, const struct ir3_shader_variant *v,
363 		enum pipe_shader_type stage, struct fd_ringbuffer *ring)
364 {
365 	struct fd_context *ctx = emit->ctx;
366 
367 	ir3_emit_ssbo_sizes(ctx->screen, v, ring, &ctx->shaderbuf[stage]);
368 	ir3_emit_image_dims(ctx->screen, v, ring, &ctx->shaderimg[stage]);
369 }
370 
371 void
fd6_emit_cs_consts(const struct ir3_shader_variant * v,struct fd_ringbuffer * ring,struct fd_context * ctx,const struct pipe_grid_info * info)372 fd6_emit_cs_consts(const struct ir3_shader_variant *v, struct fd_ringbuffer *ring,
373 		struct fd_context *ctx, const struct pipe_grid_info *info)
374 {
375 	ir3_emit_cs_consts(v, ring, ctx, info);
376 	fd6_emit_ubos(ctx, v, ring, &ctx->constbuf[PIPE_SHADER_COMPUTE]);
377 }
378 
379 void
fd6_emit_immediates(struct fd_screen * screen,const struct ir3_shader_variant * v,struct fd_ringbuffer * ring)380 fd6_emit_immediates(struct fd_screen *screen, const struct ir3_shader_variant *v,
381 		struct fd_ringbuffer *ring)
382 {
383 	ir3_emit_immediates(screen, v, ring);
384 }
385 
386 void
fd6_emit_link_map(struct fd_screen * screen,const struct ir3_shader_variant * producer,const struct ir3_shader_variant * v,struct fd_ringbuffer * ring)387 fd6_emit_link_map(struct fd_screen *screen,
388 		const struct ir3_shader_variant *producer,
389 		const struct ir3_shader_variant *v, struct fd_ringbuffer *ring)
390 {
391 	ir3_emit_link_map(screen, producer, v, ring);
392 }
393