2 * Copyright © 2016 Red Hat.
3 * Copyright © 2016 Bas Nieuwenhuizen
5 * based in part on anv driver which is:
6 * Copyright © 2015 Intel Corporation
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice (including the next
16 * paragraph) shall be included in all copies or substantial portions of the
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 * DEALINGS IN THE SOFTWARE.
28 #include "tu_private.h"
30 #include "main/menums.h"
32 #include "nir/nir_builder.h"
33 #include "spirv/nir_spirv.h"
34 #include "util/debug.h"
35 #include "util/mesa-sha1.h"
36 #include "util/u_atomic.h"
37 #include "vk_format.h"
42 struct tu_pipeline_builder
44 struct tu_device
*device
;
45 struct tu_pipeline_cache
*cache
;
46 const VkAllocationCallbacks
*alloc
;
47 const VkGraphicsPipelineCreateInfo
*create_info
;
49 bool rasterizer_discard
;
50 /* these states are affectd by rasterizer_discard */
51 VkSampleCountFlagBits samples
;
52 bool use_depth_stencil_attachment
;
55 static enum tu_dynamic_state_bits
56 tu_dynamic_state_bit(VkDynamicState state
)
59 case VK_DYNAMIC_STATE_VIEWPORT
:
60 return TU_DYNAMIC_VIEWPORT
;
61 case VK_DYNAMIC_STATE_SCISSOR
:
62 return TU_DYNAMIC_SCISSOR
;
63 case VK_DYNAMIC_STATE_LINE_WIDTH
:
64 return TU_DYNAMIC_LINE_WIDTH
;
65 case VK_DYNAMIC_STATE_DEPTH_BIAS
:
66 return TU_DYNAMIC_DEPTH_BIAS
;
67 case VK_DYNAMIC_STATE_BLEND_CONSTANTS
:
68 return TU_DYNAMIC_BLEND_CONSTANTS
;
69 case VK_DYNAMIC_STATE_DEPTH_BOUNDS
:
70 return TU_DYNAMIC_DEPTH_BOUNDS
;
71 case VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK
:
72 return TU_DYNAMIC_STENCIL_COMPARE_MASK
;
73 case VK_DYNAMIC_STATE_STENCIL_WRITE_MASK
:
74 return TU_DYNAMIC_STENCIL_WRITE_MASK
;
75 case VK_DYNAMIC_STATE_STENCIL_REFERENCE
:
76 return TU_DYNAMIC_STENCIL_REFERENCE
;
78 unreachable("invalid dynamic state");
83 static enum pc_di_primtype
84 tu6_primtype(VkPrimitiveTopology topology
)
87 case VK_PRIMITIVE_TOPOLOGY_POINT_LIST
:
88 return DI_PT_POINTLIST
;
89 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST
:
90 return DI_PT_LINELIST
;
91 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP
:
92 return DI_PT_LINESTRIP
;
93 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST
:
95 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP
:
97 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN
:
99 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY
:
100 return DI_PT_LINE_ADJ
;
101 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY
:
102 return DI_PT_LINESTRIP_ADJ
;
103 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY
:
104 return DI_PT_TRI_ADJ
;
105 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY
:
106 return DI_PT_TRISTRIP_ADJ
;
107 case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST
:
109 unreachable("invalid primitive topology");
114 static enum adreno_compare_func
115 tu6_compare_func(VkCompareOp op
)
118 case VK_COMPARE_OP_NEVER
:
120 case VK_COMPARE_OP_LESS
:
122 case VK_COMPARE_OP_EQUAL
:
124 case VK_COMPARE_OP_LESS_OR_EQUAL
:
126 case VK_COMPARE_OP_GREATER
:
128 case VK_COMPARE_OP_NOT_EQUAL
:
129 return FUNC_NOTEQUAL
;
130 case VK_COMPARE_OP_GREATER_OR_EQUAL
:
132 case VK_COMPARE_OP_ALWAYS
:
135 unreachable("invalid VkCompareOp");
140 static enum adreno_stencil_op
141 tu6_stencil_op(VkStencilOp op
)
144 case VK_STENCIL_OP_KEEP
:
146 case VK_STENCIL_OP_ZERO
:
148 case VK_STENCIL_OP_REPLACE
:
149 return STENCIL_REPLACE
;
150 case VK_STENCIL_OP_INCREMENT_AND_CLAMP
:
151 return STENCIL_INCR_CLAMP
;
152 case VK_STENCIL_OP_DECREMENT_AND_CLAMP
:
153 return STENCIL_DECR_CLAMP
;
154 case VK_STENCIL_OP_INVERT
:
155 return STENCIL_INVERT
;
156 case VK_STENCIL_OP_INCREMENT_AND_WRAP
:
157 return STENCIL_INCR_WRAP
;
158 case VK_STENCIL_OP_DECREMENT_AND_WRAP
:
159 return STENCIL_DECR_WRAP
;
161 unreachable("invalid VkStencilOp");
167 tu6_guardband_adj(uint32_t v
)
170 return (uint32_t)(511.0 - 65.0 * (log2(v
) - 8.0));
176 tu6_emit_viewport(struct tu_cs
*cs
, const VkViewport
*viewport
)
180 scales
[0] = viewport
->width
/ 2.0f
;
181 scales
[1] = viewport
->height
/ 2.0f
;
182 scales
[2] = viewport
->maxDepth
- viewport
->minDepth
;
183 offsets
[0] = viewport
->x
+ scales
[0];
184 offsets
[1] = viewport
->y
+ scales
[1];
185 offsets
[2] = viewport
->minDepth
;
189 min
.x
= (int32_t) viewport
->x
;
190 max
.x
= (int32_t) ceilf(viewport
->x
+ viewport
->width
);
191 if (viewport
->height
>= 0.0f
) {
192 min
.y
= (int32_t) viewport
->y
;
193 max
.y
= (int32_t) ceilf(viewport
->y
+ viewport
->height
);
195 min
.y
= (int32_t)(viewport
->y
+ viewport
->height
);
196 max
.y
= (int32_t) ceilf(viewport
->y
);
198 /* the spec allows viewport->height to be 0.0f */
201 assert(min
.x
>= 0 && min
.x
< max
.x
);
202 assert(min
.y
>= 0 && min
.y
< max
.y
);
204 VkExtent2D guardband_adj
;
205 guardband_adj
.width
= tu6_guardband_adj(max
.x
- min
.x
);
206 guardband_adj
.height
= tu6_guardband_adj(max
.y
- min
.y
);
208 tu_cs_emit_pkt4(cs
, REG_A6XX_GRAS_CL_VPORT_XOFFSET_0
, 6);
209 tu_cs_emit(cs
, A6XX_GRAS_CL_VPORT_XOFFSET_0(offsets
[0]));
210 tu_cs_emit(cs
, A6XX_GRAS_CL_VPORT_XSCALE_0(scales
[0]));
211 tu_cs_emit(cs
, A6XX_GRAS_CL_VPORT_YOFFSET_0(offsets
[1]));
212 tu_cs_emit(cs
, A6XX_GRAS_CL_VPORT_YSCALE_0(scales
[1]));
213 tu_cs_emit(cs
, A6XX_GRAS_CL_VPORT_ZOFFSET_0(offsets
[2]));
214 tu_cs_emit(cs
, A6XX_GRAS_CL_VPORT_ZSCALE_0(scales
[2]));
216 tu_cs_emit_pkt4(cs
, REG_A6XX_GRAS_SC_VIEWPORT_SCISSOR_TL_0
, 2);
217 tu_cs_emit(cs
, A6XX_GRAS_SC_VIEWPORT_SCISSOR_TL_0_X(min
.x
) |
218 A6XX_GRAS_SC_VIEWPORT_SCISSOR_TL_0_Y(min
.y
));
219 tu_cs_emit(cs
, A6XX_GRAS_SC_VIEWPORT_SCISSOR_TL_0_X(max
.x
- 1) |
220 A6XX_GRAS_SC_VIEWPORT_SCISSOR_TL_0_Y(max
.y
- 1));
222 tu_cs_emit_pkt4(cs
, REG_A6XX_GRAS_CL_GUARDBAND_CLIP_ADJ
, 1);
224 A6XX_GRAS_CL_GUARDBAND_CLIP_ADJ_HORZ(guardband_adj
.width
) |
225 A6XX_GRAS_CL_GUARDBAND_CLIP_ADJ_VERT(guardband_adj
.height
));
229 tu6_emit_scissor(struct tu_cs
*cs
, const VkRect2D
*scissor
)
231 const VkOffset2D min
= scissor
->offset
;
232 const VkOffset2D max
= {
233 scissor
->offset
.x
+ scissor
->extent
.width
,
234 scissor
->offset
.y
+ scissor
->extent
.height
,
237 tu_cs_emit_pkt4(cs
, REG_A6XX_GRAS_SC_SCREEN_SCISSOR_TL_0
, 2);
238 tu_cs_emit(cs
, A6XX_GRAS_SC_SCREEN_SCISSOR_TL_0_X(min
.x
) |
239 A6XX_GRAS_SC_SCREEN_SCISSOR_TL_0_Y(min
.y
));
240 tu_cs_emit(cs
, A6XX_GRAS_SC_SCREEN_SCISSOR_TL_0_X(max
.x
- 1) |
241 A6XX_GRAS_SC_SCREEN_SCISSOR_TL_0_Y(max
.y
- 1));
245 tu6_emit_gras_unknowns(struct tu_cs
*cs
)
247 tu_cs_emit_pkt4(cs
, REG_A6XX_GRAS_UNKNOWN_8000
, 1);
248 tu_cs_emit(cs
, 0x80);
249 tu_cs_emit_pkt4(cs
, REG_A6XX_GRAS_UNKNOWN_8001
, 1);
251 tu_cs_emit_pkt4(cs
, REG_A6XX_GRAS_UNKNOWN_8004
, 1);
256 tu6_emit_point_size(struct tu_cs
*cs
)
258 tu_cs_emit_pkt4(cs
, REG_A6XX_GRAS_SU_POINT_MINMAX
, 2);
259 tu_cs_emit(cs
, A6XX_GRAS_SU_POINT_MINMAX_MIN(1.0f
/ 16.0f
) |
260 A6XX_GRAS_SU_POINT_MINMAX_MAX(4092.0f
));
261 tu_cs_emit(cs
, A6XX_GRAS_SU_POINT_SIZE(1.0f
));
265 tu6_gras_su_cntl(const VkPipelineRasterizationStateCreateInfo
*rast_info
,
266 VkSampleCountFlagBits samples
)
268 uint32_t gras_su_cntl
= 0;
270 if (rast_info
->cullMode
& VK_CULL_MODE_FRONT_BIT
)
271 gras_su_cntl
|= A6XX_GRAS_SU_CNTL_CULL_FRONT
;
272 if (rast_info
->cullMode
& VK_CULL_MODE_BACK_BIT
)
273 gras_su_cntl
|= A6XX_GRAS_SU_CNTL_CULL_BACK
;
275 if (rast_info
->frontFace
== VK_FRONT_FACE_CLOCKWISE
)
276 gras_su_cntl
|= A6XX_GRAS_SU_CNTL_FRONT_CW
;
278 /* don't set A6XX_GRAS_SU_CNTL_LINEHALFWIDTH */
280 if (rast_info
->depthBiasEnable
)
281 gras_su_cntl
|= A6XX_GRAS_SU_CNTL_POLY_OFFSET
;
283 if (samples
> VK_SAMPLE_COUNT_1_BIT
)
284 gras_su_cntl
|= A6XX_GRAS_SU_CNTL_MSAA_ENABLE
;
290 tu6_emit_gras_su_cntl(struct tu_cs
*cs
,
291 uint32_t gras_su_cntl
,
294 assert((gras_su_cntl
& A6XX_GRAS_SU_CNTL_LINEHALFWIDTH__MASK
) == 0);
295 gras_su_cntl
|= A6XX_GRAS_SU_CNTL_LINEHALFWIDTH(line_width
/ 2.0f
);
297 tu_cs_emit_pkt4(cs
, REG_A6XX_GRAS_SU_CNTL
, 1);
298 tu_cs_emit(cs
, gras_su_cntl
);
302 tu6_emit_depth_bias(struct tu_cs
*cs
,
303 float constant_factor
,
307 tu_cs_emit_pkt4(cs
, REG_A6XX_GRAS_SU_POLY_OFFSET_SCALE
, 3);
308 tu_cs_emit(cs
, A6XX_GRAS_SU_POLY_OFFSET_SCALE(slope_factor
));
309 tu_cs_emit(cs
, A6XX_GRAS_SU_POLY_OFFSET_OFFSET(constant_factor
));
310 tu_cs_emit(cs
, A6XX_GRAS_SU_POLY_OFFSET_OFFSET_CLAMP(clamp
));
314 tu6_emit_alpha_control_disable(struct tu_cs
*cs
)
316 tu_cs_emit_pkt4(cs
, REG_A6XX_RB_ALPHA_CONTROL
, 1);
321 tu6_emit_depth_control(struct tu_cs
*cs
,
322 const VkPipelineDepthStencilStateCreateInfo
*ds_info
)
324 assert(!ds_info
->depthBoundsTestEnable
);
326 uint32_t rb_depth_cntl
= 0;
327 if (ds_info
->depthTestEnable
) {
329 A6XX_RB_DEPTH_CNTL_Z_ENABLE
|
330 A6XX_RB_DEPTH_CNTL_ZFUNC(tu6_compare_func(ds_info
->depthCompareOp
)) |
331 A6XX_RB_DEPTH_CNTL_Z_TEST_ENABLE
;
333 if (ds_info
->depthWriteEnable
)
334 rb_depth_cntl
|= A6XX_RB_DEPTH_CNTL_Z_WRITE_ENABLE
;
337 tu_cs_emit_pkt4(cs
, REG_A6XX_RB_DEPTH_CNTL
, 1);
338 tu_cs_emit(cs
, rb_depth_cntl
);
342 tu6_emit_stencil_control(struct tu_cs
*cs
,
343 const VkPipelineDepthStencilStateCreateInfo
*ds_info
)
345 uint32_t rb_stencil_control
= 0;
346 if (ds_info
->stencilTestEnable
) {
347 const VkStencilOpState
*front
= &ds_info
->front
;
348 const VkStencilOpState
*back
= &ds_info
->back
;
349 rb_stencil_control
|=
350 A6XX_RB_STENCIL_CONTROL_STENCIL_ENABLE
|
351 A6XX_RB_STENCIL_CONTROL_STENCIL_ENABLE_BF
|
352 A6XX_RB_STENCIL_CONTROL_STENCIL_READ
|
353 A6XX_RB_STENCIL_CONTROL_FUNC(tu6_compare_func(front
->compareOp
)) |
354 A6XX_RB_STENCIL_CONTROL_FAIL(tu6_stencil_op(front
->failOp
)) |
355 A6XX_RB_STENCIL_CONTROL_ZPASS(tu6_stencil_op(front
->passOp
)) |
356 A6XX_RB_STENCIL_CONTROL_ZFAIL(tu6_stencil_op(front
->depthFailOp
)) |
357 A6XX_RB_STENCIL_CONTROL_FUNC_BF(tu6_compare_func(back
->compareOp
)) |
358 A6XX_RB_STENCIL_CONTROL_FAIL_BF(tu6_stencil_op(back
->failOp
)) |
359 A6XX_RB_STENCIL_CONTROL_ZPASS_BF(tu6_stencil_op(back
->passOp
)) |
360 A6XX_RB_STENCIL_CONTROL_ZFAIL_BF(tu6_stencil_op(back
->depthFailOp
));
363 tu_cs_emit_pkt4(cs
, REG_A6XX_RB_STENCIL_CONTROL
, 1);
364 tu_cs_emit(cs
, rb_stencil_control
);
368 tu6_emit_stencil_compare_mask(struct tu_cs
*cs
, uint32_t front
, uint32_t back
)
370 tu_cs_emit_pkt4(cs
, REG_A6XX_RB_STENCILMASK
, 1);
372 cs
, A6XX_RB_STENCILMASK_MASK(front
) | A6XX_RB_STENCILMASK_BFMASK(back
));
376 tu6_emit_stencil_write_mask(struct tu_cs
*cs
, uint32_t front
, uint32_t back
)
378 tu_cs_emit_pkt4(cs
, REG_A6XX_RB_STENCILWRMASK
, 1);
379 tu_cs_emit(cs
, A6XX_RB_STENCILWRMASK_WRMASK(front
) |
380 A6XX_RB_STENCILWRMASK_BFWRMASK(back
));
384 tu6_emit_stencil_reference(struct tu_cs
*cs
, uint32_t front
, uint32_t back
)
386 tu_cs_emit_pkt4(cs
, REG_A6XX_RB_STENCILREF
, 1);
388 A6XX_RB_STENCILREF_REF(front
) | A6XX_RB_STENCILREF_BFREF(back
));
392 tu_pipeline_builder_create_pipeline(struct tu_pipeline_builder
*builder
,
393 struct tu_pipeline
**out_pipeline
)
395 struct tu_device
*dev
= builder
->device
;
397 struct tu_pipeline
*pipeline
=
398 vk_zalloc2(&dev
->alloc
, builder
->alloc
, sizeof(*pipeline
), 8,
399 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT
);
401 return VK_ERROR_OUT_OF_HOST_MEMORY
;
403 tu_cs_init(&pipeline
->cs
, TU_CS_MODE_SUB_STREAM
, 2048);
405 /* reserve the space now such that tu_cs_begin_sub_stream never fails */
406 VkResult result
= tu_cs_reserve_space(dev
, &pipeline
->cs
, 2048);
407 if (result
!= VK_SUCCESS
) {
408 vk_free2(&dev
->alloc
, builder
->alloc
, pipeline
);
412 *out_pipeline
= pipeline
;
418 tu_pipeline_builder_parse_dynamic(struct tu_pipeline_builder
*builder
,
419 struct tu_pipeline
*pipeline
)
421 const VkPipelineDynamicStateCreateInfo
*dynamic_info
=
422 builder
->create_info
->pDynamicState
;
427 for (uint32_t i
= 0; i
< dynamic_info
->dynamicStateCount
; i
++) {
428 pipeline
->dynamic_state
.mask
|=
429 tu_dynamic_state_bit(dynamic_info
->pDynamicStates
[i
]);
434 tu_pipeline_builder_parse_input_assembly(struct tu_pipeline_builder
*builder
,
435 struct tu_pipeline
*pipeline
)
437 const VkPipelineInputAssemblyStateCreateInfo
*ia_info
=
438 builder
->create_info
->pInputAssemblyState
;
440 pipeline
->ia
.primtype
= tu6_primtype(ia_info
->topology
);
441 pipeline
->ia
.primitive_restart
= ia_info
->primitiveRestartEnable
;
445 tu_pipeline_builder_parse_viewport(struct tu_pipeline_builder
*builder
,
446 struct tu_pipeline
*pipeline
)
450 * pViewportState is a pointer to an instance of the
451 * VkPipelineViewportStateCreateInfo structure, and is ignored if the
452 * pipeline has rasterization disabled."
454 * We leave the relevant registers stale in that case.
456 if (builder
->rasterizer_discard
)
459 const VkPipelineViewportStateCreateInfo
*vp_info
=
460 builder
->create_info
->pViewportState
;
463 tu_cs_begin_sub_stream(builder
->device
, &pipeline
->cs
, 15, &vp_cs
);
465 if (!(pipeline
->dynamic_state
.mask
& TU_DYNAMIC_VIEWPORT
)) {
466 assert(vp_info
->viewportCount
== 1);
467 tu6_emit_viewport(&vp_cs
, vp_info
->pViewports
);
470 if (!(pipeline
->dynamic_state
.mask
& TU_DYNAMIC_SCISSOR
)) {
471 assert(vp_info
->scissorCount
== 1);
472 tu6_emit_scissor(&vp_cs
, vp_info
->pScissors
);
475 pipeline
->vp
.state_ib
= tu_cs_end_sub_stream(&pipeline
->cs
, &vp_cs
);
479 tu_pipeline_builder_parse_rasterization(struct tu_pipeline_builder
*builder
,
480 struct tu_pipeline
*pipeline
)
482 const VkPipelineRasterizationStateCreateInfo
*rast_info
=
483 builder
->create_info
->pRasterizationState
;
485 assert(!rast_info
->depthClampEnable
);
486 assert(rast_info
->polygonMode
== VK_POLYGON_MODE_FILL
);
488 struct tu_cs rast_cs
;
489 tu_cs_begin_sub_stream(builder
->device
, &pipeline
->cs
, 20, &rast_cs
);
491 /* move to hw ctx init? */
492 tu6_emit_gras_unknowns(&rast_cs
);
493 tu6_emit_point_size(&rast_cs
);
495 const uint32_t gras_su_cntl
=
496 tu6_gras_su_cntl(rast_info
, builder
->samples
);
498 if (!(pipeline
->dynamic_state
.mask
& TU_DYNAMIC_LINE_WIDTH
))
499 tu6_emit_gras_su_cntl(&rast_cs
, gras_su_cntl
, rast_info
->lineWidth
);
501 if (!(pipeline
->dynamic_state
.mask
& TU_DYNAMIC_DEPTH_BIAS
)) {
502 tu6_emit_depth_bias(&rast_cs
, rast_info
->depthBiasConstantFactor
,
503 rast_info
->depthBiasClamp
,
504 rast_info
->depthBiasSlopeFactor
);
507 pipeline
->rast
.state_ib
= tu_cs_end_sub_stream(&pipeline
->cs
, &rast_cs
);
509 pipeline
->rast
.gras_su_cntl
= gras_su_cntl
;
513 tu_pipeline_builder_parse_depth_stencil(struct tu_pipeline_builder
*builder
,
514 struct tu_pipeline
*pipeline
)
518 * pDepthStencilState is a pointer to an instance of the
519 * VkPipelineDepthStencilStateCreateInfo structure, and is ignored if
520 * the pipeline has rasterization disabled or if the subpass of the
521 * render pass the pipeline is created against does not use a
522 * depth/stencil attachment.
524 * We disable both depth and stenil tests in those cases.
526 static const VkPipelineDepthStencilStateCreateInfo dummy_ds_info
;
527 const VkPipelineDepthStencilStateCreateInfo
*ds_info
=
528 builder
->use_depth_stencil_attachment
529 ? builder
->create_info
->pDepthStencilState
533 tu_cs_begin_sub_stream(builder
->device
, &pipeline
->cs
, 12, &ds_cs
);
535 /* move to hw ctx init? */
536 tu6_emit_alpha_control_disable(&ds_cs
);
538 tu6_emit_depth_control(&ds_cs
, ds_info
);
539 tu6_emit_stencil_control(&ds_cs
, ds_info
);
541 if (!(pipeline
->dynamic_state
.mask
& TU_DYNAMIC_STENCIL_COMPARE_MASK
)) {
542 tu6_emit_stencil_compare_mask(&ds_cs
, ds_info
->front
.compareMask
,
543 ds_info
->back
.compareMask
);
545 if (!(pipeline
->dynamic_state
.mask
& TU_DYNAMIC_STENCIL_WRITE_MASK
)) {
546 tu6_emit_stencil_write_mask(&ds_cs
, ds_info
->front
.writeMask
,
547 ds_info
->back
.writeMask
);
549 if (!(pipeline
->dynamic_state
.mask
& TU_DYNAMIC_STENCIL_REFERENCE
)) {
550 tu6_emit_stencil_reference(&ds_cs
, ds_info
->front
.reference
,
551 ds_info
->back
.reference
);
554 pipeline
->ds
.state_ib
= tu_cs_end_sub_stream(&pipeline
->cs
, &ds_cs
);
558 tu_pipeline_finish(struct tu_pipeline
*pipeline
,
559 struct tu_device
*dev
,
560 const VkAllocationCallbacks
*alloc
)
562 tu_cs_finish(dev
, &pipeline
->cs
);
566 tu_pipeline_builder_build(struct tu_pipeline_builder
*builder
,
567 struct tu_pipeline
**pipeline
)
569 VkResult result
= tu_pipeline_builder_create_pipeline(builder
, pipeline
);
570 if (result
!= VK_SUCCESS
)
573 tu_pipeline_builder_parse_dynamic(builder
, *pipeline
);
574 tu_pipeline_builder_parse_input_assembly(builder
, *pipeline
);
575 tu_pipeline_builder_parse_viewport(builder
, *pipeline
);
576 tu_pipeline_builder_parse_rasterization(builder
, *pipeline
);
577 tu_pipeline_builder_parse_depth_stencil(builder
, *pipeline
);
579 /* we should have reserved enough space upfront such that the CS never
582 assert((*pipeline
)->cs
.bo_count
== 1);
588 tu_pipeline_builder_init_graphics(
589 struct tu_pipeline_builder
*builder
,
590 struct tu_device
*dev
,
591 struct tu_pipeline_cache
*cache
,
592 const VkGraphicsPipelineCreateInfo
*create_info
,
593 const VkAllocationCallbacks
*alloc
)
595 *builder
= (struct tu_pipeline_builder
) {
598 .create_info
= create_info
,
602 builder
->rasterizer_discard
=
603 create_info
->pRasterizationState
->rasterizerDiscardEnable
;
605 if (builder
->rasterizer_discard
) {
606 builder
->samples
= VK_SAMPLE_COUNT_1_BIT
;
608 builder
->samples
= create_info
->pMultisampleState
->rasterizationSamples
;
610 const struct tu_render_pass
*pass
=
611 tu_render_pass_from_handle(create_info
->renderPass
);
612 const struct tu_subpass
*subpass
=
613 &pass
->subpasses
[create_info
->subpass
];
615 builder
->use_depth_stencil_attachment
=
616 subpass
->depth_stencil_attachment
.attachment
!= VK_ATTACHMENT_UNUSED
;
621 tu_CreateGraphicsPipelines(VkDevice device
,
622 VkPipelineCache pipelineCache
,
624 const VkGraphicsPipelineCreateInfo
*pCreateInfos
,
625 const VkAllocationCallbacks
*pAllocator
,
626 VkPipeline
*pPipelines
)
628 TU_FROM_HANDLE(tu_device
, dev
, device
);
629 TU_FROM_HANDLE(tu_pipeline_cache
, cache
, pipelineCache
);
631 for (uint32_t i
= 0; i
< count
; i
++) {
632 struct tu_pipeline_builder builder
;
633 tu_pipeline_builder_init_graphics(&builder
, dev
, cache
,
634 &pCreateInfos
[i
], pAllocator
);
636 struct tu_pipeline
*pipeline
;
637 VkResult result
= tu_pipeline_builder_build(&builder
, &pipeline
);
639 if (result
!= VK_SUCCESS
) {
640 for (uint32_t j
= 0; j
< i
; j
++) {
641 tu_DestroyPipeline(device
, pPipelines
[j
], pAllocator
);
642 pPipelines
[j
] = VK_NULL_HANDLE
;
648 pPipelines
[i
] = tu_pipeline_to_handle(pipeline
);
655 tu_compute_pipeline_create(VkDevice _device
,
656 VkPipelineCache _cache
,
657 const VkComputePipelineCreateInfo
*pCreateInfo
,
658 const VkAllocationCallbacks
*pAllocator
,
659 VkPipeline
*pPipeline
)
665 tu_CreateComputePipelines(VkDevice _device
,
666 VkPipelineCache pipelineCache
,
668 const VkComputePipelineCreateInfo
*pCreateInfos
,
669 const VkAllocationCallbacks
*pAllocator
,
670 VkPipeline
*pPipelines
)
672 VkResult result
= VK_SUCCESS
;
675 for (; i
< count
; i
++) {
677 r
= tu_compute_pipeline_create(_device
, pipelineCache
, &pCreateInfos
[i
],
678 pAllocator
, &pPipelines
[i
]);
679 if (r
!= VK_SUCCESS
) {
681 pPipelines
[i
] = VK_NULL_HANDLE
;
689 tu_DestroyPipeline(VkDevice _device
,
690 VkPipeline _pipeline
,
691 const VkAllocationCallbacks
*pAllocator
)
693 TU_FROM_HANDLE(tu_device
, dev
, _device
);
694 TU_FROM_HANDLE(tu_pipeline
, pipeline
, _pipeline
);
699 tu_pipeline_finish(pipeline
, dev
, pAllocator
);
700 vk_free2(&dev
->alloc
, pAllocator
, pipeline
);