2 * Copyright © 2014-2017 Broadcom
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:
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
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
24 #include "util/u_pack_color.h"
25 #include "util/u_upload_mgr.h"
26 #include "util/format_srgb.h"
28 #include "v3d_context.h"
29 #include "compiler/v3d_compiler.h"
30 #include "broadcom/cle/v3d_packet_v33_pack.h"
33 get_texrect_scale(struct v3d_texture_stateobj
*texstate
,
34 enum quniform_contents contents
,
37 struct pipe_sampler_view
*texture
= texstate
->textures
[data
];
40 if (contents
== QUNIFORM_TEXRECT_SCALE_X
)
41 dim
= texture
->texture
->width0
;
43 dim
= texture
->texture
->height0
;
45 return fui(1.0f
/ dim
);
49 get_texture_size(struct v3d_texture_stateobj
*texstate
,
50 enum quniform_contents contents
,
53 struct pipe_sampler_view
*texture
= texstate
->textures
[data
];
56 case QUNIFORM_TEXTURE_WIDTH
:
57 return u_minify(texture
->texture
->width0
,
58 texture
->u
.tex
.first_level
);
59 case QUNIFORM_TEXTURE_HEIGHT
:
60 return u_minify(texture
->texture
->height0
,
61 texture
->u
.tex
.first_level
);
62 case QUNIFORM_TEXTURE_DEPTH
:
63 return u_minify(texture
->texture
->depth0
,
64 texture
->u
.tex
.first_level
);
65 case QUNIFORM_TEXTURE_ARRAY_SIZE
:
66 return texture
->texture
->array_size
;
67 case QUNIFORM_TEXTURE_LEVELS
:
68 return (texture
->u
.tex
.last_level
-
69 texture
->u
.tex
.first_level
) + 1;
71 unreachable("Bad texture size field");
76 get_image_size(struct v3d_shaderimg_stateobj
*shaderimg
,
77 enum quniform_contents contents
,
80 struct v3d_image_view
*image
= &shaderimg
->si
[data
];
83 case QUNIFORM_IMAGE_WIDTH
:
84 return u_minify(image
->base
.resource
->width0
,
85 image
->base
.u
.tex
.level
);
86 case QUNIFORM_IMAGE_HEIGHT
:
87 return u_minify(image
->base
.resource
->height0
,
88 image
->base
.u
.tex
.level
);
89 case QUNIFORM_IMAGE_DEPTH
:
90 return u_minify(image
->base
.resource
->depth0
,
91 image
->base
.u
.tex
.level
);
92 case QUNIFORM_IMAGE_ARRAY_SIZE
:
93 return image
->base
.resource
->array_size
;
95 unreachable("Bad texture size field");
100 * Writes the V3D 3.x P0 (CFG_MODE=1) texture parameter.
102 * Some bits of this field are dependent on the type of sample being done by
103 * the shader, while other bits are dependent on the sampler state. We OR the
107 write_texture_p0(struct v3d_job
*job
,
108 struct v3d_cl_out
**uniforms
,
109 struct v3d_texture_stateobj
*texstate
,
111 uint32_t shader_data
)
113 struct pipe_sampler_state
*psampler
= texstate
->samplers
[unit
];
114 struct v3d_sampler_state
*sampler
= v3d_sampler_state(psampler
);
116 cl_aligned_u32(uniforms
, shader_data
| sampler
->p0
);
119 /** Writes the V3D 3.x P1 (CFG_MODE=1) texture parameter. */
121 write_texture_p1(struct v3d_job
*job
,
122 struct v3d_cl_out
**uniforms
,
123 struct v3d_texture_stateobj
*texstate
,
126 /* Extract the texture unit from the top bits, and the compiler's
127 * packed p1 from the bottom.
129 uint32_t unit
= data
>> 5;
130 uint32_t p1
= data
& 0x1f;
132 struct pipe_sampler_view
*psview
= texstate
->textures
[unit
];
133 struct v3d_sampler_view
*sview
= v3d_sampler_view(psview
);
135 struct V3D33_TEXTURE_UNIFORM_PARAMETER_1_CFG_MODE1 unpacked
= {
136 .texture_state_record_base_address
= texstate
->texture_state
[unit
],
140 V3D33_TEXTURE_UNIFORM_PARAMETER_1_CFG_MODE1_pack(&job
->indirect
,
144 cl_aligned_u32(uniforms
, p1
| packed
| sview
->p1
);
147 /** Writes the V3D 4.x TMU configuration parameter 0. */
149 write_tmu_p0(struct v3d_job
*job
,
150 struct v3d_cl_out
**uniforms
,
151 struct v3d_texture_stateobj
*texstate
,
154 int unit
= v3d_unit_data_get_unit(data
);
155 struct pipe_sampler_view
*psview
= texstate
->textures
[unit
];
156 struct v3d_sampler_view
*sview
= v3d_sampler_view(psview
);
157 struct v3d_resource
*rsc
= v3d_resource(sview
->texture
);
159 cl_aligned_reloc(&job
->indirect
, uniforms
, sview
->bo
,
160 v3d_unit_data_get_offset(data
));
161 v3d_job_add_bo(job
, rsc
->bo
);
165 write_image_tmu_p0(struct v3d_job
*job
,
166 struct v3d_cl_out
**uniforms
,
167 struct v3d_shaderimg_stateobj
*img
,
170 /* Extract the image unit from the top bits, and the compiler's
171 * packed p0 from the bottom.
173 uint32_t unit
= data
>> 24;
174 uint32_t p0
= data
& 0x00ffffff;
176 struct v3d_image_view
*iview
= &img
->si
[unit
];
177 struct v3d_resource
*rsc
= v3d_resource(iview
->base
.resource
);
179 cl_aligned_reloc(&job
->indirect
, uniforms
,
180 v3d_resource(iview
->tex_state
)->bo
,
181 iview
->tex_state_offset
| p0
);
182 v3d_job_add_bo(job
, rsc
->bo
);
185 /** Writes the V3D 4.x TMU configuration parameter 1. */
187 write_tmu_p1(struct v3d_job
*job
,
188 struct v3d_cl_out
**uniforms
,
189 struct v3d_texture_stateobj
*texstate
,
192 uint32_t unit
= v3d_unit_data_get_unit(data
);
193 struct pipe_sampler_state
*psampler
= texstate
->samplers
[unit
];
194 struct v3d_sampler_state
*sampler
= v3d_sampler_state(psampler
);
195 struct pipe_sampler_view
*psview
= texstate
->textures
[unit
];
196 struct v3d_sampler_view
*sview
= v3d_sampler_view(psview
);
199 if (sampler
->border_color_variants
)
200 variant
= sview
->sampler_variant
;
202 cl_aligned_reloc(&job
->indirect
, uniforms
,
203 v3d_resource(sampler
->sampler_state
)->bo
,
204 sampler
->sampler_state_offset
[variant
] |
205 v3d_unit_data_get_offset(data
));
209 v3d_write_uniforms(struct v3d_context
*v3d
, struct v3d_job
*job
,
210 struct v3d_compiled_shader
*shader
,
211 enum pipe_shader_type stage
)
213 struct v3d_constbuf_stateobj
*cb
= &v3d
->constbuf
[stage
];
214 struct v3d_texture_stateobj
*texstate
= &v3d
->tex
[stage
];
215 struct v3d_uniform_list
*uinfo
= &shader
->prog_data
.base
->uniforms
;
216 const uint32_t *gallium_uniforms
= cb
->cb
[0].user_buffer
;
218 /* The hardware always pre-fetches the next uniform (also when there
219 * aren't any), so we always allocate space for an extra slot. This
220 * fixes MMU exceptions reported since Linux kernel 5.4 when the
221 * uniforms fill up the tail bytes of a page in the indirect
222 * BO. In that scenario, when the hardware pre-fetches after reading
223 * the last uniform it will read beyond the end of the page and trigger
226 v3d_cl_ensure_space(&job
->indirect
, (uinfo
->count
+ 1) * 4, 4);
228 struct v3d_cl_reloc uniform_stream
= cl_get_address(&job
->indirect
);
229 v3d_bo_reference(uniform_stream
.bo
);
231 struct v3d_cl_out
*uniforms
=
232 cl_start(&job
->indirect
);
234 for (int i
= 0; i
< uinfo
->count
; i
++) {
235 uint32_t data
= uinfo
->data
[i
];
237 switch (uinfo
->contents
[i
]) {
238 case QUNIFORM_CONSTANT
:
239 cl_aligned_u32(&uniforms
, data
);
241 case QUNIFORM_UNIFORM
:
242 cl_aligned_u32(&uniforms
, gallium_uniforms
[data
]);
244 case QUNIFORM_VIEWPORT_X_SCALE
:
245 cl_aligned_f(&uniforms
, v3d
->viewport
.scale
[0] * 256.0f
);
247 case QUNIFORM_VIEWPORT_Y_SCALE
:
248 cl_aligned_f(&uniforms
, v3d
->viewport
.scale
[1] * 256.0f
);
251 case QUNIFORM_VIEWPORT_Z_OFFSET
:
252 cl_aligned_f(&uniforms
, v3d
->viewport
.translate
[2]);
254 case QUNIFORM_VIEWPORT_Z_SCALE
:
255 cl_aligned_f(&uniforms
, v3d
->viewport
.scale
[2]);
258 case QUNIFORM_USER_CLIP_PLANE
:
259 cl_aligned_f(&uniforms
,
260 v3d
->clip
.ucp
[data
/ 4][data
% 4]);
263 case QUNIFORM_TMU_CONFIG_P0
:
264 write_tmu_p0(job
, &uniforms
, texstate
, data
);
267 case QUNIFORM_TMU_CONFIG_P1
:
268 write_tmu_p1(job
, &uniforms
, texstate
, data
);
271 case QUNIFORM_IMAGE_TMU_CONFIG_P0
:
272 write_image_tmu_p0(job
, &uniforms
,
273 &v3d
->shaderimg
[stage
], data
);
276 case QUNIFORM_TEXTURE_CONFIG_P1
:
277 write_texture_p1(job
, &uniforms
, texstate
,
281 case QUNIFORM_TEXRECT_SCALE_X
:
282 case QUNIFORM_TEXRECT_SCALE_Y
:
283 cl_aligned_u32(&uniforms
,
284 get_texrect_scale(texstate
,
289 case QUNIFORM_TEXTURE_WIDTH
:
290 case QUNIFORM_TEXTURE_HEIGHT
:
291 case QUNIFORM_TEXTURE_DEPTH
:
292 case QUNIFORM_TEXTURE_ARRAY_SIZE
:
293 case QUNIFORM_TEXTURE_LEVELS
:
294 cl_aligned_u32(&uniforms
,
295 get_texture_size(texstate
,
300 case QUNIFORM_IMAGE_WIDTH
:
301 case QUNIFORM_IMAGE_HEIGHT
:
302 case QUNIFORM_IMAGE_DEPTH
:
303 case QUNIFORM_IMAGE_ARRAY_SIZE
:
304 cl_aligned_u32(&uniforms
,
305 get_image_size(&v3d
->shaderimg
[stage
],
310 case QUNIFORM_ALPHA_REF
:
311 cl_aligned_f(&uniforms
,
312 v3d
->zsa
->base
.alpha
.ref_value
);
315 case QUNIFORM_UBO_ADDR
: {
316 uint32_t unit
= v3d_unit_data_get_unit(data
);
317 /* Constant buffer 0 may be a system memory pointer,
318 * in which case we want to upload a shadow copy to
321 if (!cb
->cb
[unit
].buffer
) {
322 u_upload_data(v3d
->uploader
, 0,
323 cb
->cb
[unit
].buffer_size
, 16,
324 cb
->cb
[unit
].user_buffer
,
325 &cb
->cb
[unit
].buffer_offset
,
326 &cb
->cb
[unit
].buffer
);
329 cl_aligned_reloc(&job
->indirect
, &uniforms
,
330 v3d_resource(cb
->cb
[unit
].buffer
)->bo
,
331 cb
->cb
[unit
].buffer_offset
+
332 v3d_unit_data_get_offset(data
));
336 case QUNIFORM_SSBO_OFFSET
: {
337 struct pipe_shader_buffer
*sb
=
338 &v3d
->ssbo
[stage
].sb
[data
];
340 cl_aligned_reloc(&job
->indirect
, &uniforms
,
341 v3d_resource(sb
->buffer
)->bo
,
346 case QUNIFORM_GET_BUFFER_SIZE
:
347 cl_aligned_u32(&uniforms
,
348 v3d
->ssbo
[stage
].sb
[data
].buffer_size
);
351 case QUNIFORM_TEXTURE_FIRST_LEVEL
:
352 cl_aligned_f(&uniforms
,
353 texstate
->textures
[data
]->u
.tex
.first_level
);
356 case QUNIFORM_SPILL_OFFSET
:
357 cl_aligned_reloc(&job
->indirect
, &uniforms
,
358 v3d
->prog
.spill_bo
, 0);
361 case QUNIFORM_SPILL_SIZE_PER_THREAD
:
362 cl_aligned_u32(&uniforms
,
363 v3d
->prog
.spill_size_per_thread
);
366 case QUNIFORM_NUM_WORK_GROUPS
:
367 cl_aligned_u32(&uniforms
,
368 v3d
->compute_num_workgroups
[data
]);
371 case QUNIFORM_SHARED_OFFSET
:
372 cl_aligned_reloc(&job
->indirect
, &uniforms
,
373 v3d
->compute_shared_memory
, 0);
377 assert(quniform_contents_is_texture_p0(uinfo
->contents
[i
]));
379 write_texture_p0(job
, &uniforms
, texstate
,
381 QUNIFORM_TEXTURE_CONFIG_P0_0
,
387 uint32_t written_val
= *((uint32_t *)uniforms
- 1);
388 fprintf(stderr
, "shader %p[%d]: 0x%08x / 0x%08x (%f) ",
389 shader
, i
, __gen_address_offset(&uniform_stream
) + i
* 4,
390 written_val
, uif(written_val
));
391 vir_dump_uniform(uinfo
->contents
[i
], data
);
392 fprintf(stderr
, "\n");
396 cl_end(&job
->indirect
, uniforms
);
398 return uniform_stream
;
402 v3d_set_shader_uniform_dirty_flags(struct v3d_compiled_shader
*shader
)
406 for (int i
= 0; i
< shader
->prog_data
.base
->uniforms
.count
; i
++) {
407 switch (shader
->prog_data
.base
->uniforms
.contents
[i
]) {
408 case QUNIFORM_CONSTANT
:
410 case QUNIFORM_UNIFORM
:
411 case QUNIFORM_UBO_ADDR
:
412 dirty
|= VC5_DIRTY_CONSTBUF
;
415 case QUNIFORM_VIEWPORT_X_SCALE
:
416 case QUNIFORM_VIEWPORT_Y_SCALE
:
417 case QUNIFORM_VIEWPORT_Z_OFFSET
:
418 case QUNIFORM_VIEWPORT_Z_SCALE
:
419 dirty
|= VC5_DIRTY_VIEWPORT
;
422 case QUNIFORM_USER_CLIP_PLANE
:
423 dirty
|= VC5_DIRTY_CLIP
;
426 case QUNIFORM_TMU_CONFIG_P0
:
427 case QUNIFORM_TMU_CONFIG_P1
:
428 case QUNIFORM_TEXTURE_CONFIG_P1
:
429 case QUNIFORM_TEXTURE_FIRST_LEVEL
:
430 case QUNIFORM_TEXRECT_SCALE_X
:
431 case QUNIFORM_TEXRECT_SCALE_Y
:
432 case QUNIFORM_TEXTURE_WIDTH
:
433 case QUNIFORM_TEXTURE_HEIGHT
:
434 case QUNIFORM_TEXTURE_DEPTH
:
435 case QUNIFORM_TEXTURE_ARRAY_SIZE
:
436 case QUNIFORM_TEXTURE_LEVELS
:
437 case QUNIFORM_SPILL_OFFSET
:
438 case QUNIFORM_SPILL_SIZE_PER_THREAD
:
439 /* We could flag this on just the stage we're
440 * compiling for, but it's not passed in.
442 dirty
|= VC5_DIRTY_FRAGTEX
| VC5_DIRTY_VERTTEX
|
443 VC5_DIRTY_GEOMTEX
| VC5_DIRTY_COMPTEX
;
446 case QUNIFORM_SSBO_OFFSET
:
447 case QUNIFORM_GET_BUFFER_SIZE
:
448 dirty
|= VC5_DIRTY_SSBO
;
451 case QUNIFORM_IMAGE_TMU_CONFIG_P0
:
452 case QUNIFORM_IMAGE_WIDTH
:
453 case QUNIFORM_IMAGE_HEIGHT
:
454 case QUNIFORM_IMAGE_DEPTH
:
455 case QUNIFORM_IMAGE_ARRAY_SIZE
:
456 dirty
|= VC5_DIRTY_SHADER_IMAGE
;
459 case QUNIFORM_ALPHA_REF
:
460 dirty
|= VC5_DIRTY_ZSA
;
463 case QUNIFORM_NUM_WORK_GROUPS
:
464 case QUNIFORM_SHARED_OFFSET
:
465 /* Compute always recalculates uniforms. */
469 assert(quniform_contents_is_texture_p0(shader
->prog_data
.base
->uniforms
.contents
[i
]));
470 dirty
|= VC5_DIRTY_FRAGTEX
| VC5_DIRTY_VERTTEX
|
471 VC5_DIRTY_GEOMTEX
| VC5_DIRTY_COMPTEX
;
476 shader
->uniform_dirty_bits
= dirty
;