turnip: compile VkPipelineShaderStageCreateInfo
[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 struct tu_shader *shaders[MESA_SHADER_STAGES];
50 uint32_t shader_offsets[MESA_SHADER_STAGES];
51 uint32_t binning_vs_offset;
52 uint32_t shader_total_size;
53
54 bool rasterizer_discard;
55 /* these states are affectd by rasterizer_discard */
56 VkSampleCountFlagBits samples;
57 bool use_depth_stencil_attachment;
58 bool use_color_attachments;
59 VkFormat color_attachment_formats[MAX_RTS];
60 };
61
62 static enum tu_dynamic_state_bits
63 tu_dynamic_state_bit(VkDynamicState state)
64 {
65 switch (state) {
66 case VK_DYNAMIC_STATE_VIEWPORT:
67 return TU_DYNAMIC_VIEWPORT;
68 case VK_DYNAMIC_STATE_SCISSOR:
69 return TU_DYNAMIC_SCISSOR;
70 case VK_DYNAMIC_STATE_LINE_WIDTH:
71 return TU_DYNAMIC_LINE_WIDTH;
72 case VK_DYNAMIC_STATE_DEPTH_BIAS:
73 return TU_DYNAMIC_DEPTH_BIAS;
74 case VK_DYNAMIC_STATE_BLEND_CONSTANTS:
75 return TU_DYNAMIC_BLEND_CONSTANTS;
76 case VK_DYNAMIC_STATE_DEPTH_BOUNDS:
77 return TU_DYNAMIC_DEPTH_BOUNDS;
78 case VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK:
79 return TU_DYNAMIC_STENCIL_COMPARE_MASK;
80 case VK_DYNAMIC_STATE_STENCIL_WRITE_MASK:
81 return TU_DYNAMIC_STENCIL_WRITE_MASK;
82 case VK_DYNAMIC_STATE_STENCIL_REFERENCE:
83 return TU_DYNAMIC_STENCIL_REFERENCE;
84 default:
85 unreachable("invalid dynamic state");
86 return 0;
87 }
88 }
89
90 static gl_shader_stage
91 tu_shader_stage(VkShaderStageFlagBits stage)
92 {
93 switch (stage) {
94 case VK_SHADER_STAGE_VERTEX_BIT:
95 return MESA_SHADER_VERTEX;
96 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
97 return MESA_SHADER_TESS_CTRL;
98 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
99 return MESA_SHADER_TESS_EVAL;
100 case VK_SHADER_STAGE_GEOMETRY_BIT:
101 return MESA_SHADER_GEOMETRY;
102 case VK_SHADER_STAGE_FRAGMENT_BIT:
103 return MESA_SHADER_FRAGMENT;
104 case VK_SHADER_STAGE_COMPUTE_BIT:
105 return MESA_SHADER_COMPUTE;
106 default:
107 unreachable("invalid VkShaderStageFlagBits");
108 return MESA_SHADER_NONE;
109 }
110 }
111
112 static bool
113 tu_logic_op_reads_dst(VkLogicOp op)
114 {
115 switch (op) {
116 case VK_LOGIC_OP_CLEAR:
117 case VK_LOGIC_OP_COPY:
118 case VK_LOGIC_OP_COPY_INVERTED:
119 case VK_LOGIC_OP_SET:
120 return false;
121 default:
122 return true;
123 }
124 }
125
126 static VkBlendFactor
127 tu_blend_factor_no_dst_alpha(VkBlendFactor factor)
128 {
129 /* treat dst alpha as 1.0 and avoid reading it */
130 switch (factor) {
131 case VK_BLEND_FACTOR_DST_ALPHA:
132 return VK_BLEND_FACTOR_ONE;
133 case VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA:
134 return VK_BLEND_FACTOR_ZERO;
135 default:
136 return factor;
137 }
138 }
139
140 static enum pc_di_primtype
141 tu6_primtype(VkPrimitiveTopology topology)
142 {
143 switch (topology) {
144 case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
145 return DI_PT_POINTLIST;
146 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
147 return DI_PT_LINELIST;
148 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
149 return DI_PT_LINESTRIP;
150 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
151 return DI_PT_TRILIST;
152 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
153 return DI_PT_TRILIST;
154 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
155 return DI_PT_TRIFAN;
156 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
157 return DI_PT_LINE_ADJ;
158 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
159 return DI_PT_LINESTRIP_ADJ;
160 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
161 return DI_PT_TRI_ADJ;
162 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
163 return DI_PT_TRISTRIP_ADJ;
164 case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST:
165 default:
166 unreachable("invalid primitive topology");
167 return DI_PT_NONE;
168 }
169 }
170
171 static enum adreno_compare_func
172 tu6_compare_func(VkCompareOp op)
173 {
174 switch (op) {
175 case VK_COMPARE_OP_NEVER:
176 return FUNC_NEVER;
177 case VK_COMPARE_OP_LESS:
178 return FUNC_LESS;
179 case VK_COMPARE_OP_EQUAL:
180 return FUNC_EQUAL;
181 case VK_COMPARE_OP_LESS_OR_EQUAL:
182 return FUNC_LEQUAL;
183 case VK_COMPARE_OP_GREATER:
184 return FUNC_GREATER;
185 case VK_COMPARE_OP_NOT_EQUAL:
186 return FUNC_NOTEQUAL;
187 case VK_COMPARE_OP_GREATER_OR_EQUAL:
188 return FUNC_GEQUAL;
189 case VK_COMPARE_OP_ALWAYS:
190 return FUNC_ALWAYS;
191 default:
192 unreachable("invalid VkCompareOp");
193 return FUNC_NEVER;
194 }
195 }
196
197 static enum adreno_stencil_op
198 tu6_stencil_op(VkStencilOp op)
199 {
200 switch (op) {
201 case VK_STENCIL_OP_KEEP:
202 return STENCIL_KEEP;
203 case VK_STENCIL_OP_ZERO:
204 return STENCIL_ZERO;
205 case VK_STENCIL_OP_REPLACE:
206 return STENCIL_REPLACE;
207 case VK_STENCIL_OP_INCREMENT_AND_CLAMP:
208 return STENCIL_INCR_CLAMP;
209 case VK_STENCIL_OP_DECREMENT_AND_CLAMP:
210 return STENCIL_DECR_CLAMP;
211 case VK_STENCIL_OP_INVERT:
212 return STENCIL_INVERT;
213 case VK_STENCIL_OP_INCREMENT_AND_WRAP:
214 return STENCIL_INCR_WRAP;
215 case VK_STENCIL_OP_DECREMENT_AND_WRAP:
216 return STENCIL_DECR_WRAP;
217 default:
218 unreachable("invalid VkStencilOp");
219 return STENCIL_KEEP;
220 }
221 }
222
223 static enum a3xx_rop_code
224 tu6_rop(VkLogicOp op)
225 {
226 switch (op) {
227 case VK_LOGIC_OP_CLEAR:
228 return ROP_CLEAR;
229 case VK_LOGIC_OP_AND:
230 return ROP_AND;
231 case VK_LOGIC_OP_AND_REVERSE:
232 return ROP_AND_REVERSE;
233 case VK_LOGIC_OP_COPY:
234 return ROP_COPY;
235 case VK_LOGIC_OP_AND_INVERTED:
236 return ROP_AND_INVERTED;
237 case VK_LOGIC_OP_NO_OP:
238 return ROP_NOOP;
239 case VK_LOGIC_OP_XOR:
240 return ROP_XOR;
241 case VK_LOGIC_OP_OR:
242 return ROP_OR;
243 case VK_LOGIC_OP_NOR:
244 return ROP_NOR;
245 case VK_LOGIC_OP_EQUIVALENT:
246 return ROP_EQUIV;
247 case VK_LOGIC_OP_INVERT:
248 return ROP_INVERT;
249 case VK_LOGIC_OP_OR_REVERSE:
250 return ROP_OR_REVERSE;
251 case VK_LOGIC_OP_COPY_INVERTED:
252 return ROP_COPY_INVERTED;
253 case VK_LOGIC_OP_OR_INVERTED:
254 return ROP_OR_INVERTED;
255 case VK_LOGIC_OP_NAND:
256 return ROP_NAND;
257 case VK_LOGIC_OP_SET:
258 return ROP_SET;
259 default:
260 unreachable("invalid VkLogicOp");
261 return ROP_NOOP;
262 }
263 }
264
265 static enum adreno_rb_blend_factor
266 tu6_blend_factor(VkBlendFactor factor)
267 {
268 switch (factor) {
269 case VK_BLEND_FACTOR_ZERO:
270 return FACTOR_ZERO;
271 case VK_BLEND_FACTOR_ONE:
272 return FACTOR_ONE;
273 case VK_BLEND_FACTOR_SRC_COLOR:
274 return FACTOR_SRC_COLOR;
275 case VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR:
276 return FACTOR_ONE_MINUS_SRC_COLOR;
277 case VK_BLEND_FACTOR_DST_COLOR:
278 return FACTOR_DST_COLOR;
279 case VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR:
280 return FACTOR_ONE_MINUS_DST_COLOR;
281 case VK_BLEND_FACTOR_SRC_ALPHA:
282 return FACTOR_SRC_ALPHA;
283 case VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA:
284 return FACTOR_ONE_MINUS_SRC_ALPHA;
285 case VK_BLEND_FACTOR_DST_ALPHA:
286 return FACTOR_DST_ALPHA;
287 case VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA:
288 return FACTOR_ONE_MINUS_DST_ALPHA;
289 case VK_BLEND_FACTOR_CONSTANT_COLOR:
290 return FACTOR_CONSTANT_COLOR;
291 case VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR:
292 return FACTOR_ONE_MINUS_CONSTANT_COLOR;
293 case VK_BLEND_FACTOR_CONSTANT_ALPHA:
294 return FACTOR_CONSTANT_ALPHA;
295 case VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA:
296 return FACTOR_ONE_MINUS_CONSTANT_ALPHA;
297 case VK_BLEND_FACTOR_SRC_ALPHA_SATURATE:
298 return FACTOR_SRC_ALPHA_SATURATE;
299 case VK_BLEND_FACTOR_SRC1_COLOR:
300 return FACTOR_SRC1_COLOR;
301 case VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR:
302 return FACTOR_ONE_MINUS_SRC1_COLOR;
303 case VK_BLEND_FACTOR_SRC1_ALPHA:
304 return FACTOR_SRC1_ALPHA;
305 case VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA:
306 return FACTOR_ONE_MINUS_SRC1_ALPHA;
307 default:
308 unreachable("invalid VkBlendFactor");
309 return FACTOR_ZERO;
310 }
311 }
312
313 static enum a3xx_rb_blend_opcode
314 tu6_blend_op(VkBlendOp op)
315 {
316 switch (op) {
317 case VK_BLEND_OP_ADD:
318 return BLEND_DST_PLUS_SRC;
319 case VK_BLEND_OP_SUBTRACT:
320 return BLEND_SRC_MINUS_DST;
321 case VK_BLEND_OP_REVERSE_SUBTRACT:
322 return BLEND_DST_MINUS_SRC;
323 case VK_BLEND_OP_MIN:
324 return BLEND_MIN_DST_SRC;
325 case VK_BLEND_OP_MAX:
326 return BLEND_MAX_DST_SRC;
327 default:
328 unreachable("invalid VkBlendOp");
329 return BLEND_DST_PLUS_SRC;
330 }
331 }
332
333 static uint32_t
334 tu6_guardband_adj(uint32_t v)
335 {
336 if (v > 256)
337 return (uint32_t)(511.0 - 65.0 * (log2(v) - 8.0));
338 else
339 return 511;
340 }
341
342 void
343 tu6_emit_viewport(struct tu_cs *cs, const VkViewport *viewport)
344 {
345 float offsets[3];
346 float scales[3];
347 scales[0] = viewport->width / 2.0f;
348 scales[1] = viewport->height / 2.0f;
349 scales[2] = viewport->maxDepth - viewport->minDepth;
350 offsets[0] = viewport->x + scales[0];
351 offsets[1] = viewport->y + scales[1];
352 offsets[2] = viewport->minDepth;
353
354 VkOffset2D min;
355 VkOffset2D max;
356 min.x = (int32_t) viewport->x;
357 max.x = (int32_t) ceilf(viewport->x + viewport->width);
358 if (viewport->height >= 0.0f) {
359 min.y = (int32_t) viewport->y;
360 max.y = (int32_t) ceilf(viewport->y + viewport->height);
361 } else {
362 min.y = (int32_t)(viewport->y + viewport->height);
363 max.y = (int32_t) ceilf(viewport->y);
364 }
365 /* the spec allows viewport->height to be 0.0f */
366 if (min.y == max.y)
367 max.y++;
368 assert(min.x >= 0 && min.x < max.x);
369 assert(min.y >= 0 && min.y < max.y);
370
371 VkExtent2D guardband_adj;
372 guardband_adj.width = tu6_guardband_adj(max.x - min.x);
373 guardband_adj.height = tu6_guardband_adj(max.y - min.y);
374
375 tu_cs_emit_pkt4(cs, REG_A6XX_GRAS_CL_VPORT_XOFFSET_0, 6);
376 tu_cs_emit(cs, A6XX_GRAS_CL_VPORT_XOFFSET_0(offsets[0]));
377 tu_cs_emit(cs, A6XX_GRAS_CL_VPORT_XSCALE_0(scales[0]));
378 tu_cs_emit(cs, A6XX_GRAS_CL_VPORT_YOFFSET_0(offsets[1]));
379 tu_cs_emit(cs, A6XX_GRAS_CL_VPORT_YSCALE_0(scales[1]));
380 tu_cs_emit(cs, A6XX_GRAS_CL_VPORT_ZOFFSET_0(offsets[2]));
381 tu_cs_emit(cs, A6XX_GRAS_CL_VPORT_ZSCALE_0(scales[2]));
382
383 tu_cs_emit_pkt4(cs, REG_A6XX_GRAS_SC_VIEWPORT_SCISSOR_TL_0, 2);
384 tu_cs_emit(cs, A6XX_GRAS_SC_VIEWPORT_SCISSOR_TL_0_X(min.x) |
385 A6XX_GRAS_SC_VIEWPORT_SCISSOR_TL_0_Y(min.y));
386 tu_cs_emit(cs, A6XX_GRAS_SC_VIEWPORT_SCISSOR_TL_0_X(max.x - 1) |
387 A6XX_GRAS_SC_VIEWPORT_SCISSOR_TL_0_Y(max.y - 1));
388
389 tu_cs_emit_pkt4(cs, REG_A6XX_GRAS_CL_GUARDBAND_CLIP_ADJ, 1);
390 tu_cs_emit(cs,
391 A6XX_GRAS_CL_GUARDBAND_CLIP_ADJ_HORZ(guardband_adj.width) |
392 A6XX_GRAS_CL_GUARDBAND_CLIP_ADJ_VERT(guardband_adj.height));
393 }
394
395 void
396 tu6_emit_scissor(struct tu_cs *cs, const VkRect2D *scissor)
397 {
398 const VkOffset2D min = scissor->offset;
399 const VkOffset2D max = {
400 scissor->offset.x + scissor->extent.width,
401 scissor->offset.y + scissor->extent.height,
402 };
403
404 tu_cs_emit_pkt4(cs, REG_A6XX_GRAS_SC_SCREEN_SCISSOR_TL_0, 2);
405 tu_cs_emit(cs, A6XX_GRAS_SC_SCREEN_SCISSOR_TL_0_X(min.x) |
406 A6XX_GRAS_SC_SCREEN_SCISSOR_TL_0_Y(min.y));
407 tu_cs_emit(cs, A6XX_GRAS_SC_SCREEN_SCISSOR_TL_0_X(max.x - 1) |
408 A6XX_GRAS_SC_SCREEN_SCISSOR_TL_0_Y(max.y - 1));
409 }
410
411 static void
412 tu6_emit_gras_unknowns(struct tu_cs *cs)
413 {
414 tu_cs_emit_pkt4(cs, REG_A6XX_GRAS_UNKNOWN_8000, 1);
415 tu_cs_emit(cs, 0x80);
416 tu_cs_emit_pkt4(cs, REG_A6XX_GRAS_UNKNOWN_8001, 1);
417 tu_cs_emit(cs, 0x0);
418 tu_cs_emit_pkt4(cs, REG_A6XX_GRAS_UNKNOWN_8004, 1);
419 tu_cs_emit(cs, 0x0);
420 }
421
422 static void
423 tu6_emit_point_size(struct tu_cs *cs)
424 {
425 tu_cs_emit_pkt4(cs, REG_A6XX_GRAS_SU_POINT_MINMAX, 2);
426 tu_cs_emit(cs, A6XX_GRAS_SU_POINT_MINMAX_MIN(1.0f / 16.0f) |
427 A6XX_GRAS_SU_POINT_MINMAX_MAX(4092.0f));
428 tu_cs_emit(cs, A6XX_GRAS_SU_POINT_SIZE(1.0f));
429 }
430
431 static uint32_t
432 tu6_gras_su_cntl(const VkPipelineRasterizationStateCreateInfo *rast_info,
433 VkSampleCountFlagBits samples)
434 {
435 uint32_t gras_su_cntl = 0;
436
437 if (rast_info->cullMode & VK_CULL_MODE_FRONT_BIT)
438 gras_su_cntl |= A6XX_GRAS_SU_CNTL_CULL_FRONT;
439 if (rast_info->cullMode & VK_CULL_MODE_BACK_BIT)
440 gras_su_cntl |= A6XX_GRAS_SU_CNTL_CULL_BACK;
441
442 if (rast_info->frontFace == VK_FRONT_FACE_CLOCKWISE)
443 gras_su_cntl |= A6XX_GRAS_SU_CNTL_FRONT_CW;
444
445 /* don't set A6XX_GRAS_SU_CNTL_LINEHALFWIDTH */
446
447 if (rast_info->depthBiasEnable)
448 gras_su_cntl |= A6XX_GRAS_SU_CNTL_POLY_OFFSET;
449
450 if (samples > VK_SAMPLE_COUNT_1_BIT)
451 gras_su_cntl |= A6XX_GRAS_SU_CNTL_MSAA_ENABLE;
452
453 return gras_su_cntl;
454 }
455
456 void
457 tu6_emit_gras_su_cntl(struct tu_cs *cs,
458 uint32_t gras_su_cntl,
459 float line_width)
460 {
461 assert((gras_su_cntl & A6XX_GRAS_SU_CNTL_LINEHALFWIDTH__MASK) == 0);
462 gras_su_cntl |= A6XX_GRAS_SU_CNTL_LINEHALFWIDTH(line_width / 2.0f);
463
464 tu_cs_emit_pkt4(cs, REG_A6XX_GRAS_SU_CNTL, 1);
465 tu_cs_emit(cs, gras_su_cntl);
466 }
467
468 void
469 tu6_emit_depth_bias(struct tu_cs *cs,
470 float constant_factor,
471 float clamp,
472 float slope_factor)
473 {
474 tu_cs_emit_pkt4(cs, REG_A6XX_GRAS_SU_POLY_OFFSET_SCALE, 3);
475 tu_cs_emit(cs, A6XX_GRAS_SU_POLY_OFFSET_SCALE(slope_factor));
476 tu_cs_emit(cs, A6XX_GRAS_SU_POLY_OFFSET_OFFSET(constant_factor));
477 tu_cs_emit(cs, A6XX_GRAS_SU_POLY_OFFSET_OFFSET_CLAMP(clamp));
478 }
479
480 static void
481 tu6_emit_alpha_control_disable(struct tu_cs *cs)
482 {
483 tu_cs_emit_pkt4(cs, REG_A6XX_RB_ALPHA_CONTROL, 1);
484 tu_cs_emit(cs, 0);
485 }
486
487 static void
488 tu6_emit_depth_control(struct tu_cs *cs,
489 const VkPipelineDepthStencilStateCreateInfo *ds_info)
490 {
491 assert(!ds_info->depthBoundsTestEnable);
492
493 uint32_t rb_depth_cntl = 0;
494 if (ds_info->depthTestEnable) {
495 rb_depth_cntl |=
496 A6XX_RB_DEPTH_CNTL_Z_ENABLE |
497 A6XX_RB_DEPTH_CNTL_ZFUNC(tu6_compare_func(ds_info->depthCompareOp)) |
498 A6XX_RB_DEPTH_CNTL_Z_TEST_ENABLE;
499
500 if (ds_info->depthWriteEnable)
501 rb_depth_cntl |= A6XX_RB_DEPTH_CNTL_Z_WRITE_ENABLE;
502 }
503
504 tu_cs_emit_pkt4(cs, REG_A6XX_RB_DEPTH_CNTL, 1);
505 tu_cs_emit(cs, rb_depth_cntl);
506 }
507
508 static void
509 tu6_emit_stencil_control(struct tu_cs *cs,
510 const VkPipelineDepthStencilStateCreateInfo *ds_info)
511 {
512 uint32_t rb_stencil_control = 0;
513 if (ds_info->stencilTestEnable) {
514 const VkStencilOpState *front = &ds_info->front;
515 const VkStencilOpState *back = &ds_info->back;
516 rb_stencil_control |=
517 A6XX_RB_STENCIL_CONTROL_STENCIL_ENABLE |
518 A6XX_RB_STENCIL_CONTROL_STENCIL_ENABLE_BF |
519 A6XX_RB_STENCIL_CONTROL_STENCIL_READ |
520 A6XX_RB_STENCIL_CONTROL_FUNC(tu6_compare_func(front->compareOp)) |
521 A6XX_RB_STENCIL_CONTROL_FAIL(tu6_stencil_op(front->failOp)) |
522 A6XX_RB_STENCIL_CONTROL_ZPASS(tu6_stencil_op(front->passOp)) |
523 A6XX_RB_STENCIL_CONTROL_ZFAIL(tu6_stencil_op(front->depthFailOp)) |
524 A6XX_RB_STENCIL_CONTROL_FUNC_BF(tu6_compare_func(back->compareOp)) |
525 A6XX_RB_STENCIL_CONTROL_FAIL_BF(tu6_stencil_op(back->failOp)) |
526 A6XX_RB_STENCIL_CONTROL_ZPASS_BF(tu6_stencil_op(back->passOp)) |
527 A6XX_RB_STENCIL_CONTROL_ZFAIL_BF(tu6_stencil_op(back->depthFailOp));
528 }
529
530 tu_cs_emit_pkt4(cs, REG_A6XX_RB_STENCIL_CONTROL, 1);
531 tu_cs_emit(cs, rb_stencil_control);
532 }
533
534 void
535 tu6_emit_stencil_compare_mask(struct tu_cs *cs, uint32_t front, uint32_t back)
536 {
537 tu_cs_emit_pkt4(cs, REG_A6XX_RB_STENCILMASK, 1);
538 tu_cs_emit(
539 cs, A6XX_RB_STENCILMASK_MASK(front) | A6XX_RB_STENCILMASK_BFMASK(back));
540 }
541
542 void
543 tu6_emit_stencil_write_mask(struct tu_cs *cs, uint32_t front, uint32_t back)
544 {
545 tu_cs_emit_pkt4(cs, REG_A6XX_RB_STENCILWRMASK, 1);
546 tu_cs_emit(cs, A6XX_RB_STENCILWRMASK_WRMASK(front) |
547 A6XX_RB_STENCILWRMASK_BFWRMASK(back));
548 }
549
550 void
551 tu6_emit_stencil_reference(struct tu_cs *cs, uint32_t front, uint32_t back)
552 {
553 tu_cs_emit_pkt4(cs, REG_A6XX_RB_STENCILREF, 1);
554 tu_cs_emit(cs,
555 A6XX_RB_STENCILREF_REF(front) | A6XX_RB_STENCILREF_BFREF(back));
556 }
557
558 static uint32_t
559 tu6_rb_mrt_blend_control(const VkPipelineColorBlendAttachmentState *att,
560 bool has_alpha)
561 {
562 const enum a3xx_rb_blend_opcode color_op = tu6_blend_op(att->colorBlendOp);
563 const enum adreno_rb_blend_factor src_color_factor = tu6_blend_factor(
564 has_alpha ? att->srcColorBlendFactor
565 : tu_blend_factor_no_dst_alpha(att->srcColorBlendFactor));
566 const enum adreno_rb_blend_factor dst_color_factor = tu6_blend_factor(
567 has_alpha ? att->dstColorBlendFactor
568 : tu_blend_factor_no_dst_alpha(att->dstColorBlendFactor));
569 const enum a3xx_rb_blend_opcode alpha_op = tu6_blend_op(att->alphaBlendOp);
570 const enum adreno_rb_blend_factor src_alpha_factor =
571 tu6_blend_factor(att->srcAlphaBlendFactor);
572 const enum adreno_rb_blend_factor dst_alpha_factor =
573 tu6_blend_factor(att->dstAlphaBlendFactor);
574
575 return A6XX_RB_MRT_BLEND_CONTROL_RGB_SRC_FACTOR(src_color_factor) |
576 A6XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE(color_op) |
577 A6XX_RB_MRT_BLEND_CONTROL_RGB_DEST_FACTOR(dst_color_factor) |
578 A6XX_RB_MRT_BLEND_CONTROL_ALPHA_SRC_FACTOR(src_alpha_factor) |
579 A6XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE(alpha_op) |
580 A6XX_RB_MRT_BLEND_CONTROL_ALPHA_DEST_FACTOR(dst_alpha_factor);
581 }
582
583 static uint32_t
584 tu6_rb_mrt_control(const VkPipelineColorBlendAttachmentState *att,
585 uint32_t rb_mrt_control_rop,
586 bool is_int,
587 bool has_alpha)
588 {
589 uint32_t rb_mrt_control =
590 A6XX_RB_MRT_CONTROL_COMPONENT_ENABLE(att->colorWriteMask);
591
592 /* ignore blending and logic op for integer attachments */
593 if (is_int) {
594 rb_mrt_control |= A6XX_RB_MRT_CONTROL_ROP_CODE(ROP_COPY);
595 return rb_mrt_control;
596 }
597
598 rb_mrt_control |= rb_mrt_control_rop;
599
600 if (att->blendEnable) {
601 rb_mrt_control |= A6XX_RB_MRT_CONTROL_BLEND;
602
603 if (has_alpha)
604 rb_mrt_control |= A6XX_RB_MRT_CONTROL_BLEND2;
605 }
606
607 return rb_mrt_control;
608 }
609
610 static void
611 tu6_emit_rb_mrt_controls(struct tu_cs *cs,
612 const VkPipelineColorBlendStateCreateInfo *blend_info,
613 const VkFormat attachment_formats[MAX_RTS],
614 uint32_t *blend_enable_mask)
615 {
616 *blend_enable_mask = 0;
617
618 bool rop_reads_dst = false;
619 uint32_t rb_mrt_control_rop = 0;
620 if (blend_info->logicOpEnable) {
621 rop_reads_dst = tu_logic_op_reads_dst(blend_info->logicOp);
622 rb_mrt_control_rop =
623 A6XX_RB_MRT_CONTROL_ROP_ENABLE |
624 A6XX_RB_MRT_CONTROL_ROP_CODE(tu6_rop(blend_info->logicOp));
625 }
626
627 for (uint32_t i = 0; i < blend_info->attachmentCount; i++) {
628 const VkPipelineColorBlendAttachmentState *att =
629 &blend_info->pAttachments[i];
630 const VkFormat format = attachment_formats[i];
631
632 uint32_t rb_mrt_control = 0;
633 uint32_t rb_mrt_blend_control = 0;
634 if (format != VK_FORMAT_UNDEFINED) {
635 const bool is_int = vk_format_is_int(format);
636 const bool has_alpha = vk_format_has_alpha(format);
637
638 rb_mrt_control =
639 tu6_rb_mrt_control(att, rb_mrt_control_rop, is_int, has_alpha);
640 rb_mrt_blend_control = tu6_rb_mrt_blend_control(att, has_alpha);
641
642 if (att->blendEnable || rop_reads_dst)
643 *blend_enable_mask |= 1 << i;
644 }
645
646 tu_cs_emit_pkt4(cs, REG_A6XX_RB_MRT_CONTROL(i), 2);
647 tu_cs_emit(cs, rb_mrt_control);
648 tu_cs_emit(cs, rb_mrt_blend_control);
649 }
650
651 for (uint32_t i = blend_info->attachmentCount; i < MAX_RTS; i++) {
652 tu_cs_emit_pkt4(cs, REG_A6XX_RB_MRT_CONTROL(i), 2);
653 tu_cs_emit(cs, 0);
654 tu_cs_emit(cs, 0);
655 }
656 }
657
658 static void
659 tu6_emit_blend_control(struct tu_cs *cs,
660 uint32_t blend_enable_mask,
661 const VkPipelineMultisampleStateCreateInfo *msaa_info)
662 {
663 assert(!msaa_info->sampleShadingEnable);
664 assert(!msaa_info->alphaToOneEnable);
665
666 uint32_t sp_blend_cntl = A6XX_SP_BLEND_CNTL_UNK8;
667 if (blend_enable_mask)
668 sp_blend_cntl |= A6XX_SP_BLEND_CNTL_ENABLED;
669 if (msaa_info->alphaToCoverageEnable)
670 sp_blend_cntl |= A6XX_SP_BLEND_CNTL_ALPHA_TO_COVERAGE;
671
672 const uint32_t sample_mask =
673 msaa_info->pSampleMask ? *msaa_info->pSampleMask
674 : ((1 << msaa_info->rasterizationSamples) - 1);
675
676 /* set A6XX_RB_BLEND_CNTL_INDEPENDENT_BLEND only when enabled? */
677 uint32_t rb_blend_cntl =
678 A6XX_RB_BLEND_CNTL_ENABLE_BLEND(blend_enable_mask) |
679 A6XX_RB_BLEND_CNTL_INDEPENDENT_BLEND |
680 A6XX_RB_BLEND_CNTL_SAMPLE_MASK(sample_mask);
681 if (msaa_info->alphaToCoverageEnable)
682 rb_blend_cntl |= A6XX_RB_BLEND_CNTL_ALPHA_TO_COVERAGE;
683
684 tu_cs_emit_pkt4(cs, REG_A6XX_SP_BLEND_CNTL, 1);
685 tu_cs_emit(cs, sp_blend_cntl);
686
687 tu_cs_emit_pkt4(cs, REG_A6XX_RB_BLEND_CNTL, 1);
688 tu_cs_emit(cs, rb_blend_cntl);
689 }
690
691 void
692 tu6_emit_blend_constants(struct tu_cs *cs, const float constants[4])
693 {
694 tu_cs_emit_pkt4(cs, REG_A6XX_RB_BLEND_RED_F32, 4);
695 tu_cs_emit_array(cs, (const uint32_t *) constants, 4);
696 }
697
698 static VkResult
699 tu_pipeline_builder_create_pipeline(struct tu_pipeline_builder *builder,
700 struct tu_pipeline **out_pipeline)
701 {
702 struct tu_device *dev = builder->device;
703
704 struct tu_pipeline *pipeline =
705 vk_zalloc2(&dev->alloc, builder->alloc, sizeof(*pipeline), 8,
706 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
707 if (!pipeline)
708 return VK_ERROR_OUT_OF_HOST_MEMORY;
709
710 tu_cs_init(&pipeline->cs, TU_CS_MODE_SUB_STREAM, 2048);
711
712 /* reserve the space now such that tu_cs_begin_sub_stream never fails */
713 VkResult result = tu_cs_reserve_space(dev, &pipeline->cs, 2048);
714 if (result != VK_SUCCESS) {
715 vk_free2(&dev->alloc, builder->alloc, pipeline);
716 return result;
717 }
718
719 *out_pipeline = pipeline;
720
721 return VK_SUCCESS;
722 }
723
724 static VkResult
725 tu_pipeline_builder_compile_shaders(struct tu_pipeline_builder *builder)
726 {
727 const VkPipelineShaderStageCreateInfo *stage_infos[MESA_SHADER_STAGES] = {
728 NULL
729 };
730 for (uint32_t i = 0; i < builder->create_info->stageCount; i++) {
731 gl_shader_stage stage =
732 tu_shader_stage(builder->create_info->pStages[i].stage);
733 stage_infos[stage] = &builder->create_info->pStages[i];
734 }
735
736 struct tu_shader_compile_options options;
737 tu_shader_compile_options_init(&options, builder->create_info);
738
739 /* compile shaders in reverse order */
740 struct tu_shader *next_stage_shader = NULL;
741 for (gl_shader_stage stage = MESA_SHADER_STAGES - 1;
742 stage > MESA_SHADER_NONE; stage--) {
743 const VkPipelineShaderStageCreateInfo *stage_info = stage_infos[stage];
744 if (!stage_info)
745 continue;
746
747 struct tu_shader *shader =
748 tu_shader_create(builder->device, stage, stage_info, builder->alloc);
749 if (!shader)
750 return VK_ERROR_OUT_OF_HOST_MEMORY;
751
752 VkResult result =
753 tu_shader_compile(builder->device, shader, next_stage_shader,
754 &options, builder->alloc);
755 if (result != VK_SUCCESS)
756 return result;
757
758 builder->shaders[stage] = shader;
759 builder->shader_offsets[stage] = builder->shader_total_size;
760 builder->shader_total_size +=
761 sizeof(uint32_t) * shader->variants[0].info.sizedwords;
762
763 next_stage_shader = shader;
764 }
765
766 if (builder->shaders[MESA_SHADER_VERTEX]->has_binning_pass) {
767 const struct tu_shader *vs = builder->shaders[MESA_SHADER_VERTEX];
768 builder->binning_vs_offset = builder->shader_total_size;
769 builder->shader_total_size +=
770 sizeof(uint32_t) * vs->variants[1].info.sizedwords;
771 }
772
773 return VK_SUCCESS;
774 }
775
776 static VkResult
777 tu_pipeline_builder_upload_shaders(struct tu_pipeline_builder *builder,
778 struct tu_pipeline *pipeline)
779 {
780 struct tu_bo *bo = &pipeline->program.binary_bo;
781
782 VkResult result =
783 tu_bo_init_new(builder->device, bo, builder->shader_total_size);
784 if (result != VK_SUCCESS)
785 return result;
786
787 result = tu_bo_map(builder->device, bo);
788 if (result != VK_SUCCESS)
789 return result;
790
791 for (uint32_t i = 0; i < MESA_SHADER_STAGES; i++) {
792 const struct tu_shader *shader = builder->shaders[i];
793 if (!shader)
794 continue;
795
796 memcpy(bo->map + builder->shader_offsets[i], shader->binary,
797 sizeof(uint32_t) * shader->variants[0].info.sizedwords);
798 }
799
800 if (builder->shaders[MESA_SHADER_VERTEX]->has_binning_pass) {
801 const struct tu_shader *vs = builder->shaders[MESA_SHADER_VERTEX];
802 memcpy(bo->map + builder->binning_vs_offset, vs->binning_binary,
803 sizeof(uint32_t) * vs->variants[1].info.sizedwords);
804 }
805
806 return VK_SUCCESS;
807 }
808
809 static void
810 tu_pipeline_builder_parse_dynamic(struct tu_pipeline_builder *builder,
811 struct tu_pipeline *pipeline)
812 {
813 const VkPipelineDynamicStateCreateInfo *dynamic_info =
814 builder->create_info->pDynamicState;
815
816 if (!dynamic_info)
817 return;
818
819 for (uint32_t i = 0; i < dynamic_info->dynamicStateCount; i++) {
820 pipeline->dynamic_state.mask |=
821 tu_dynamic_state_bit(dynamic_info->pDynamicStates[i]);
822 }
823 }
824
825 static void
826 tu_pipeline_builder_parse_input_assembly(struct tu_pipeline_builder *builder,
827 struct tu_pipeline *pipeline)
828 {
829 const VkPipelineInputAssemblyStateCreateInfo *ia_info =
830 builder->create_info->pInputAssemblyState;
831
832 pipeline->ia.primtype = tu6_primtype(ia_info->topology);
833 pipeline->ia.primitive_restart = ia_info->primitiveRestartEnable;
834 }
835
836 static void
837 tu_pipeline_builder_parse_viewport(struct tu_pipeline_builder *builder,
838 struct tu_pipeline *pipeline)
839 {
840 /* The spec says:
841 *
842 * pViewportState is a pointer to an instance of the
843 * VkPipelineViewportStateCreateInfo structure, and is ignored if the
844 * pipeline has rasterization disabled."
845 *
846 * We leave the relevant registers stale in that case.
847 */
848 if (builder->rasterizer_discard)
849 return;
850
851 const VkPipelineViewportStateCreateInfo *vp_info =
852 builder->create_info->pViewportState;
853
854 struct tu_cs vp_cs;
855 tu_cs_begin_sub_stream(builder->device, &pipeline->cs, 15, &vp_cs);
856
857 if (!(pipeline->dynamic_state.mask & TU_DYNAMIC_VIEWPORT)) {
858 assert(vp_info->viewportCount == 1);
859 tu6_emit_viewport(&vp_cs, vp_info->pViewports);
860 }
861
862 if (!(pipeline->dynamic_state.mask & TU_DYNAMIC_SCISSOR)) {
863 assert(vp_info->scissorCount == 1);
864 tu6_emit_scissor(&vp_cs, vp_info->pScissors);
865 }
866
867 pipeline->vp.state_ib = tu_cs_end_sub_stream(&pipeline->cs, &vp_cs);
868 }
869
870 static void
871 tu_pipeline_builder_parse_rasterization(struct tu_pipeline_builder *builder,
872 struct tu_pipeline *pipeline)
873 {
874 const VkPipelineRasterizationStateCreateInfo *rast_info =
875 builder->create_info->pRasterizationState;
876
877 assert(!rast_info->depthClampEnable);
878 assert(rast_info->polygonMode == VK_POLYGON_MODE_FILL);
879
880 struct tu_cs rast_cs;
881 tu_cs_begin_sub_stream(builder->device, &pipeline->cs, 20, &rast_cs);
882
883 /* move to hw ctx init? */
884 tu6_emit_gras_unknowns(&rast_cs);
885 tu6_emit_point_size(&rast_cs);
886
887 const uint32_t gras_su_cntl =
888 tu6_gras_su_cntl(rast_info, builder->samples);
889
890 if (!(pipeline->dynamic_state.mask & TU_DYNAMIC_LINE_WIDTH))
891 tu6_emit_gras_su_cntl(&rast_cs, gras_su_cntl, rast_info->lineWidth);
892
893 if (!(pipeline->dynamic_state.mask & TU_DYNAMIC_DEPTH_BIAS)) {
894 tu6_emit_depth_bias(&rast_cs, rast_info->depthBiasConstantFactor,
895 rast_info->depthBiasClamp,
896 rast_info->depthBiasSlopeFactor);
897 }
898
899 pipeline->rast.state_ib = tu_cs_end_sub_stream(&pipeline->cs, &rast_cs);
900
901 pipeline->rast.gras_su_cntl = gras_su_cntl;
902 }
903
904 static void
905 tu_pipeline_builder_parse_depth_stencil(struct tu_pipeline_builder *builder,
906 struct tu_pipeline *pipeline)
907 {
908 /* The spec says:
909 *
910 * pDepthStencilState is a pointer to an instance of the
911 * VkPipelineDepthStencilStateCreateInfo structure, and is ignored if
912 * the pipeline has rasterization disabled or if the subpass of the
913 * render pass the pipeline is created against does not use a
914 * depth/stencil attachment.
915 *
916 * We disable both depth and stenil tests in those cases.
917 */
918 static const VkPipelineDepthStencilStateCreateInfo dummy_ds_info;
919 const VkPipelineDepthStencilStateCreateInfo *ds_info =
920 builder->use_depth_stencil_attachment
921 ? builder->create_info->pDepthStencilState
922 : &dummy_ds_info;
923
924 struct tu_cs ds_cs;
925 tu_cs_begin_sub_stream(builder->device, &pipeline->cs, 12, &ds_cs);
926
927 /* move to hw ctx init? */
928 tu6_emit_alpha_control_disable(&ds_cs);
929
930 tu6_emit_depth_control(&ds_cs, ds_info);
931 tu6_emit_stencil_control(&ds_cs, ds_info);
932
933 if (!(pipeline->dynamic_state.mask & TU_DYNAMIC_STENCIL_COMPARE_MASK)) {
934 tu6_emit_stencil_compare_mask(&ds_cs, ds_info->front.compareMask,
935 ds_info->back.compareMask);
936 }
937 if (!(pipeline->dynamic_state.mask & TU_DYNAMIC_STENCIL_WRITE_MASK)) {
938 tu6_emit_stencil_write_mask(&ds_cs, ds_info->front.writeMask,
939 ds_info->back.writeMask);
940 }
941 if (!(pipeline->dynamic_state.mask & TU_DYNAMIC_STENCIL_REFERENCE)) {
942 tu6_emit_stencil_reference(&ds_cs, ds_info->front.reference,
943 ds_info->back.reference);
944 }
945
946 pipeline->ds.state_ib = tu_cs_end_sub_stream(&pipeline->cs, &ds_cs);
947 }
948
949 static void
950 tu_pipeline_builder_parse_multisample_and_color_blend(
951 struct tu_pipeline_builder *builder, struct tu_pipeline *pipeline)
952 {
953 /* The spec says:
954 *
955 * pMultisampleState is a pointer to an instance of the
956 * VkPipelineMultisampleStateCreateInfo, and is ignored if the pipeline
957 * has rasterization disabled.
958 *
959 * Also,
960 *
961 * pColorBlendState is a pointer to an instance of the
962 * VkPipelineColorBlendStateCreateInfo structure, and is ignored if the
963 * pipeline has rasterization disabled or if the subpass of the render
964 * pass the pipeline is created against does not use any color
965 * attachments.
966 *
967 * We leave the relevant registers stale when rasterization is disabled.
968 */
969 if (builder->rasterizer_discard)
970 return;
971
972 static const VkPipelineColorBlendStateCreateInfo dummy_blend_info;
973 const VkPipelineMultisampleStateCreateInfo *msaa_info =
974 builder->create_info->pMultisampleState;
975 const VkPipelineColorBlendStateCreateInfo *blend_info =
976 builder->use_color_attachments ? builder->create_info->pColorBlendState
977 : &dummy_blend_info;
978
979 struct tu_cs blend_cs;
980 tu_cs_begin_sub_stream(builder->device, &pipeline->cs, MAX_RTS * 3 + 9,
981 &blend_cs);
982
983 uint32_t blend_enable_mask;
984 tu6_emit_rb_mrt_controls(&blend_cs, blend_info,
985 builder->color_attachment_formats,
986 &blend_enable_mask);
987
988 if (!(pipeline->dynamic_state.mask & TU_DYNAMIC_BLEND_CONSTANTS))
989 tu6_emit_blend_constants(&blend_cs, blend_info->blendConstants);
990
991 tu6_emit_blend_control(&blend_cs, blend_enable_mask, msaa_info);
992
993 pipeline->blend.state_ib = tu_cs_end_sub_stream(&pipeline->cs, &blend_cs);
994 }
995
996 static void
997 tu_pipeline_finish(struct tu_pipeline *pipeline,
998 struct tu_device *dev,
999 const VkAllocationCallbacks *alloc)
1000 {
1001 tu_cs_finish(dev, &pipeline->cs);
1002
1003 if (pipeline->program.binary_bo.gem_handle)
1004 tu_bo_finish(dev, &pipeline->program.binary_bo);
1005 }
1006
1007 static VkResult
1008 tu_pipeline_builder_build(struct tu_pipeline_builder *builder,
1009 struct tu_pipeline **pipeline)
1010 {
1011 VkResult result = tu_pipeline_builder_create_pipeline(builder, pipeline);
1012 if (result != VK_SUCCESS)
1013 return result;
1014
1015 /* compile and upload shaders */
1016 result = tu_pipeline_builder_compile_shaders(builder);
1017 if (result == VK_SUCCESS)
1018 result = tu_pipeline_builder_upload_shaders(builder, *pipeline);
1019 if (result != VK_SUCCESS) {
1020 tu_pipeline_finish(*pipeline, builder->device, builder->alloc);
1021 vk_free2(&builder->device->alloc, builder->alloc, *pipeline);
1022 *pipeline = VK_NULL_HANDLE;
1023
1024 return result;
1025 }
1026
1027 tu_pipeline_builder_parse_dynamic(builder, *pipeline);
1028 tu_pipeline_builder_parse_input_assembly(builder, *pipeline);
1029 tu_pipeline_builder_parse_viewport(builder, *pipeline);
1030 tu_pipeline_builder_parse_rasterization(builder, *pipeline);
1031 tu_pipeline_builder_parse_depth_stencil(builder, *pipeline);
1032 tu_pipeline_builder_parse_multisample_and_color_blend(builder, *pipeline);
1033
1034 /* we should have reserved enough space upfront such that the CS never
1035 * grows
1036 */
1037 assert((*pipeline)->cs.bo_count == 1);
1038
1039 return VK_SUCCESS;
1040 }
1041
1042 static void
1043 tu_pipeline_builder_finish(struct tu_pipeline_builder *builder)
1044 {
1045 for (uint32_t i = 0; i < MESA_SHADER_STAGES; i++) {
1046 if (!builder->shaders[i])
1047 continue;
1048 tu_shader_destroy(builder->device, builder->shaders[i], builder->alloc);
1049 }
1050 }
1051
1052 static void
1053 tu_pipeline_builder_init_graphics(
1054 struct tu_pipeline_builder *builder,
1055 struct tu_device *dev,
1056 struct tu_pipeline_cache *cache,
1057 const VkGraphicsPipelineCreateInfo *create_info,
1058 const VkAllocationCallbacks *alloc)
1059 {
1060 *builder = (struct tu_pipeline_builder) {
1061 .device = dev,
1062 .cache = cache,
1063 .create_info = create_info,
1064 .alloc = alloc,
1065 };
1066
1067 builder->rasterizer_discard =
1068 create_info->pRasterizationState->rasterizerDiscardEnable;
1069
1070 if (builder->rasterizer_discard) {
1071 builder->samples = VK_SAMPLE_COUNT_1_BIT;
1072 } else {
1073 builder->samples = create_info->pMultisampleState->rasterizationSamples;
1074
1075 const struct tu_render_pass *pass =
1076 tu_render_pass_from_handle(create_info->renderPass);
1077 const struct tu_subpass *subpass =
1078 &pass->subpasses[create_info->subpass];
1079
1080 builder->use_depth_stencil_attachment =
1081 subpass->depth_stencil_attachment.attachment != VK_ATTACHMENT_UNUSED;
1082
1083 for (uint32_t i = 0; i < subpass->color_count; i++) {
1084 const uint32_t a = subpass->color_attachments[i].attachment;
1085 if (a == VK_ATTACHMENT_UNUSED)
1086 continue;
1087
1088 builder->color_attachment_formats[i] = pass->attachments[a].format;
1089 builder->use_color_attachments = true;
1090 }
1091 }
1092 }
1093
1094 VkResult
1095 tu_CreateGraphicsPipelines(VkDevice device,
1096 VkPipelineCache pipelineCache,
1097 uint32_t count,
1098 const VkGraphicsPipelineCreateInfo *pCreateInfos,
1099 const VkAllocationCallbacks *pAllocator,
1100 VkPipeline *pPipelines)
1101 {
1102 TU_FROM_HANDLE(tu_device, dev, device);
1103 TU_FROM_HANDLE(tu_pipeline_cache, cache, pipelineCache);
1104
1105 for (uint32_t i = 0; i < count; i++) {
1106 struct tu_pipeline_builder builder;
1107 tu_pipeline_builder_init_graphics(&builder, dev, cache,
1108 &pCreateInfos[i], pAllocator);
1109
1110 struct tu_pipeline *pipeline;
1111 VkResult result = tu_pipeline_builder_build(&builder, &pipeline);
1112 tu_pipeline_builder_finish(&builder);
1113
1114 if (result != VK_SUCCESS) {
1115 for (uint32_t j = 0; j < i; j++) {
1116 tu_DestroyPipeline(device, pPipelines[j], pAllocator);
1117 pPipelines[j] = VK_NULL_HANDLE;
1118 }
1119
1120 return result;
1121 }
1122
1123 pPipelines[i] = tu_pipeline_to_handle(pipeline);
1124 }
1125
1126 return VK_SUCCESS;
1127 }
1128
1129 static VkResult
1130 tu_compute_pipeline_create(VkDevice _device,
1131 VkPipelineCache _cache,
1132 const VkComputePipelineCreateInfo *pCreateInfo,
1133 const VkAllocationCallbacks *pAllocator,
1134 VkPipeline *pPipeline)
1135 {
1136 return VK_SUCCESS;
1137 }
1138
1139 VkResult
1140 tu_CreateComputePipelines(VkDevice _device,
1141 VkPipelineCache pipelineCache,
1142 uint32_t count,
1143 const VkComputePipelineCreateInfo *pCreateInfos,
1144 const VkAllocationCallbacks *pAllocator,
1145 VkPipeline *pPipelines)
1146 {
1147 VkResult result = VK_SUCCESS;
1148
1149 unsigned i = 0;
1150 for (; i < count; i++) {
1151 VkResult r;
1152 r = tu_compute_pipeline_create(_device, pipelineCache, &pCreateInfos[i],
1153 pAllocator, &pPipelines[i]);
1154 if (r != VK_SUCCESS) {
1155 result = r;
1156 pPipelines[i] = VK_NULL_HANDLE;
1157 }
1158 }
1159
1160 return result;
1161 }
1162
1163 void
1164 tu_DestroyPipeline(VkDevice _device,
1165 VkPipeline _pipeline,
1166 const VkAllocationCallbacks *pAllocator)
1167 {
1168 TU_FROM_HANDLE(tu_device, dev, _device);
1169 TU_FROM_HANDLE(tu_pipeline, pipeline, _pipeline);
1170
1171 if (!_pipeline)
1172 return;
1173
1174 tu_pipeline_finish(pipeline, dev, pAllocator);
1175 vk_free2(&dev->alloc, pAllocator, pipeline);
1176 }