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_blitter.h"
25 #include "util/u_prim.h"
26 #include "util/u_format.h"
27 #include "util/u_pack_color.h"
28 #include "util/u_prim_restart.h"
29 #include "util/u_upload_mgr.h"
30 #include "indices/u_primconvert.h"
32 #include "v3d_context.h"
33 #include "v3d_resource.h"
35 #include "broadcom/compiler/v3d_compiler.h"
36 #include "broadcom/common/v3d_macros.h"
37 #include "broadcom/cle/v3dx_pack.h"
40 * Does the initial bining command list setup for drawing to a given FBO.
43 v3d_start_draw(struct v3d_context
*v3d
)
45 struct v3d_job
*job
= v3d
->job
;
50 /* Get space to emit our BCL state, using a branch to jump to a new BO
53 v3d_cl_ensure_space_with_branch(&job
->bcl
, 256 /* XXX */);
55 job
->submit
.bcl_start
= job
->bcl
.bo
->offset
;
56 v3d_job_add_bo(job
, job
->bcl
.bo
);
58 job
->tile_alloc
= v3d_bo_alloc(v3d
->screen
, 1024 * 1024, "tile_alloc");
59 uint32_t tsda_per_tile_size
= v3d
->screen
->devinfo
.ver
>= 40 ? 256 : 64;
60 job
->tile_state
= v3d_bo_alloc(v3d
->screen
,
67 cl_emit(&job
->bcl
, TILE_BINNING_MODE_CFG
, config
) {
68 config
.width_in_pixels
= v3d
->framebuffer
.width
;
69 config
.height_in_pixels
= v3d
->framebuffer
.height
;
70 config
.number_of_render_targets
=
71 MAX2(v3d
->framebuffer
.nr_cbufs
, 1);
73 config
.multisample_mode_4x
= job
->msaa
;
75 config
.maximum_bpp_of_all_render_targets
= job
->internal_bpp
;
77 #else /* V3D_VERSION < 40 */
78 /* "Binning mode lists start with a Tile Binning Mode Configuration
81 * Part1 signals the end of binning config setup.
83 cl_emit(&job
->bcl
, TILE_BINNING_MODE_CFG_PART2
, config
) {
84 config
.tile_allocation_memory_address
=
85 cl_address(job
->tile_alloc
, 0);
86 config
.tile_allocation_memory_size
= job
->tile_alloc
->size
;
89 cl_emit(&job
->bcl
, TILE_BINNING_MODE_CFG_PART1
, config
) {
90 config
.tile_state_data_array_base_address
=
91 cl_address(job
->tile_state
, 0);
93 config
.width_in_tiles
= job
->draw_tiles_x
;
94 config
.height_in_tiles
= job
->draw_tiles_y
;
96 config
.number_of_render_targets
=
97 MAX2(v3d
->framebuffer
.nr_cbufs
, 1);
99 config
.multisample_mode_4x
= job
->msaa
;
101 config
.maximum_bpp_of_all_render_targets
= job
->internal_bpp
;
103 #endif /* V3D_VERSION < 40 */
105 /* There's definitely nothing in the VCD cache we want. */
106 cl_emit(&job
->bcl
, FLUSH_VCD_CACHE
, bin
);
108 /* Disable any leftover OQ state from another job. */
109 cl_emit(&job
->bcl
, OCCLUSION_QUERY_COUNTER
, counter
);
111 /* "Binning mode lists must have a Start Tile Binning item (6) after
112 * any prefix state data before the binning list proper starts."
114 cl_emit(&job
->bcl
, START_TILE_BINNING
, bin
);
116 job
->needs_flush
= true;
117 job
->draw_width
= v3d
->framebuffer
.width
;
118 job
->draw_height
= v3d
->framebuffer
.height
;
122 v3d_predraw_check_stage_inputs(struct pipe_context
*pctx
,
123 enum pipe_shader_type s
)
125 struct v3d_context
*v3d
= v3d_context(pctx
);
127 /* XXX perf: If we're reading from the output of TF in this job, we
128 * should instead be using the wait for transform feedback
132 /* Flush writes to textures we're sampling. */
133 for (int i
= 0; i
< v3d
->tex
[s
].num_textures
; i
++) {
134 struct pipe_sampler_view
*pview
= v3d
->tex
[s
].textures
[i
];
137 struct v3d_sampler_view
*view
= v3d_sampler_view(pview
);
139 if (view
->texture
!= view
->base
.texture
)
140 v3d_update_shadow_texture(pctx
, &view
->base
);
142 v3d_flush_jobs_writing_resource(v3d
, view
->texture
);
145 /* Flush writes to UBOs. */
146 foreach_bit(i
, v3d
->constbuf
[s
].enabled_mask
) {
147 struct pipe_constant_buffer
*cb
= &v3d
->constbuf
[s
].cb
[i
];
149 v3d_flush_jobs_writing_resource(v3d
, cb
->buffer
);
154 v3d_emit_gl_shader_state(struct v3d_context
*v3d
,
155 const struct pipe_draw_info
*info
)
157 struct v3d_job
*job
= v3d
->job
;
158 /* VC5_DIRTY_VTXSTATE */
159 struct v3d_vertex_stateobj
*vtx
= v3d
->vtx
;
160 /* VC5_DIRTY_VTXBUF */
161 struct v3d_vertexbuf_stateobj
*vertexbuf
= &v3d
->vertexbuf
;
163 /* Upload the uniforms to the indirect CL first */
164 struct v3d_cl_reloc fs_uniforms
=
165 v3d_write_uniforms(v3d
, v3d
->prog
.fs
,
166 PIPE_SHADER_FRAGMENT
);
167 struct v3d_cl_reloc vs_uniforms
=
168 v3d_write_uniforms(v3d
, v3d
->prog
.vs
,
170 struct v3d_cl_reloc cs_uniforms
=
171 v3d_write_uniforms(v3d
, v3d
->prog
.cs
,
174 /* See GFXH-930 workaround below */
175 uint32_t num_elements_to_emit
= MAX2(vtx
->num_elements
, 1);
176 uint32_t shader_rec_offset
=
177 v3d_cl_ensure_space(&job
->indirect
,
178 cl_packet_length(GL_SHADER_STATE_RECORD
) +
179 num_elements_to_emit
*
180 cl_packet_length(GL_SHADER_STATE_ATTRIBUTE_RECORD
),
183 /* XXX perf: We should move most of the SHADER_STATE_RECORD setup to
184 * compile time, so that we mostly just have to OR the VS and FS
185 * records together at draw time.
187 cl_emit(&job
->indirect
, GL_SHADER_STATE_RECORD
, shader
) {
188 shader
.enable_clipping
= true;
189 /* VC5_DIRTY_PRIM_MODE | VC5_DIRTY_RASTERIZER */
190 shader
.point_size_in_shaded_vertex_data
=
191 (info
->mode
== PIPE_PRIM_POINTS
&&
192 v3d
->rasterizer
->base
.point_size_per_vertex
);
194 /* Must be set if the shader modifies Z, discards, or modifies
195 * the sample mask. For any of these cases, the fragment
196 * shader needs to write the Z value (even just discards).
198 shader
.fragment_shader_does_z_writes
=
199 (v3d
->prog
.fs
->prog_data
.fs
->writes_z
||
200 v3d
->prog
.fs
->prog_data
.fs
->discard
);
202 shader
.fragment_shader_uses_real_pixel_centre_w_in_addition_to_centroid_w2
=
203 v3d
->prog
.fs
->prog_data
.fs
->uses_center_w
;
205 shader
.number_of_varyings_in_fragment_shader
=
206 v3d
->prog
.fs
->prog_data
.base
->num_inputs
;
208 shader
.coordinate_shader_propagate_nans
= true;
209 shader
.vertex_shader_propagate_nans
= true;
210 shader
.fragment_shader_propagate_nans
= true;
212 shader
.coordinate_shader_code_address
=
213 cl_address(v3d_resource(v3d
->prog
.cs
->resource
)->bo
,
214 v3d
->prog
.cs
->offset
);
215 shader
.vertex_shader_code_address
=
216 cl_address(v3d_resource(v3d
->prog
.vs
->resource
)->bo
,
217 v3d
->prog
.vs
->offset
);
218 shader
.fragment_shader_code_address
=
219 cl_address(v3d_resource(v3d
->prog
.fs
->resource
)->bo
,
220 v3d
->prog
.fs
->offset
);
222 /* XXX: Use combined input/output size flag in the common
225 shader
.coordinate_shader_has_separate_input_and_output_vpm_blocks
=
226 v3d
->prog
.cs
->prog_data
.vs
->separate_segments
;
227 shader
.vertex_shader_has_separate_input_and_output_vpm_blocks
=
228 v3d
->prog
.vs
->prog_data
.vs
->separate_segments
;
230 shader
.coordinate_shader_input_vpm_segment_size
=
231 v3d
->prog
.cs
->prog_data
.vs
->vpm_input_size
;
232 shader
.vertex_shader_input_vpm_segment_size
=
233 v3d
->prog
.vs
->prog_data
.vs
->vpm_input_size
;
235 shader
.coordinate_shader_output_vpm_segment_size
=
236 v3d
->prog
.cs
->prog_data
.vs
->vpm_output_size
;
237 shader
.vertex_shader_output_vpm_segment_size
=
238 v3d
->prog
.vs
->prog_data
.vs
->vpm_output_size
;
240 shader
.coordinate_shader_uniforms_address
= cs_uniforms
;
241 shader
.vertex_shader_uniforms_address
= vs_uniforms
;
242 shader
.fragment_shader_uniforms_address
= fs_uniforms
;
244 #if V3D_VERSION >= 41
245 shader
.min_coord_shader_input_segments_required_in_play
= 1;
246 shader
.min_vertex_shader_input_segments_required_in_play
= 1;
248 shader
.coordinate_shader_4_way_threadable
=
249 v3d
->prog
.cs
->prog_data
.vs
->base
.threads
== 4;
250 shader
.vertex_shader_4_way_threadable
=
251 v3d
->prog
.vs
->prog_data
.vs
->base
.threads
== 4;
252 shader
.fragment_shader_4_way_threadable
=
253 v3d
->prog
.fs
->prog_data
.fs
->base
.threads
== 4;
255 shader
.coordinate_shader_start_in_final_thread_section
=
256 v3d
->prog
.cs
->prog_data
.vs
->base
.single_seg
;
257 shader
.vertex_shader_start_in_final_thread_section
=
258 v3d
->prog
.vs
->prog_data
.vs
->base
.single_seg
;
259 shader
.fragment_shader_start_in_final_thread_section
=
260 v3d
->prog
.fs
->prog_data
.fs
->base
.single_seg
;
262 shader
.coordinate_shader_4_way_threadable
=
263 v3d
->prog
.cs
->prog_data
.vs
->base
.threads
== 4;
264 shader
.coordinate_shader_2_way_threadable
=
265 v3d
->prog
.cs
->prog_data
.vs
->base
.threads
== 2;
266 shader
.vertex_shader_4_way_threadable
=
267 v3d
->prog
.vs
->prog_data
.vs
->base
.threads
== 4;
268 shader
.vertex_shader_2_way_threadable
=
269 v3d
->prog
.vs
->prog_data
.vs
->base
.threads
== 2;
270 shader
.fragment_shader_4_way_threadable
=
271 v3d
->prog
.fs
->prog_data
.fs
->base
.threads
== 4;
272 shader
.fragment_shader_2_way_threadable
=
273 v3d
->prog
.fs
->prog_data
.fs
->base
.threads
== 2;
276 shader
.vertex_id_read_by_coordinate_shader
=
277 v3d
->prog
.cs
->prog_data
.vs
->uses_vid
;
278 shader
.instance_id_read_by_coordinate_shader
=
279 v3d
->prog
.cs
->prog_data
.vs
->uses_iid
;
280 shader
.vertex_id_read_by_vertex_shader
=
281 v3d
->prog
.vs
->prog_data
.vs
->uses_vid
;
282 shader
.instance_id_read_by_vertex_shader
=
283 v3d
->prog
.vs
->prog_data
.vs
->uses_iid
;
285 shader
.address_of_default_attribute_values
=
286 cl_address(v3d_resource(vtx
->defaults
)->bo
,
287 vtx
->defaults_offset
);
290 for (int i
= 0; i
< vtx
->num_elements
; i
++) {
291 struct pipe_vertex_element
*elem
= &vtx
->pipe
[i
];
292 struct pipe_vertex_buffer
*vb
=
293 &vertexbuf
->vb
[elem
->vertex_buffer_index
];
294 struct v3d_resource
*rsc
= v3d_resource(vb
->buffer
.resource
);
296 const uint32_t size
=
297 cl_packet_length(GL_SHADER_STATE_ATTRIBUTE_RECORD
);
298 cl_emit_with_prepacked(&job
->indirect
,
299 GL_SHADER_STATE_ATTRIBUTE_RECORD
,
300 &vtx
->attrs
[i
* size
], attr
) {
301 attr
.stride
= vb
->stride
;
302 attr
.address
= cl_address(rsc
->bo
,
305 attr
.number_of_values_read_by_coordinate_shader
=
306 v3d
->prog
.cs
->prog_data
.vs
->vattr_sizes
[i
];
307 attr
.number_of_values_read_by_vertex_shader
=
308 v3d
->prog
.vs
->prog_data
.vs
->vattr_sizes
[i
];
309 #if V3D_VERSION >= 41
310 attr
.maximum_index
= 0xffffff;
313 STATIC_ASSERT(sizeof(vtx
->attrs
) >= VC5_MAX_ATTRIBUTES
* size
);
316 if (vtx
->num_elements
== 0) {
317 /* GFXH-930: At least one attribute must be enabled and read
318 * by CS and VS. If we have no attributes being consumed by
319 * the shader, set up a dummy to be loaded into the VPM.
321 cl_emit(&job
->indirect
, GL_SHADER_STATE_ATTRIBUTE_RECORD
, attr
) {
322 /* Valid address of data whose value will be unused. */
323 attr
.address
= cl_address(job
->indirect
.bo
, 0);
325 attr
.type
= ATTRIBUTE_FLOAT
;
329 attr
.number_of_values_read_by_coordinate_shader
= 1;
330 attr
.number_of_values_read_by_vertex_shader
= 1;
334 cl_emit(&job
->bcl
, VCM_CACHE_SIZE
, vcm
) {
335 vcm
.number_of_16_vertex_batches_for_binning
=
336 v3d
->prog
.cs
->prog_data
.vs
->vcm_cache_size
;
337 vcm
.number_of_16_vertex_batches_for_rendering
=
338 v3d
->prog
.vs
->prog_data
.vs
->vcm_cache_size
;
341 cl_emit(&job
->bcl
, GL_SHADER_STATE
, state
) {
342 state
.address
= cl_address(job
->indirect
.bo
, shader_rec_offset
);
343 state
.number_of_attribute_arrays
= num_elements_to_emit
;
346 v3d_bo_unreference(&cs_uniforms
.bo
);
347 v3d_bo_unreference(&vs_uniforms
.bo
);
348 v3d_bo_unreference(&fs_uniforms
.bo
);
350 job
->shader_rec_count
++;
354 * Computes the various transform feedback statistics, since they can't be
355 * recorded by CL packets.
358 v3d_tf_statistics_record(struct v3d_context
*v3d
,
359 const struct pipe_draw_info
*info
,
362 if (!v3d
->active_queries
)
365 uint32_t prims
= u_prims_for_vertices(info
->mode
, info
->count
);
366 v3d
->prims_generated
+= prims
;
369 /* XXX: Only count if we didn't overflow. */
370 v3d
->tf_prims_generated
+= prims
;
375 v3d_update_job_ez(struct v3d_context
*v3d
, struct v3d_job
*job
)
377 switch (v3d
->zsa
->ez_state
) {
378 case VC5_EZ_UNDECIDED
:
379 /* If the Z/S state didn't pick a direction but didn't
380 * disable, then go along with the current EZ state. This
381 * allows EZ optimization for Z func == EQUAL or NEVER.
387 /* If the Z/S state picked a direction, then it needs to match
388 * the current direction if we've decided on one.
390 if (job
->ez_state
== VC5_EZ_UNDECIDED
)
391 job
->ez_state
= v3d
->zsa
->ez_state
;
392 else if (job
->ez_state
!= v3d
->zsa
->ez_state
)
393 job
->ez_state
= VC5_EZ_DISABLED
;
396 case VC5_EZ_DISABLED
:
397 /* If the current Z/S state disables EZ because of a bad Z
398 * func or stencil operation, then we can't do any more EZ in
401 job
->ez_state
= VC5_EZ_DISABLED
;
405 /* If the FS affects the Z of the pixels, then it may update against
406 * the chosen EZ direction (though we could use
407 * ARB_conservative_depth's hints to avoid this)
409 if (v3d
->prog
.fs
->prog_data
.fs
->writes_z
) {
410 job
->ez_state
= VC5_EZ_DISABLED
;
413 if (job
->first_ez_state
== VC5_EZ_UNDECIDED
&&
414 (job
->ez_state
!= VC5_EZ_DISABLED
|| job
->draw_calls_queued
== 0))
415 job
->first_ez_state
= job
->ez_state
;
419 v3d_draw_vbo(struct pipe_context
*pctx
, const struct pipe_draw_info
*info
)
421 struct v3d_context
*v3d
= v3d_context(pctx
);
423 if (!info
->count_from_stream_output
&& !info
->indirect
&&
424 !info
->primitive_restart
&&
425 !u_trim_pipe_prim(info
->mode
, (unsigned*)&info
->count
))
428 /* Fall back for weird desktop GL primitive restart values. */
429 if (info
->primitive_restart
&&
433 switch (info
->index_size
) {
442 if (info
->restart_index
!= mask
) {
443 util_draw_vbo_without_prim_restart(pctx
, info
);
448 if (info
->mode
>= PIPE_PRIM_QUADS
) {
449 util_primconvert_save_rasterizer_state(v3d
->primconvert
, &v3d
->rasterizer
->base
);
450 util_primconvert_draw_vbo(v3d
->primconvert
, info
);
451 perf_debug("Fallback conversion for %d %s vertices\n",
452 info
->count
, u_prim_name(info
->mode
));
456 /* Before setting up the draw, flush anything writing to the textures
459 for (int s
= 0; s
< PIPE_SHADER_TYPES
; s
++)
460 v3d_predraw_check_stage_inputs(pctx
, s
);
463 v3d_flush_jobs_writing_resource(v3d
, info
->indirect
->buffer
);
465 struct v3d_job
*job
= v3d_get_job_for_fbo(v3d
);
467 /* If vertex texturing depends on the output of rendering, we need to
468 * ensure that that rendering is complete before we run a coordinate
469 * shader that depends on it.
471 * Given that doing that is unusual, for now we just block the binner
472 * on the last submitted render, rather than tracking the last
473 * rendering to each texture's BO.
475 if (v3d
->tex
[PIPE_SHADER_VERTEX
].num_textures
) {
476 perf_debug("Blocking binner on last render "
477 "due to vertex texturing.\n");
478 job
->submit
.in_sync_bcl
= v3d
->out_sync
;
481 /* Get space to emit our draw call into the BCL, using a branch to
482 * jump to a new BO if necessary.
484 v3d_cl_ensure_space_with_branch(&job
->bcl
, 256 /* XXX */);
486 if (v3d
->prim_mode
!= info
->mode
) {
487 v3d
->prim_mode
= info
->mode
;
488 v3d
->dirty
|= VC5_DIRTY_PRIM_MODE
;
492 v3d_update_compiled_shaders(v3d
, info
->mode
);
493 v3d_update_job_ez(v3d
, job
);
495 #if V3D_VERSION >= 41
496 v3d41_emit_state(pctx
);
498 v3d33_emit_state(pctx
);
501 if (v3d
->dirty
& (VC5_DIRTY_VTXBUF
|
503 VC5_DIRTY_PRIM_MODE
|
504 VC5_DIRTY_RASTERIZER
|
505 VC5_DIRTY_COMPILED_CS
|
506 VC5_DIRTY_COMPILED_VS
|
507 VC5_DIRTY_COMPILED_FS
|
508 v3d
->prog
.cs
->uniform_dirty_bits
|
509 v3d
->prog
.vs
->uniform_dirty_bits
|
510 v3d
->prog
.fs
->uniform_dirty_bits
)) {
511 v3d_emit_gl_shader_state(v3d
, info
);
516 /* The Base Vertex/Base Instance packet sets those values to nonzero
517 * for the next draw call only.
519 if (info
->index_bias
|| info
->start_instance
) {
520 cl_emit(&job
->bcl
, BASE_VERTEX_BASE_INSTANCE
, base
) {
521 base
.base_instance
= info
->start_instance
;
522 base
.base_vertex
= info
->index_bias
;
526 uint32_t prim_tf_enable
= 0;
528 /* V3D 3.x: The HW only processes transform feedback on primitives
531 if (v3d
->streamout
.num_targets
)
532 prim_tf_enable
= (V3D_PRIM_POINTS_TF
- V3D_PRIM_POINTS
);
535 v3d_tf_statistics_record(v3d
, info
, v3d
->streamout
.num_targets
);
537 /* Note that the primitive type fields match with OpenGL/gallium
538 * definitions, up to but not including QUADS.
540 if (info
->index_size
) {
541 uint32_t index_size
= info
->index_size
;
542 uint32_t offset
= info
->start
* index_size
;
543 struct pipe_resource
*prsc
;
544 if (info
->has_user_indices
) {
546 u_upload_data(v3d
->uploader
, 0,
547 info
->count
* info
->index_size
, 4,
551 prsc
= info
->index
.resource
;
553 struct v3d_resource
*rsc
= v3d_resource(prsc
);
555 #if V3D_VERSION >= 40
556 cl_emit(&job
->bcl
, INDEX_BUFFER_SETUP
, ib
) {
557 ib
.address
= cl_address(rsc
->bo
, 0);
558 ib
.size
= rsc
->bo
->size
;
562 if (info
->indirect
) {
563 cl_emit(&job
->bcl
, INDIRECT_INDEXED_INSTANCED_PRIM_LIST
, prim
) {
564 prim
.index_type
= ffs(info
->index_size
) - 1;
566 prim
.address_of_indices_list
=
567 cl_address(rsc
->bo
, offset
);
568 #endif /* V3D_VERSION < 40 */
569 prim
.mode
= info
->mode
| prim_tf_enable
;
570 prim
.enable_primitive_restarts
= info
->primitive_restart
;
572 prim
.number_of_draw_indirect_indexed_records
= info
->indirect
->draw_count
;
574 prim
.stride_in_multiples_of_4_bytes
= info
->indirect
->stride
>> 2;
575 prim
.address
= cl_address(v3d_resource(info
->indirect
->buffer
)->bo
,
576 info
->indirect
->offset
);
578 } else if (info
->instance_count
> 1) {
579 cl_emit(&job
->bcl
, INDEXED_INSTANCED_PRIM_LIST
, prim
) {
580 prim
.index_type
= ffs(info
->index_size
) - 1;
581 #if V3D_VERSION >= 40
582 prim
.index_offset
= offset
;
583 #else /* V3D_VERSION < 40 */
584 prim
.maximum_index
= (1u << 31) - 1; /* XXX */
585 prim
.address_of_indices_list
=
586 cl_address(rsc
->bo
, offset
);
587 #endif /* V3D_VERSION < 40 */
588 prim
.mode
= info
->mode
| prim_tf_enable
;
589 prim
.enable_primitive_restarts
= info
->primitive_restart
;
591 prim
.number_of_instances
= info
->instance_count
;
592 prim
.instance_length
= info
->count
;
595 cl_emit(&job
->bcl
, INDEXED_PRIM_LIST
, prim
) {
596 prim
.index_type
= ffs(info
->index_size
) - 1;
597 prim
.length
= info
->count
;
598 #if V3D_VERSION >= 40
599 prim
.index_offset
= offset
;
600 #else /* V3D_VERSION < 40 */
601 prim
.maximum_index
= (1u << 31) - 1; /* XXX */
602 prim
.address_of_indices_list
=
603 cl_address(rsc
->bo
, offset
);
604 #endif /* V3D_VERSION < 40 */
605 prim
.mode
= info
->mode
| prim_tf_enable
;
606 prim
.enable_primitive_restarts
= info
->primitive_restart
;
610 job
->draw_calls_queued
++;
612 if (info
->has_user_indices
)
613 pipe_resource_reference(&prsc
, NULL
);
615 if (info
->indirect
) {
616 cl_emit(&job
->bcl
, INDIRECT_VERTEX_ARRAY_INSTANCED_PRIMS
, prim
) {
617 prim
.mode
= info
->mode
| prim_tf_enable
;
618 prim
.number_of_draw_indirect_array_records
= info
->indirect
->draw_count
;
620 prim
.stride_in_multiples_of_4_bytes
= info
->indirect
->stride
>> 2;
621 prim
.address
= cl_address(v3d_resource(info
->indirect
->buffer
)->bo
,
622 info
->indirect
->offset
);
624 } else if (info
->instance_count
> 1) {
625 cl_emit(&job
->bcl
, VERTEX_ARRAY_INSTANCED_PRIMS
, prim
) {
626 prim
.mode
= info
->mode
| prim_tf_enable
;
627 prim
.index_of_first_vertex
= info
->start
;
628 prim
.number_of_instances
= info
->instance_count
;
629 prim
.instance_length
= info
->count
;
632 cl_emit(&job
->bcl
, VERTEX_ARRAY_PRIMS
, prim
) {
633 prim
.mode
= info
->mode
| prim_tf_enable
;
634 prim
.length
= info
->count
;
635 prim
.index_of_first_vertex
= info
->start
;
640 /* A flush is required in between a TF draw and any following TF specs
641 * packet, or the GPU may hang. Just flush each time for now.
643 if (v3d
->streamout
.num_targets
)
644 cl_emit(&job
->bcl
, TRANSFORM_FEEDBACK_FLUSH_AND_COUNT
, flush
);
646 job
->draw_calls_queued
++;
648 /* Increment the TF offsets by how many verts we wrote. XXX: This
649 * needs some clamping to the buffer size.
651 for (int i
= 0; i
< v3d
->streamout
.num_targets
; i
++)
652 v3d
->streamout
.offsets
[i
] += info
->count
;
654 if (v3d
->zsa
&& job
->zsbuf
&& v3d
->zsa
->base
.depth
.enabled
) {
655 struct v3d_resource
*rsc
= v3d_resource(job
->zsbuf
->texture
);
656 v3d_job_add_bo(job
, rsc
->bo
);
658 job
->load
|= PIPE_CLEAR_DEPTH
& ~job
->clear
;
659 if (v3d
->zsa
->base
.depth
.writemask
)
660 job
->store
|= PIPE_CLEAR_DEPTH
;
661 rsc
->initialized_buffers
= PIPE_CLEAR_DEPTH
;
664 if (v3d
->zsa
&& job
->zsbuf
&& v3d
->zsa
->base
.stencil
[0].enabled
) {
665 struct v3d_resource
*rsc
= v3d_resource(job
->zsbuf
->texture
);
666 if (rsc
->separate_stencil
)
667 rsc
= rsc
->separate_stencil
;
669 v3d_job_add_bo(job
, rsc
->bo
);
671 job
->load
|= PIPE_CLEAR_STENCIL
& ~job
->clear
;
672 if (v3d
->zsa
->base
.stencil
[0].writemask
||
673 v3d
->zsa
->base
.stencil
[1].writemask
) {
674 job
->store
|= PIPE_CLEAR_STENCIL
;
676 rsc
->initialized_buffers
|= PIPE_CLEAR_STENCIL
;
679 for (int i
= 0; i
< VC5_MAX_DRAW_BUFFERS
; i
++) {
680 uint32_t bit
= PIPE_CLEAR_COLOR0
<< i
;
681 int blend_rt
= v3d
->blend
->base
.independent_blend_enable
? i
: 0;
683 if (job
->store
& bit
|| !job
->cbufs
[i
])
685 struct v3d_resource
*rsc
= v3d_resource(job
->cbufs
[i
]->texture
);
687 job
->load
|= bit
& ~job
->clear
;
688 if (v3d
->blend
->base
.rt
[blend_rt
].colormask
)
690 v3d_job_add_bo(job
, rsc
->bo
);
693 if (job
->referenced_size
> 768 * 1024 * 1024) {
694 perf_debug("Flushing job with %dkb to try to free up memory\n",
695 job
->referenced_size
/ 1024);
699 if (V3D_DEBUG
& V3D_DEBUG_ALWAYS_FLUSH
)
704 * Implements gallium's clear() hook (glClear()) by drawing a pair of triangles.
707 v3d_draw_clear(struct v3d_context
*v3d
,
709 const union pipe_color_union
*color
,
710 double depth
, unsigned stencil
)
712 static const union pipe_color_union dummy_color
= {};
714 /* The blitter util dereferences the color regardless, even though the
715 * gallium clear API may not pass one in when only Z/S are cleared.
718 color
= &dummy_color
;
720 v3d_blitter_save(v3d
);
721 util_blitter_clear(v3d
->blitter
,
722 v3d
->framebuffer
.width
,
723 v3d
->framebuffer
.height
,
724 util_framebuffer_get_num_layers(&v3d
->framebuffer
),
725 buffers
, color
, depth
, stencil
);
729 * Attempts to perform the GL clear by using the TLB's fast clear at the start
733 v3d_tlb_clear(struct v3d_job
*job
, unsigned buffers
,
734 const union pipe_color_union
*color
,
735 double depth
, unsigned stencil
)
737 struct v3d_context
*v3d
= job
->v3d
;
739 if (job
->draw_calls_queued
) {
740 /* If anything in the CL has drawn using the buffer, then the
741 * TLB clear we're trying to add now would happen before that
744 buffers
&= ~(job
->load
| job
->store
);
747 /* GFXH-1461: If we were to emit a load of just depth or just stencil,
748 * then the clear for the other may get lost. We need to decide now
749 * if it would be possible to need to emit a load of just one after
750 * we've set up our TLB clears.
752 if (buffers
& PIPE_CLEAR_DEPTHSTENCIL
&&
753 (buffers
& PIPE_CLEAR_DEPTHSTENCIL
) != PIPE_CLEAR_DEPTHSTENCIL
&&
755 util_format_is_depth_and_stencil(job
->zsbuf
->texture
->format
)) {
756 buffers
&= ~PIPE_CLEAR_DEPTHSTENCIL
;
759 for (int i
= 0; i
< VC5_MAX_DRAW_BUFFERS
; i
++) {
760 uint32_t bit
= PIPE_CLEAR_COLOR0
<< i
;
761 if (!(buffers
& bit
))
764 struct pipe_surface
*psurf
= v3d
->framebuffer
.cbufs
[i
];
765 struct v3d_surface
*surf
= v3d_surface(psurf
);
766 struct v3d_resource
*rsc
= v3d_resource(psurf
->texture
);
769 uint32_t internal_size
= 4 << surf
->internal_bpp
;
771 static union pipe_color_union swapped_color
;
772 if (v3d
->swap_color_rb
& (1 << i
)) {
773 swapped_color
.f
[0] = color
->f
[2];
774 swapped_color
.f
[1] = color
->f
[1];
775 swapped_color
.f
[2] = color
->f
[0];
776 swapped_color
.f
[3] = color
->f
[3];
777 color
= &swapped_color
;
780 switch (surf
->internal_type
) {
781 case V3D_INTERNAL_TYPE_8
:
782 util_pack_color(color
->f
, PIPE_FORMAT_R8G8B8A8_UNORM
,
784 memcpy(job
->clear_color
[i
], uc
.ui
, internal_size
);
786 case V3D_INTERNAL_TYPE_8I
:
787 case V3D_INTERNAL_TYPE_8UI
:
788 job
->clear_color
[i
][0] = ((color
->ui
[0] & 0xff) |
789 (color
->ui
[1] & 0xff) << 8 |
790 (color
->ui
[2] & 0xff) << 16 |
791 (color
->ui
[3] & 0xff) << 24);
793 case V3D_INTERNAL_TYPE_16F
:
794 util_pack_color(color
->f
, PIPE_FORMAT_R16G16B16A16_FLOAT
,
796 memcpy(job
->clear_color
[i
], uc
.ui
, internal_size
);
798 case V3D_INTERNAL_TYPE_16I
:
799 case V3D_INTERNAL_TYPE_16UI
:
800 job
->clear_color
[i
][0] = ((color
->ui
[0] & 0xffff) |
802 job
->clear_color
[i
][1] = ((color
->ui
[2] & 0xffff) |
805 case V3D_INTERNAL_TYPE_32F
:
806 case V3D_INTERNAL_TYPE_32I
:
807 case V3D_INTERNAL_TYPE_32UI
:
808 memcpy(job
->clear_color
[i
], color
->ui
, internal_size
);
812 rsc
->initialized_buffers
|= bit
;
815 unsigned zsclear
= buffers
& PIPE_CLEAR_DEPTHSTENCIL
;
817 struct v3d_resource
*rsc
=
818 v3d_resource(v3d
->framebuffer
.zsbuf
->texture
);
820 if (zsclear
& PIPE_CLEAR_DEPTH
)
821 job
->clear_z
= depth
;
822 if (zsclear
& PIPE_CLEAR_STENCIL
)
823 job
->clear_s
= stencil
;
825 rsc
->initialized_buffers
|= zsclear
;
830 job
->draw_max_x
= v3d
->framebuffer
.width
;
831 job
->draw_max_y
= v3d
->framebuffer
.height
;
832 job
->clear
|= buffers
;
833 job
->store
|= buffers
;
841 v3d_clear(struct pipe_context
*pctx
, unsigned buffers
,
842 const union pipe_color_union
*color
, double depth
, unsigned stencil
)
844 struct v3d_context
*v3d
= v3d_context(pctx
);
845 struct v3d_job
*job
= v3d_get_job_for_fbo(v3d
);
847 buffers
&= ~v3d_tlb_clear(job
, buffers
, color
, depth
, stencil
);
850 v3d_draw_clear(v3d
, buffers
, color
, depth
, stencil
);
854 v3d_clear_render_target(struct pipe_context
*pctx
, struct pipe_surface
*ps
,
855 const union pipe_color_union
*color
,
856 unsigned x
, unsigned y
, unsigned w
, unsigned h
,
857 bool render_condition_enabled
)
859 fprintf(stderr
, "unimpl: clear RT\n");
863 v3d_clear_depth_stencil(struct pipe_context
*pctx
, struct pipe_surface
*ps
,
864 unsigned buffers
, double depth
, unsigned stencil
,
865 unsigned x
, unsigned y
, unsigned w
, unsigned h
,
866 bool render_condition_enabled
)
868 fprintf(stderr
, "unimpl: clear DS\n");
872 v3dX(draw_init
)(struct pipe_context
*pctx
)
874 pctx
->draw_vbo
= v3d_draw_vbo
;
875 pctx
->clear
= v3d_clear
;
876 pctx
->clear_render_target
= v3d_clear_render_target
;
877 pctx
->clear_depth_stencil
= v3d_clear_depth_stencil
;