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_compiled_shader
*shader
,
210 enum pipe_shader_type stage
)
212 struct v3d_constbuf_stateobj
*cb
= &v3d
->constbuf
[stage
];
213 struct v3d_texture_stateobj
*texstate
= &v3d
->tex
[stage
];
214 struct v3d_uniform_list
*uinfo
= &shader
->prog_data
.base
->uniforms
;
215 struct v3d_job
*job
= v3d
->job
;
216 const uint32_t *gallium_uniforms
= cb
->cb
[0].user_buffer
;
218 /* We always need to return some space for uniforms, because the HW
219 * will be prefetching, even if we don't read any in the program.
221 v3d_cl_ensure_space(&job
->indirect
, MAX2(uinfo
->count
, 1) * 4, 4);
223 struct v3d_cl_reloc uniform_stream
= cl_get_address(&job
->indirect
);
224 v3d_bo_reference(uniform_stream
.bo
);
226 struct v3d_cl_out
*uniforms
=
227 cl_start(&job
->indirect
);
229 for (int i
= 0; i
< uinfo
->count
; i
++) {
230 uint32_t data
= uinfo
->data
[i
];
232 switch (uinfo
->contents
[i
]) {
233 case QUNIFORM_CONSTANT
:
234 cl_aligned_u32(&uniforms
, data
);
236 case QUNIFORM_UNIFORM
:
237 cl_aligned_u32(&uniforms
, gallium_uniforms
[data
]);
239 case QUNIFORM_VIEWPORT_X_SCALE
:
240 cl_aligned_f(&uniforms
, v3d
->viewport
.scale
[0] * 256.0f
);
242 case QUNIFORM_VIEWPORT_Y_SCALE
:
243 cl_aligned_f(&uniforms
, v3d
->viewport
.scale
[1] * 256.0f
);
246 case QUNIFORM_VIEWPORT_Z_OFFSET
:
247 cl_aligned_f(&uniforms
, v3d
->viewport
.translate
[2]);
249 case QUNIFORM_VIEWPORT_Z_SCALE
:
250 cl_aligned_f(&uniforms
, v3d
->viewport
.scale
[2]);
253 case QUNIFORM_USER_CLIP_PLANE
:
254 cl_aligned_f(&uniforms
,
255 v3d
->clip
.ucp
[data
/ 4][data
% 4]);
258 case QUNIFORM_TMU_CONFIG_P0
:
259 write_tmu_p0(job
, &uniforms
, texstate
, data
);
262 case QUNIFORM_TMU_CONFIG_P1
:
263 write_tmu_p1(job
, &uniforms
, texstate
, data
);
266 case QUNIFORM_IMAGE_TMU_CONFIG_P0
:
267 write_image_tmu_p0(job
, &uniforms
,
268 &v3d
->shaderimg
[stage
], data
);
271 case QUNIFORM_TEXTURE_CONFIG_P1
:
272 write_texture_p1(job
, &uniforms
, texstate
,
276 case QUNIFORM_TEXRECT_SCALE_X
:
277 case QUNIFORM_TEXRECT_SCALE_Y
:
278 cl_aligned_u32(&uniforms
,
279 get_texrect_scale(texstate
,
284 case QUNIFORM_TEXTURE_WIDTH
:
285 case QUNIFORM_TEXTURE_HEIGHT
:
286 case QUNIFORM_TEXTURE_DEPTH
:
287 case QUNIFORM_TEXTURE_ARRAY_SIZE
:
288 case QUNIFORM_TEXTURE_LEVELS
:
289 cl_aligned_u32(&uniforms
,
290 get_texture_size(texstate
,
295 case QUNIFORM_IMAGE_WIDTH
:
296 case QUNIFORM_IMAGE_HEIGHT
:
297 case QUNIFORM_IMAGE_DEPTH
:
298 case QUNIFORM_IMAGE_ARRAY_SIZE
:
299 cl_aligned_u32(&uniforms
,
300 get_image_size(&v3d
->shaderimg
[stage
],
305 case QUNIFORM_ALPHA_REF
:
306 cl_aligned_f(&uniforms
,
307 v3d
->zsa
->base
.alpha
.ref_value
);
310 case QUNIFORM_UBO_ADDR
: {
311 uint32_t unit
= v3d_unit_data_get_unit(data
);
312 /* Constant buffer 0 may be a system memory pointer,
313 * in which case we want to upload a shadow copy to
316 if (!cb
->cb
[unit
].buffer
) {
317 u_upload_data(v3d
->uploader
, 0,
318 cb
->cb
[unit
].buffer_size
, 16,
319 cb
->cb
[unit
].user_buffer
,
320 &cb
->cb
[unit
].buffer_offset
,
321 &cb
->cb
[unit
].buffer
);
324 cl_aligned_reloc(&job
->indirect
, &uniforms
,
325 v3d_resource(cb
->cb
[unit
].buffer
)->bo
,
326 cb
->cb
[unit
].buffer_offset
+
327 v3d_unit_data_get_offset(data
));
331 case QUNIFORM_SSBO_OFFSET
: {
332 struct pipe_shader_buffer
*sb
=
333 &v3d
->ssbo
[stage
].sb
[data
];
335 cl_aligned_reloc(&job
->indirect
, &uniforms
,
336 v3d_resource(sb
->buffer
)->bo
,
341 case QUNIFORM_GET_BUFFER_SIZE
:
342 cl_aligned_u32(&uniforms
,
343 v3d
->ssbo
[stage
].sb
[data
].buffer_size
);
346 case QUNIFORM_TEXTURE_FIRST_LEVEL
:
347 cl_aligned_f(&uniforms
,
348 texstate
->textures
[data
]->u
.tex
.first_level
);
351 case QUNIFORM_SPILL_OFFSET
:
352 cl_aligned_reloc(&job
->indirect
, &uniforms
,
353 v3d
->prog
.spill_bo
, 0);
356 case QUNIFORM_SPILL_SIZE_PER_THREAD
:
357 cl_aligned_u32(&uniforms
,
358 v3d
->prog
.spill_size_per_thread
);
362 assert(quniform_contents_is_texture_p0(uinfo
->contents
[i
]));
364 write_texture_p0(job
, &uniforms
, texstate
,
366 QUNIFORM_TEXTURE_CONFIG_P0_0
,
372 uint32_t written_val
= *((uint32_t *)uniforms
- 1);
373 fprintf(stderr
, "shader %p[%d]: 0x%08x / 0x%08x (%f) ",
374 shader
, i
, __gen_address_offset(&uniform_stream
) + i
* 4,
375 written_val
, uif(written_val
));
376 vir_dump_uniform(uinfo
->contents
[i
], data
);
377 fprintf(stderr
, "\n");
381 cl_end(&job
->indirect
, uniforms
);
383 return uniform_stream
;
387 v3d_set_shader_uniform_dirty_flags(struct v3d_compiled_shader
*shader
)
391 for (int i
= 0; i
< shader
->prog_data
.base
->uniforms
.count
; i
++) {
392 switch (shader
->prog_data
.base
->uniforms
.contents
[i
]) {
393 case QUNIFORM_CONSTANT
:
395 case QUNIFORM_UNIFORM
:
396 case QUNIFORM_UBO_ADDR
:
397 dirty
|= VC5_DIRTY_CONSTBUF
;
400 case QUNIFORM_VIEWPORT_X_SCALE
:
401 case QUNIFORM_VIEWPORT_Y_SCALE
:
402 case QUNIFORM_VIEWPORT_Z_OFFSET
:
403 case QUNIFORM_VIEWPORT_Z_SCALE
:
404 dirty
|= VC5_DIRTY_VIEWPORT
;
407 case QUNIFORM_USER_CLIP_PLANE
:
408 dirty
|= VC5_DIRTY_CLIP
;
411 case QUNIFORM_TMU_CONFIG_P0
:
412 case QUNIFORM_TMU_CONFIG_P1
:
413 case QUNIFORM_TEXTURE_CONFIG_P1
:
414 case QUNIFORM_TEXTURE_FIRST_LEVEL
:
415 case QUNIFORM_TEXRECT_SCALE_X
:
416 case QUNIFORM_TEXRECT_SCALE_Y
:
417 case QUNIFORM_TEXTURE_WIDTH
:
418 case QUNIFORM_TEXTURE_HEIGHT
:
419 case QUNIFORM_TEXTURE_DEPTH
:
420 case QUNIFORM_TEXTURE_ARRAY_SIZE
:
421 case QUNIFORM_TEXTURE_LEVELS
:
422 case QUNIFORM_SPILL_OFFSET
:
423 case QUNIFORM_SPILL_SIZE_PER_THREAD
:
424 /* We could flag this on just the stage we're
425 * compiling for, but it's not passed in.
427 dirty
|= VC5_DIRTY_FRAGTEX
| VC5_DIRTY_VERTTEX
;
430 case QUNIFORM_SSBO_OFFSET
:
431 case QUNIFORM_GET_BUFFER_SIZE
:
432 dirty
|= VC5_DIRTY_SSBO
;
435 case QUNIFORM_IMAGE_TMU_CONFIG_P0
:
436 case QUNIFORM_IMAGE_WIDTH
:
437 case QUNIFORM_IMAGE_HEIGHT
:
438 case QUNIFORM_IMAGE_DEPTH
:
439 case QUNIFORM_IMAGE_ARRAY_SIZE
:
440 dirty
|= VC5_DIRTY_SHADER_IMAGE
;
443 case QUNIFORM_ALPHA_REF
:
444 dirty
|= VC5_DIRTY_ZSA
;
448 assert(quniform_contents_is_texture_p0(shader
->prog_data
.base
->uniforms
.contents
[i
]));
449 dirty
|= VC5_DIRTY_FRAGTEX
| VC5_DIRTY_VERTTEX
;
454 shader
->uniform_dirty_bits
= dirty
;