1 /*
2 * Copyright © 2014-2015 Broadcom
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24 #include "util/u_pack_color.h"
25 #include "util/u_upload_mgr.h"
26 #include "util/format_srgb.h"
27
28 #include "vc4_context.h"
29 #include "vc4_qir.h"
30
31 static void
write_texture_p0(struct vc4_job * job,struct vc4_cl_out ** uniforms,struct vc4_texture_stateobj * texstate,uint32_t unit)32 write_texture_p0(struct vc4_job *job,
33 struct vc4_cl_out **uniforms,
34 struct vc4_texture_stateobj *texstate,
35 uint32_t unit)
36 {
37 struct vc4_sampler_view *sview =
38 vc4_sampler_view(texstate->textures[unit]);
39 struct vc4_resource *rsc = vc4_resource(sview->texture);
40
41 cl_reloc(job, &job->uniforms, uniforms, rsc->bo, sview->texture_p0);
42 }
43
44 static void
write_texture_p1(struct vc4_job * job,struct vc4_cl_out ** uniforms,struct vc4_texture_stateobj * texstate,uint32_t unit)45 write_texture_p1(struct vc4_job *job,
46 struct vc4_cl_out **uniforms,
47 struct vc4_texture_stateobj *texstate,
48 uint32_t unit)
49 {
50 struct vc4_sampler_view *sview =
51 vc4_sampler_view(texstate->textures[unit]);
52 struct vc4_sampler_state *sampler =
53 vc4_sampler_state(texstate->samplers[unit]);
54
55 cl_aligned_u32(uniforms, sview->texture_p1 | sampler->texture_p1);
56 }
57
58 static void
write_texture_p2(struct vc4_job * job,struct vc4_cl_out ** uniforms,struct vc4_texture_stateobj * texstate,uint32_t data)59 write_texture_p2(struct vc4_job *job,
60 struct vc4_cl_out **uniforms,
61 struct vc4_texture_stateobj *texstate,
62 uint32_t data)
63 {
64 uint32_t unit = data & 0xffff;
65 struct pipe_sampler_view *texture = texstate->textures[unit];
66 struct vc4_resource *rsc = vc4_resource(texture->texture);
67
68 cl_aligned_u32(uniforms,
69 VC4_SET_FIELD(VC4_TEX_P2_PTYPE_CUBE_MAP_STRIDE,
70 VC4_TEX_P2_PTYPE) |
71 VC4_SET_FIELD(rsc->cube_map_stride >> 12, VC4_TEX_P2_CMST) |
72 VC4_SET_FIELD((data >> 16) & 1, VC4_TEX_P2_BSLOD));
73 }
74
75 static void
write_texture_first_level(struct vc4_job * job,struct vc4_cl_out ** uniforms,struct vc4_texture_stateobj * texstate,uint32_t data)76 write_texture_first_level(struct vc4_job *job,
77 struct vc4_cl_out **uniforms,
78 struct vc4_texture_stateobj *texstate,
79 uint32_t data)
80 {
81 uint32_t unit = data & 0xffff;
82 struct pipe_sampler_view *texture = texstate->textures[unit];
83
84 cl_aligned_f(uniforms, texture->u.tex.first_level);
85 }
86
87 static void
write_texture_msaa_addr(struct vc4_job * job,struct vc4_cl_out ** uniforms,struct vc4_texture_stateobj * texstate,uint32_t unit)88 write_texture_msaa_addr(struct vc4_job *job,
89 struct vc4_cl_out **uniforms,
90 struct vc4_texture_stateobj *texstate,
91 uint32_t unit)
92 {
93 struct pipe_sampler_view *texture = texstate->textures[unit];
94 struct vc4_resource *rsc = vc4_resource(texture->texture);
95
96 cl_aligned_reloc(job, &job->uniforms, uniforms, rsc->bo, 0);
97 }
98
99
100 #define SWIZ(x,y,z,w) { \
101 PIPE_SWIZZLE_##x, \
102 PIPE_SWIZZLE_##y, \
103 PIPE_SWIZZLE_##z, \
104 PIPE_SWIZZLE_##w \
105 }
106
107 static void
write_texture_border_color(struct vc4_job * job,struct vc4_cl_out ** uniforms,struct vc4_texture_stateobj * texstate,uint32_t unit)108 write_texture_border_color(struct vc4_job *job,
109 struct vc4_cl_out **uniforms,
110 struct vc4_texture_stateobj *texstate,
111 uint32_t unit)
112 {
113 struct pipe_sampler_state *sampler = texstate->samplers[unit];
114 struct pipe_sampler_view *texture = texstate->textures[unit];
115 struct vc4_resource *rsc = vc4_resource(texture->texture);
116 union util_color uc;
117
118 const struct util_format_description *tex_format_desc =
119 util_format_description(texture->format);
120
121 float border_color[4];
122 for (int i = 0; i < 4; i++)
123 border_color[i] = sampler->border_color.f[i];
124 if (util_format_is_srgb(texture->format)) {
125 for (int i = 0; i < 3; i++)
126 border_color[i] =
127 util_format_linear_to_srgb_float(border_color[i]);
128 }
129
130 /* Turn the border color into the layout of channels that it would
131 * have when stored as texture contents.
132 */
133 float storage_color[4];
134 util_format_unswizzle_4f(storage_color,
135 border_color,
136 tex_format_desc->swizzle);
137
138 /* Now, pack so that when the vc4_format-sampled texture contents are
139 * replaced with our border color, the vc4_get_format_swizzle()
140 * swizzling will get the right channels.
141 */
142 if (util_format_is_depth_or_stencil(texture->format)) {
143 uc.ui[0] = util_pack_z(PIPE_FORMAT_Z24X8_UNORM,
144 sampler->border_color.f[0]) << 8;
145 } else {
146 switch (rsc->vc4_format) {
147 default:
148 case VC4_TEXTURE_TYPE_RGBA8888:
149 util_pack_color(storage_color,
150 PIPE_FORMAT_R8G8B8A8_UNORM, &uc);
151 break;
152 case VC4_TEXTURE_TYPE_RGBA4444:
153 case VC4_TEXTURE_TYPE_RGBA5551:
154 util_pack_color(storage_color,
155 PIPE_FORMAT_A8B8G8R8_UNORM, &uc);
156 break;
157 case VC4_TEXTURE_TYPE_RGB565:
158 util_pack_color(storage_color,
159 PIPE_FORMAT_B8G8R8A8_UNORM, &uc);
160 break;
161 case VC4_TEXTURE_TYPE_ALPHA:
162 uc.ui[0] = float_to_ubyte(storage_color[0]) << 24;
163 break;
164 case VC4_TEXTURE_TYPE_LUMALPHA:
165 uc.ui[0] = ((float_to_ubyte(storage_color[1]) << 24) |
166 (float_to_ubyte(storage_color[0]) << 0));
167 break;
168 }
169 }
170
171 cl_aligned_u32(uniforms, uc.ui[0]);
172 }
173
174 static uint32_t
get_texrect_scale(struct vc4_texture_stateobj * texstate,enum quniform_contents contents,uint32_t data)175 get_texrect_scale(struct vc4_texture_stateobj *texstate,
176 enum quniform_contents contents,
177 uint32_t data)
178 {
179 struct pipe_sampler_view *texture = texstate->textures[data];
180 uint32_t dim;
181
182 if (contents == QUNIFORM_TEXRECT_SCALE_X)
183 dim = texture->texture->width0;
184 else
185 dim = texture->texture->height0;
186
187 return fui(1.0f / dim);
188 }
189
190 void
vc4_write_uniforms(struct vc4_context * vc4,struct vc4_compiled_shader * shader,struct vc4_constbuf_stateobj * cb,struct vc4_texture_stateobj * texstate)191 vc4_write_uniforms(struct vc4_context *vc4, struct vc4_compiled_shader *shader,
192 struct vc4_constbuf_stateobj *cb,
193 struct vc4_texture_stateobj *texstate)
194 {
195 struct vc4_shader_uniform_info *uinfo = &shader->uniforms;
196 struct vc4_job *job = vc4->job;
197 const uint32_t *gallium_uniforms = cb->cb[0].user_buffer;
198
199 cl_ensure_space(&job->uniforms, (uinfo->count +
200 uinfo->num_texture_samples) * 4);
201
202 struct vc4_cl_out *uniforms =
203 cl_start_shader_reloc(&job->uniforms,
204 uinfo->num_texture_samples);
205
206 for (int i = 0; i < uinfo->count; i++) {
207 enum quniform_contents contents = uinfo->contents[i];
208 uint32_t data = uinfo->data[i];
209
210 switch (contents) {
211 case QUNIFORM_CONSTANT:
212 cl_aligned_u32(&uniforms, data);
213 break;
214 case QUNIFORM_UNIFORM:
215 cl_aligned_u32(&uniforms,
216 gallium_uniforms[data]);
217 break;
218 case QUNIFORM_VIEWPORT_X_SCALE:
219 cl_aligned_f(&uniforms, vc4->viewport.scale[0] * 16.0f);
220 break;
221 case QUNIFORM_VIEWPORT_Y_SCALE:
222 cl_aligned_f(&uniforms, vc4->viewport.scale[1] * 16.0f);
223 break;
224
225 case QUNIFORM_VIEWPORT_Z_OFFSET:
226 cl_aligned_f(&uniforms, vc4->viewport.translate[2]);
227 break;
228 case QUNIFORM_VIEWPORT_Z_SCALE:
229 cl_aligned_f(&uniforms, vc4->viewport.scale[2]);
230 break;
231
232 case QUNIFORM_USER_CLIP_PLANE:
233 cl_aligned_f(&uniforms,
234 vc4->clip.ucp[data / 4][data % 4]);
235 break;
236
237 case QUNIFORM_TEXTURE_CONFIG_P0:
238 write_texture_p0(job, &uniforms, texstate, data);
239 break;
240
241 case QUNIFORM_TEXTURE_CONFIG_P1:
242 write_texture_p1(job, &uniforms, texstate, data);
243 break;
244
245 case QUNIFORM_TEXTURE_CONFIG_P2:
246 write_texture_p2(job, &uniforms, texstate, data);
247 break;
248
249 case QUNIFORM_TEXTURE_FIRST_LEVEL:
250 write_texture_first_level(job, &uniforms, texstate,
251 data);
252 break;
253
254 case QUNIFORM_UBO0_ADDR:
255 /* Constant buffer 0 may be a system memory pointer,
256 * in which case we want to upload a shadow copy to
257 * the GPU.
258 */
259 if (!cb->cb[0].buffer) {
260 u_upload_data(vc4->uploader, 0,
261 cb->cb[0].buffer_size, 16,
262 cb->cb[0].user_buffer,
263 &cb->cb[0].buffer_offset,
264 &cb->cb[0].buffer);
265 }
266
267 cl_aligned_reloc(job, &job->uniforms,
268 &uniforms,
269 vc4_resource(cb->cb[0].buffer)->bo,
270 cb->cb[0].buffer_offset +
271 data);
272 break;
273
274 case QUNIFORM_UBO1_ADDR: {
275 struct vc4_resource *rsc =
276 vc4_resource(cb->cb[1].buffer);
277
278 cl_aligned_reloc(job, &job->uniforms,
279 &uniforms,
280 rsc->bo, cb->cb[1].buffer_offset);
281 break;
282 }
283
284 case QUNIFORM_TEXTURE_MSAA_ADDR:
285 write_texture_msaa_addr(job, &uniforms, texstate, data);
286 break;
287
288 case QUNIFORM_TEXTURE_BORDER_COLOR:
289 write_texture_border_color(job, &uniforms,
290 texstate, data);
291 break;
292
293 case QUNIFORM_TEXRECT_SCALE_X:
294 case QUNIFORM_TEXRECT_SCALE_Y:
295 cl_aligned_u32(&uniforms,
296 get_texrect_scale(texstate,
297 uinfo->contents[i],
298 data));
299 break;
300
301 case QUNIFORM_BLEND_CONST_COLOR_X:
302 case QUNIFORM_BLEND_CONST_COLOR_Y:
303 case QUNIFORM_BLEND_CONST_COLOR_Z:
304 case QUNIFORM_BLEND_CONST_COLOR_W:
305 cl_aligned_f(&uniforms,
306 CLAMP(vc4->blend_color.f.color[uinfo->contents[i] -
307 QUNIFORM_BLEND_CONST_COLOR_X],
308 0, 1));
309 break;
310
311 case QUNIFORM_BLEND_CONST_COLOR_RGBA: {
312 const uint8_t *format_swiz =
313 vc4_get_format_swizzle(vc4->framebuffer.cbufs[0]->format);
314 uint32_t color = 0;
315 for (int i = 0; i < 4; i++) {
316 if (format_swiz[i] >= 4)
317 continue;
318
319 color |= (vc4->blend_color.ub[format_swiz[i]] <<
320 (i * 8));
321 }
322 cl_aligned_u32(&uniforms, color);
323 break;
324 }
325
326 case QUNIFORM_BLEND_CONST_COLOR_AAAA: {
327 uint8_t a = vc4->blend_color.ub[3];
328 cl_aligned_u32(&uniforms, ((a) |
329 (a << 8) |
330 (a << 16) |
331 (a << 24)));
332 break;
333 }
334
335 case QUNIFORM_STENCIL:
336 cl_aligned_u32(&uniforms,
337 vc4->zsa->stencil_uniforms[data] |
338 (data <= 1 ?
339 (vc4->stencil_ref.ref_value[data] << 8) :
340 0));
341 break;
342
343 case QUNIFORM_SAMPLE_MASK:
344 cl_aligned_u32(&uniforms, vc4->sample_mask);
345 break;
346
347 case QUNIFORM_UNIFORMS_ADDRESS:
348 /* This will be filled in by the kernel. */
349 cl_aligned_u32(&uniforms, 0xd0d0d0d0);
350 break;
351 }
352
353 if (false) {
354 uint32_t written_val = *((uint32_t *)uniforms - 1);
355 char *desc = qir_describe_uniform(uinfo->contents[i],
356 uinfo->data[i],
357 gallium_uniforms);
358
359 fprintf(stderr, "%p/%d: 0x%08x %s\n",
360 shader, i, written_val, desc);
361
362 ralloc_free(desc);
363 }
364 }
365
366 cl_end(&job->uniforms, uniforms);
367 }
368
369 void
vc4_set_shader_uniform_dirty_flags(struct vc4_compiled_shader * shader)370 vc4_set_shader_uniform_dirty_flags(struct vc4_compiled_shader *shader)
371 {
372 uint32_t dirty = 0;
373
374 for (int i = 0; i < shader->uniforms.count; i++) {
375 switch (shader->uniforms.contents[i]) {
376 case QUNIFORM_CONSTANT:
377 case QUNIFORM_UNIFORMS_ADDRESS:
378 break;
379 case QUNIFORM_UNIFORM:
380 case QUNIFORM_UBO0_ADDR:
381 case QUNIFORM_UBO1_ADDR:
382 dirty |= VC4_DIRTY_CONSTBUF;
383 break;
384
385 case QUNIFORM_VIEWPORT_X_SCALE:
386 case QUNIFORM_VIEWPORT_Y_SCALE:
387 case QUNIFORM_VIEWPORT_Z_OFFSET:
388 case QUNIFORM_VIEWPORT_Z_SCALE:
389 dirty |= VC4_DIRTY_VIEWPORT;
390 break;
391
392 case QUNIFORM_USER_CLIP_PLANE:
393 dirty |= VC4_DIRTY_CLIP;
394 break;
395
396 case QUNIFORM_TEXTURE_CONFIG_P0:
397 case QUNIFORM_TEXTURE_CONFIG_P1:
398 case QUNIFORM_TEXTURE_CONFIG_P2:
399 case QUNIFORM_TEXTURE_BORDER_COLOR:
400 case QUNIFORM_TEXTURE_FIRST_LEVEL:
401 case QUNIFORM_TEXTURE_MSAA_ADDR:
402 case QUNIFORM_TEXRECT_SCALE_X:
403 case QUNIFORM_TEXRECT_SCALE_Y:
404 /* We could flag this on just the stage we're
405 * compiling for, but it's not passed in.
406 */
407 dirty |= VC4_DIRTY_FRAGTEX | VC4_DIRTY_VERTTEX;
408 break;
409
410 case QUNIFORM_BLEND_CONST_COLOR_X:
411 case QUNIFORM_BLEND_CONST_COLOR_Y:
412 case QUNIFORM_BLEND_CONST_COLOR_Z:
413 case QUNIFORM_BLEND_CONST_COLOR_W:
414 case QUNIFORM_BLEND_CONST_COLOR_RGBA:
415 case QUNIFORM_BLEND_CONST_COLOR_AAAA:
416 dirty |= VC4_DIRTY_BLEND_COLOR;
417 break;
418
419 case QUNIFORM_STENCIL:
420 dirty |= VC4_DIRTY_ZSA;
421 break;
422
423 case QUNIFORM_SAMPLE_MASK:
424 dirty |= VC4_DIRTY_SAMPLE_MASK;
425 break;
426 }
427 }
428
429 shader->uniform_dirty_bits = dirty;
430 }
431