turnip: parse VkPipelineDepthStencilStateCreateInfo
[mesa.git] / src / freedreno / vulkan / tu_pipeline.c
1 /*
2 * Copyright © 2016 Red Hat.
3 * Copyright © 2016 Bas Nieuwenhuizen
4 *
5 * based in part on anv driver which is:
6 * Copyright © 2015 Intel Corporation
7 *
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:
14 *
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
17 * Software.
18 *
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.
26 */
27
28 #include "tu_private.h"
29
30 #include "main/menums.h"
31 #include "nir/nir.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"
38 #include "vk_util.h"
39
40 #include "tu_cs.h"
41
42 struct tu_pipeline_builder
43 {
44 struct tu_device *device;
45 struct tu_pipeline_cache *cache;
46 const VkAllocationCallbacks *alloc;
47 const VkGraphicsPipelineCreateInfo *create_info;
48
49 bool rasterizer_discard;
50 /* these states are affectd by rasterizer_discard */
51 VkSampleCountFlagBits samples;
52 bool use_depth_stencil_attachment;
53 };
54
55 static enum tu_dynamic_state_bits
56 tu_dynamic_state_bit(VkDynamicState state)
57 {
58 switch (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;
77 default:
78 unreachable("invalid dynamic state");
79 return 0;
80 }
81 }
82
83 static enum pc_di_primtype
84 tu6_primtype(VkPrimitiveTopology topology)
85 {
86 switch (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:
94 return DI_PT_TRILIST;
95 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
96 return DI_PT_TRILIST;
97 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
98 return DI_PT_TRIFAN;
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:
108 default:
109 unreachable("invalid primitive topology");
110 return DI_PT_NONE;
111 }
112 }
113
114 static enum adreno_compare_func
115 tu6_compare_func(VkCompareOp op)
116 {
117 switch (op) {
118 case VK_COMPARE_OP_NEVER:
119 return FUNC_NEVER;
120 case VK_COMPARE_OP_LESS:
121 return FUNC_LESS;
122 case VK_COMPARE_OP_EQUAL:
123 return FUNC_EQUAL;
124 case VK_COMPARE_OP_LESS_OR_EQUAL:
125 return FUNC_LEQUAL;
126 case VK_COMPARE_OP_GREATER:
127 return FUNC_GREATER;
128 case VK_COMPARE_OP_NOT_EQUAL:
129 return FUNC_NOTEQUAL;
130 case VK_COMPARE_OP_GREATER_OR_EQUAL:
131 return FUNC_GEQUAL;
132 case VK_COMPARE_OP_ALWAYS:
133 return FUNC_ALWAYS;
134 default:
135 unreachable("invalid VkCompareOp");
136 return FUNC_NEVER;
137 }
138 }
139
140 static enum adreno_stencil_op
141 tu6_stencil_op(VkStencilOp op)
142 {
143 switch (op) {
144 case VK_STENCIL_OP_KEEP:
145 return STENCIL_KEEP;
146 case VK_STENCIL_OP_ZERO:
147 return STENCIL_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;
160 default:
161 unreachable("invalid VkStencilOp");
162 return STENCIL_KEEP;
163 }
164 }
165
166 static uint32_t
167 tu6_guardband_adj(uint32_t v)
168 {
169 if (v > 256)
170 return (uint32_t)(511.0 - 65.0 * (log2(v) - 8.0));
171 else
172 return 511;
173 }
174
175 void
176 tu6_emit_viewport(struct tu_cs *cs, const VkViewport *viewport)
177 {
178 float offsets[3];
179 float scales[3];
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;
186
187 VkOffset2D min;
188 VkOffset2D max;
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);
194 } else {
195 min.y = (int32_t)(viewport->y + viewport->height);
196 max.y = (int32_t) ceilf(viewport->y);
197 }
198 /* the spec allows viewport->height to be 0.0f */
199 if (min.y == max.y)
200 max.y++;
201 assert(min.x >= 0 && min.x < max.x);
202 assert(min.y >= 0 && min.y < max.y);
203
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);
207
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]));
215
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));
221
222 tu_cs_emit_pkt4(cs, REG_A6XX_GRAS_CL_GUARDBAND_CLIP_ADJ, 1);
223 tu_cs_emit(cs,
224 A6XX_GRAS_CL_GUARDBAND_CLIP_ADJ_HORZ(guardband_adj.width) |
225 A6XX_GRAS_CL_GUARDBAND_CLIP_ADJ_VERT(guardband_adj.height));
226 }
227
228 void
229 tu6_emit_scissor(struct tu_cs *cs, const VkRect2D *scissor)
230 {
231 const VkOffset2D min = scissor->offset;
232 const VkOffset2D max = {
233 scissor->offset.x + scissor->extent.width,
234 scissor->offset.y + scissor->extent.height,
235 };
236
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));
242 }
243
244 static void
245 tu6_emit_gras_unknowns(struct tu_cs *cs)
246 {
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);
250 tu_cs_emit(cs, 0x0);
251 tu_cs_emit_pkt4(cs, REG_A6XX_GRAS_UNKNOWN_8004, 1);
252 tu_cs_emit(cs, 0x0);
253 }
254
255 static void
256 tu6_emit_point_size(struct tu_cs *cs)
257 {
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));
262 }
263
264 static uint32_t
265 tu6_gras_su_cntl(const VkPipelineRasterizationStateCreateInfo *rast_info,
266 VkSampleCountFlagBits samples)
267 {
268 uint32_t gras_su_cntl = 0;
269
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;
274
275 if (rast_info->frontFace == VK_FRONT_FACE_CLOCKWISE)
276 gras_su_cntl |= A6XX_GRAS_SU_CNTL_FRONT_CW;
277
278 /* don't set A6XX_GRAS_SU_CNTL_LINEHALFWIDTH */
279
280 if (rast_info->depthBiasEnable)
281 gras_su_cntl |= A6XX_GRAS_SU_CNTL_POLY_OFFSET;
282
283 if (samples > VK_SAMPLE_COUNT_1_BIT)
284 gras_su_cntl |= A6XX_GRAS_SU_CNTL_MSAA_ENABLE;
285
286 return gras_su_cntl;
287 }
288
289 void
290 tu6_emit_gras_su_cntl(struct tu_cs *cs,
291 uint32_t gras_su_cntl,
292 float line_width)
293 {
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);
296
297 tu_cs_emit_pkt4(cs, REG_A6XX_GRAS_SU_CNTL, 1);
298 tu_cs_emit(cs, gras_su_cntl);
299 }
300
301 void
302 tu6_emit_depth_bias(struct tu_cs *cs,
303 float constant_factor,
304 float clamp,
305 float slope_factor)
306 {
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));
311 }
312
313 static void
314 tu6_emit_alpha_control_disable(struct tu_cs *cs)
315 {
316 tu_cs_emit_pkt4(cs, REG_A6XX_RB_ALPHA_CONTROL, 1);
317 tu_cs_emit(cs, 0);
318 }
319
320 static void
321 tu6_emit_depth_control(struct tu_cs *cs,
322 const VkPipelineDepthStencilStateCreateInfo *ds_info)
323 {
324 assert(!ds_info->depthBoundsTestEnable);
325
326 uint32_t rb_depth_cntl = 0;
327 if (ds_info->depthTestEnable) {
328 rb_depth_cntl |=
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;
332
333 if (ds_info->depthWriteEnable)
334 rb_depth_cntl |= A6XX_RB_DEPTH_CNTL_Z_WRITE_ENABLE;
335 }
336
337 tu_cs_emit_pkt4(cs, REG_A6XX_RB_DEPTH_CNTL, 1);
338 tu_cs_emit(cs, rb_depth_cntl);
339 }
340
341 static void
342 tu6_emit_stencil_control(struct tu_cs *cs,
343 const VkPipelineDepthStencilStateCreateInfo *ds_info)
344 {
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));
361 }
362
363 tu_cs_emit_pkt4(cs, REG_A6XX_RB_STENCIL_CONTROL, 1);
364 tu_cs_emit(cs, rb_stencil_control);
365 }
366
367 void
368 tu6_emit_stencil_compare_mask(struct tu_cs *cs, uint32_t front, uint32_t back)
369 {
370 tu_cs_emit_pkt4(cs, REG_A6XX_RB_STENCILMASK, 1);
371 tu_cs_emit(
372 cs, A6XX_RB_STENCILMASK_MASK(front) | A6XX_RB_STENCILMASK_BFMASK(back));
373 }
374
375 void
376 tu6_emit_stencil_write_mask(struct tu_cs *cs, uint32_t front, uint32_t back)
377 {
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));
381 }
382
383 void
384 tu6_emit_stencil_reference(struct tu_cs *cs, uint32_t front, uint32_t back)
385 {
386 tu_cs_emit_pkt4(cs, REG_A6XX_RB_STENCILREF, 1);
387 tu_cs_emit(cs,
388 A6XX_RB_STENCILREF_REF(front) | A6XX_RB_STENCILREF_BFREF(back));
389 }
390
391 static VkResult
392 tu_pipeline_builder_create_pipeline(struct tu_pipeline_builder *builder,
393 struct tu_pipeline **out_pipeline)
394 {
395 struct tu_device *dev = builder->device;
396
397 struct tu_pipeline *pipeline =
398 vk_zalloc2(&dev->alloc, builder->alloc, sizeof(*pipeline), 8,
399 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
400 if (!pipeline)
401 return VK_ERROR_OUT_OF_HOST_MEMORY;
402
403 tu_cs_init(&pipeline->cs, TU_CS_MODE_SUB_STREAM, 2048);
404
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);
409 return result;
410 }
411
412 *out_pipeline = pipeline;
413
414 return VK_SUCCESS;
415 }
416
417 static void
418 tu_pipeline_builder_parse_dynamic(struct tu_pipeline_builder *builder,
419 struct tu_pipeline *pipeline)
420 {
421 const VkPipelineDynamicStateCreateInfo *dynamic_info =
422 builder->create_info->pDynamicState;
423
424 if (!dynamic_info)
425 return;
426
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]);
430 }
431 }
432
433 static void
434 tu_pipeline_builder_parse_input_assembly(struct tu_pipeline_builder *builder,
435 struct tu_pipeline *pipeline)
436 {
437 const VkPipelineInputAssemblyStateCreateInfo *ia_info =
438 builder->create_info->pInputAssemblyState;
439
440 pipeline->ia.primtype = tu6_primtype(ia_info->topology);
441 pipeline->ia.primitive_restart = ia_info->primitiveRestartEnable;
442 }
443
444 static void
445 tu_pipeline_builder_parse_viewport(struct tu_pipeline_builder *builder,
446 struct tu_pipeline *pipeline)
447 {
448 /* The spec says:
449 *
450 * pViewportState is a pointer to an instance of the
451 * VkPipelineViewportStateCreateInfo structure, and is ignored if the
452 * pipeline has rasterization disabled."
453 *
454 * We leave the relevant registers stale in that case.
455 */
456 if (builder->rasterizer_discard)
457 return;
458
459 const VkPipelineViewportStateCreateInfo *vp_info =
460 builder->create_info->pViewportState;
461
462 struct tu_cs vp_cs;
463 tu_cs_begin_sub_stream(builder->device, &pipeline->cs, 15, &vp_cs);
464
465 if (!(pipeline->dynamic_state.mask & TU_DYNAMIC_VIEWPORT)) {
466 assert(vp_info->viewportCount == 1);
467 tu6_emit_viewport(&vp_cs, vp_info->pViewports);
468 }
469
470 if (!(pipeline->dynamic_state.mask & TU_DYNAMIC_SCISSOR)) {
471 assert(vp_info->scissorCount == 1);
472 tu6_emit_scissor(&vp_cs, vp_info->pScissors);
473 }
474
475 pipeline->vp.state_ib = tu_cs_end_sub_stream(&pipeline->cs, &vp_cs);
476 }
477
478 static void
479 tu_pipeline_builder_parse_rasterization(struct tu_pipeline_builder *builder,
480 struct tu_pipeline *pipeline)
481 {
482 const VkPipelineRasterizationStateCreateInfo *rast_info =
483 builder->create_info->pRasterizationState;
484
485 assert(!rast_info->depthClampEnable);
486 assert(rast_info->polygonMode == VK_POLYGON_MODE_FILL);
487
488 struct tu_cs rast_cs;
489 tu_cs_begin_sub_stream(builder->device, &pipeline->cs, 20, &rast_cs);
490
491 /* move to hw ctx init? */
492 tu6_emit_gras_unknowns(&rast_cs);
493 tu6_emit_point_size(&rast_cs);
494
495 const uint32_t gras_su_cntl =
496 tu6_gras_su_cntl(rast_info, builder->samples);
497
498 if (!(pipeline->dynamic_state.mask & TU_DYNAMIC_LINE_WIDTH))
499 tu6_emit_gras_su_cntl(&rast_cs, gras_su_cntl, rast_info->lineWidth);
500
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);
505 }
506
507 pipeline->rast.state_ib = tu_cs_end_sub_stream(&pipeline->cs, &rast_cs);
508
509 pipeline->rast.gras_su_cntl = gras_su_cntl;
510 }
511
512 static void
513 tu_pipeline_builder_parse_depth_stencil(struct tu_pipeline_builder *builder,
514 struct tu_pipeline *pipeline)
515 {
516 /* The spec says:
517 *
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.
523 *
524 * We disable both depth and stenil tests in those cases.
525 */
526 static const VkPipelineDepthStencilStateCreateInfo dummy_ds_info;
527 const VkPipelineDepthStencilStateCreateInfo *ds_info =
528 builder->use_depth_stencil_attachment
529 ? builder->create_info->pDepthStencilState
530 : &dummy_ds_info;
531
532 struct tu_cs ds_cs;
533 tu_cs_begin_sub_stream(builder->device, &pipeline->cs, 12, &ds_cs);
534
535 /* move to hw ctx init? */
536 tu6_emit_alpha_control_disable(&ds_cs);
537
538 tu6_emit_depth_control(&ds_cs, ds_info);
539 tu6_emit_stencil_control(&ds_cs, ds_info);
540
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);
544 }
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);
548 }
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);
552 }
553
554 pipeline->ds.state_ib = tu_cs_end_sub_stream(&pipeline->cs, &ds_cs);
555 }
556
557 static void
558 tu_pipeline_finish(struct tu_pipeline *pipeline,
559 struct tu_device *dev,
560 const VkAllocationCallbacks *alloc)
561 {
562 tu_cs_finish(dev, &pipeline->cs);
563 }
564
565 static VkResult
566 tu_pipeline_builder_build(struct tu_pipeline_builder *builder,
567 struct tu_pipeline **pipeline)
568 {
569 VkResult result = tu_pipeline_builder_create_pipeline(builder, pipeline);
570 if (result != VK_SUCCESS)
571 return result;
572
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);
578
579 /* we should have reserved enough space upfront such that the CS never
580 * grows
581 */
582 assert((*pipeline)->cs.bo_count == 1);
583
584 return VK_SUCCESS;
585 }
586
587 static void
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)
594 {
595 *builder = (struct tu_pipeline_builder) {
596 .device = dev,
597 .cache = cache,
598 .create_info = create_info,
599 .alloc = alloc,
600 };
601
602 builder->rasterizer_discard =
603 create_info->pRasterizationState->rasterizerDiscardEnable;
604
605 if (builder->rasterizer_discard) {
606 builder->samples = VK_SAMPLE_COUNT_1_BIT;
607 } else {
608 builder->samples = create_info->pMultisampleState->rasterizationSamples;
609
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];
614
615 builder->use_depth_stencil_attachment =
616 subpass->depth_stencil_attachment.attachment != VK_ATTACHMENT_UNUSED;
617 }
618 }
619
620 VkResult
621 tu_CreateGraphicsPipelines(VkDevice device,
622 VkPipelineCache pipelineCache,
623 uint32_t count,
624 const VkGraphicsPipelineCreateInfo *pCreateInfos,
625 const VkAllocationCallbacks *pAllocator,
626 VkPipeline *pPipelines)
627 {
628 TU_FROM_HANDLE(tu_device, dev, device);
629 TU_FROM_HANDLE(tu_pipeline_cache, cache, pipelineCache);
630
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);
635
636 struct tu_pipeline *pipeline;
637 VkResult result = tu_pipeline_builder_build(&builder, &pipeline);
638
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;
643 }
644
645 return result;
646 }
647
648 pPipelines[i] = tu_pipeline_to_handle(pipeline);
649 }
650
651 return VK_SUCCESS;
652 }
653
654 static VkResult
655 tu_compute_pipeline_create(VkDevice _device,
656 VkPipelineCache _cache,
657 const VkComputePipelineCreateInfo *pCreateInfo,
658 const VkAllocationCallbacks *pAllocator,
659 VkPipeline *pPipeline)
660 {
661 return VK_SUCCESS;
662 }
663
664 VkResult
665 tu_CreateComputePipelines(VkDevice _device,
666 VkPipelineCache pipelineCache,
667 uint32_t count,
668 const VkComputePipelineCreateInfo *pCreateInfos,
669 const VkAllocationCallbacks *pAllocator,
670 VkPipeline *pPipelines)
671 {
672 VkResult result = VK_SUCCESS;
673
674 unsigned i = 0;
675 for (; i < count; i++) {
676 VkResult r;
677 r = tu_compute_pipeline_create(_device, pipelineCache, &pCreateInfos[i],
678 pAllocator, &pPipelines[i]);
679 if (r != VK_SUCCESS) {
680 result = r;
681 pPipelines[i] = VK_NULL_HANDLE;
682 }
683 }
684
685 return result;
686 }
687
688 void
689 tu_DestroyPipeline(VkDevice _device,
690 VkPipeline _pipeline,
691 const VkAllocationCallbacks *pAllocator)
692 {
693 TU_FROM_HANDLE(tu_device, dev, _device);
694 TU_FROM_HANDLE(tu_pipeline, pipeline, _pipeline);
695
696 if (!_pipeline)
697 return;
698
699 tu_pipeline_finish(pipeline, dev, pAllocator);
700 vk_free2(&dev->alloc, pAllocator, pipeline);
701 }