Blender V4.3
vk_pipeline_pool.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2024 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8#include "BKE_appdir.hh"
10
11#include "BLI_fileops.hh"
12#include "BLI_path_utils.hh"
13
14#include "CLG_log.h"
15
16#include "vk_backend.hh"
17#include "vk_memory.hh"
18#include "vk_pipeline_pool.hh"
19
20#ifdef WITH_BUILDINFO
21extern "C" char build_hash[];
22static CLG_LogRef LOG = {"gpu.vulkan"};
23#endif
24
25namespace blender::gpu {
26
28{
29 /* Initialize VkComputePipelineCreateInfo */
30 vk_compute_pipeline_create_info_.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
31 vk_compute_pipeline_create_info_.pNext = nullptr;
32 vk_compute_pipeline_create_info_.flags = 0;
33 vk_compute_pipeline_create_info_.layout = VK_NULL_HANDLE;
34 vk_compute_pipeline_create_info_.basePipelineHandle = VK_NULL_HANDLE;
35 vk_compute_pipeline_create_info_.basePipelineIndex = 0;
36 VkPipelineShaderStageCreateInfo &vk_pipeline_shader_stage_create_info =
37 vk_compute_pipeline_create_info_.stage;
38 vk_pipeline_shader_stage_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
39 vk_pipeline_shader_stage_create_info.pNext = nullptr;
40 vk_pipeline_shader_stage_create_info.flags = 0;
41 vk_pipeline_shader_stage_create_info.stage = VK_SHADER_STAGE_COMPUTE_BIT;
42 vk_pipeline_shader_stage_create_info.module = VK_NULL_HANDLE;
43 vk_pipeline_shader_stage_create_info.pName = "main";
44
45 /* Initialize VkGraphicsPipelineCreateInfo */
46 vk_graphics_pipeline_create_info_ = {};
47 vk_graphics_pipeline_create_info_.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
48 vk_graphics_pipeline_create_info_.pNext = &vk_pipeline_rendering_create_info_;
49 vk_graphics_pipeline_create_info_.stageCount = 0;
50 vk_graphics_pipeline_create_info_.pStages = vk_pipeline_shader_stage_create_info_;
51 vk_graphics_pipeline_create_info_.pInputAssemblyState =
52 &vk_pipeline_input_assembly_state_create_info_;
53 vk_graphics_pipeline_create_info_.pVertexInputState =
54 &vk_pipeline_vertex_input_state_create_info_;
55 vk_graphics_pipeline_create_info_.pRasterizationState =
56 &vk_pipeline_rasterization_state_create_info_;
57 vk_graphics_pipeline_create_info_.pViewportState = &vk_pipeline_viewport_state_create_info_;
58 vk_graphics_pipeline_create_info_.pMultisampleState =
59 &vk_pipeline_multisample_state_create_info_;
60 vk_graphics_pipeline_create_info_.pColorBlendState = &vk_pipeline_color_blend_state_create_info_;
61
62 /* Initialize VkPipelineRenderingCreateInfo */
63 vk_pipeline_rendering_create_info_ = {};
64 vk_pipeline_rendering_create_info_.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO;
65
66 /* Initialize VkPipelineShaderStageCreateInfo */
67 for (int i : IndexRange(3)) {
68 vk_pipeline_shader_stage_create_info_[i].sType =
69 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
70 vk_pipeline_shader_stage_create_info_[i].pNext = nullptr;
71 vk_pipeline_shader_stage_create_info_[i].flags = 0;
72 vk_pipeline_shader_stage_create_info_[i].module = VK_NULL_HANDLE;
73 vk_pipeline_shader_stage_create_info_[i].pName = "main";
74 }
75 vk_pipeline_shader_stage_create_info_[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
76 vk_pipeline_shader_stage_create_info_[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
77 vk_pipeline_shader_stage_create_info_[2].stage = VK_SHADER_STAGE_GEOMETRY_BIT;
78
79 /* Initialize VkPipelineInputAssemblyStateCreateInfo */
80 vk_pipeline_input_assembly_state_create_info_ = {};
81 vk_pipeline_input_assembly_state_create_info_.sType =
82 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
83
84 /* Initialize VkPipelineVertexInputStateCreateInfo */
85 vk_pipeline_vertex_input_state_create_info_ = {};
86 vk_pipeline_vertex_input_state_create_info_.sType =
87 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
88
89 /* Initialize VkPipelineRasterizationStateCreateInfo */
90 vk_pipeline_rasterization_state_create_info_ = {};
91 vk_pipeline_rasterization_state_create_info_.sType =
92 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
93 vk_pipeline_rasterization_state_create_info_.lineWidth = 1.0f;
94 vk_pipeline_rasterization_state_create_info_.frontFace = VK_FRONT_FACE_CLOCKWISE;
95
96 vk_pipeline_viewport_state_create_info_ = {};
97 vk_pipeline_viewport_state_create_info_.sType =
98 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
99
100 /* Initialize VkPipelineMultisampleStateCreateInfo */
101 vk_pipeline_multisample_state_create_info_ = {};
102 vk_pipeline_multisample_state_create_info_.sType =
103 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
104 vk_pipeline_multisample_state_create_info_.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
105 vk_pipeline_multisample_state_create_info_.minSampleShading = 1.0f;
106
107 /* Initialize VkPipelineColorBlendStateCreateInfo */
108 vk_pipeline_color_blend_state_create_info_ = {};
109 vk_pipeline_color_blend_state_create_info_.sType =
110 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
111 vk_pipeline_color_blend_attachment_state_template_.colorWriteMask = VK_COLOR_COMPONENT_R_BIT |
112 VK_COLOR_COMPONENT_G_BIT |
113 VK_COLOR_COMPONENT_B_BIT |
114 VK_COLOR_COMPONENT_A_BIT;
115 /* Initialize VkPipelineDepthStencilStateCreateInfo */
116 vk_pipeline_depth_stencil_state_create_info_ = {};
117 vk_pipeline_depth_stencil_state_create_info_.sType =
118 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
119
120 /* Initialize VkSpecializationInfo. */
121 vk_specialization_info_.mapEntryCount = 0;
122 vk_specialization_info_.pMapEntries = nullptr;
123 vk_specialization_info_.dataSize = 0;
124 vk_specialization_info_.pData = nullptr;
125
126 vk_push_constant_range_.stageFlags = 0;
127 vk_push_constant_range_.offset = 0;
128 vk_push_constant_range_.size = 0;
129}
131{
133 VKDevice &device = VKBackend::get().device;
134 VkPipelineCacheCreateInfo create_info = {};
135 create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
136 vkCreatePipelineCache(
137 device.vk_handle(), &create_info, vk_allocation_callbacks, &vk_pipeline_cache_static_);
138 vkCreatePipelineCache(
139 device.vk_handle(), &create_info, vk_allocation_callbacks, &vk_pipeline_cache_non_static_);
140}
141
142VkSpecializationInfo *VKPipelinePool::specialization_info_update(
143 Span<shader::SpecializationConstant::Value> specialization_constants)
144{
145 if (specialization_constants.is_empty()) {
146 return nullptr;
147 }
148
149 while (vk_specialization_map_entries_.size() < specialization_constants.size()) {
150 uint32_t constant_id = vk_specialization_map_entries_.size();
151 VkSpecializationMapEntry vk_specialization_map_entry = {};
152 vk_specialization_map_entry.constantID = constant_id;
153 vk_specialization_map_entry.offset = constant_id * sizeof(uint32_t);
154 vk_specialization_map_entry.size = sizeof(uint32_t);
155 vk_specialization_map_entries_.append(vk_specialization_map_entry);
156 }
157 vk_specialization_info_.dataSize = specialization_constants.size() * sizeof(uint32_t);
158 vk_specialization_info_.pData = specialization_constants.data();
159 vk_specialization_info_.mapEntryCount = specialization_constants.size();
160 vk_specialization_info_.pMapEntries = vk_specialization_map_entries_.data();
161 return &vk_specialization_info_;
162}
163
164void VKPipelinePool::specialization_info_reset()
165{
166 vk_specialization_info_.dataSize = 0;
167 vk_specialization_info_.pData = nullptr;
168 vk_specialization_info_.mapEntryCount = 0;
169 vk_specialization_info_.pMapEntries = nullptr;
170}
171
173 const bool is_static_shader,
174 VkPipeline vk_pipeline_base)
175{
176 std::scoped_lock lock(mutex_);
177 const VkPipeline *found_pipeline = compute_pipelines_.lookup_ptr(compute_info);
178 if (found_pipeline) {
179 VkPipeline result = *found_pipeline;
180 BLI_assert(result != VK_NULL_HANDLE);
181 return result;
182 }
183
184 vk_compute_pipeline_create_info_.layout = compute_info.vk_pipeline_layout;
185 vk_compute_pipeline_create_info_.stage.module = compute_info.vk_shader_module;
186 vk_compute_pipeline_create_info_.basePipelineHandle = vk_pipeline_base;
187 vk_compute_pipeline_create_info_.stage.pSpecializationInfo = specialization_info_update(
188 compute_info.specialization_constants);
189
190 /* Build pipeline. */
191 VKBackend &backend = VKBackend::get();
192 VKDevice &device = backend.device;
194
195 VkPipeline pipeline = VK_NULL_HANDLE;
196 vkCreateComputePipelines(device.vk_handle(),
197 is_static_shader ? vk_pipeline_cache_static_ :
198 vk_pipeline_cache_non_static_,
199 1,
200 &vk_compute_pipeline_create_info_,
201 vk_allocation_callbacks,
202 &pipeline);
203 compute_pipelines_.add(compute_info, pipeline);
204
205 /* Reset values to initial value. */
206 vk_compute_pipeline_create_info_.layout = VK_NULL_HANDLE;
207 vk_compute_pipeline_create_info_.stage.module = VK_NULL_HANDLE;
208 vk_compute_pipeline_create_info_.stage.pSpecializationInfo = nullptr;
209 vk_compute_pipeline_create_info_.basePipelineHandle = VK_NULL_HANDLE;
210 specialization_info_reset();
211
212 return pipeline;
213}
214
216 const bool is_static_shader,
217 VkPipeline vk_pipeline_base)
218{
219 std::scoped_lock lock(mutex_);
220 graphics_info.fragment_shader.update_hash();
221 const VkPipeline *found_pipeline = graphic_pipelines_.lookup_ptr(graphics_info);
222 if (found_pipeline) {
223 VkPipeline result = *found_pipeline;
224 BLI_assert(result != VK_NULL_HANDLE);
225 return result;
226 }
227
228 /* Specialization constants */
229 VkSpecializationInfo *specialization_info = specialization_info_update(
230 graphics_info.specialization_constants);
231
232 /* Shader stages */
233 vk_graphics_pipeline_create_info_.stageCount =
234 graphics_info.pre_rasterization.vk_geometry_module == VK_NULL_HANDLE ? 2 : 3;
235 vk_pipeline_shader_stage_create_info_[0].module =
237 vk_pipeline_shader_stage_create_info_[0].pSpecializationInfo = specialization_info;
238 vk_pipeline_shader_stage_create_info_[1].module =
240 vk_pipeline_shader_stage_create_info_[1].pSpecializationInfo = specialization_info;
241 vk_pipeline_shader_stage_create_info_[2].module =
243 vk_pipeline_shader_stage_create_info_[2].pSpecializationInfo = specialization_info;
244
245 /* Input assembly */
246 vk_pipeline_input_assembly_state_create_info_.topology = graphics_info.vertex_in.vk_topology;
247 vk_pipeline_input_assembly_state_create_info_.primitiveRestartEnable =
248 ELEM(graphics_info.vertex_in.vk_topology,
249 VK_PRIMITIVE_TOPOLOGY_POINT_LIST,
250 VK_PRIMITIVE_TOPOLOGY_LINE_LIST,
251 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
252 VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY) ?
253 VK_FALSE :
254 VK_TRUE;
255 vk_pipeline_vertex_input_state_create_info_.pVertexAttributeDescriptions =
256 graphics_info.vertex_in.attributes.data();
257 vk_pipeline_vertex_input_state_create_info_.vertexAttributeDescriptionCount =
258 graphics_info.vertex_in.attributes.size();
259 vk_pipeline_vertex_input_state_create_info_.pVertexBindingDescriptions =
260 graphics_info.vertex_in.bindings.data();
261 vk_pipeline_vertex_input_state_create_info_.vertexBindingDescriptionCount =
262 graphics_info.vertex_in.bindings.size();
263
264 /* Rasterization state */
265 vk_pipeline_rasterization_state_create_info_.frontFace = graphics_info.state.invert_facing ?
266 VK_FRONT_FACE_COUNTER_CLOCKWISE :
267 VK_FRONT_FACE_CLOCKWISE;
268 vk_pipeline_rasterization_state_create_info_.cullMode = to_vk_cull_mode_flags(
269 static_cast<eGPUFaceCullTest>(graphics_info.state.culling_test));
270 if (graphics_info.state.shadow_bias) {
271 vk_pipeline_rasterization_state_create_info_.depthBiasEnable = VK_TRUE;
272 vk_pipeline_rasterization_state_create_info_.depthBiasSlopeFactor = 2.0f;
273 vk_pipeline_rasterization_state_create_info_.depthBiasConstantFactor = 1.0f;
274 vk_pipeline_rasterization_state_create_info_.depthBiasClamp = 0.0f;
275 }
276 else {
277 vk_pipeline_rasterization_state_create_info_.depthBiasEnable = VK_FALSE;
278 }
279 vk_pipeline_rasterization_state_create_info_.frontFace = graphics_info.state.invert_facing ?
280 VK_FRONT_FACE_COUNTER_CLOCKWISE :
281 VK_FRONT_FACE_CLOCKWISE;
282
283 /* Viewport state */
284 vk_pipeline_viewport_state_create_info_.pViewports =
285 graphics_info.fragment_shader.viewports.data();
286 vk_pipeline_viewport_state_create_info_.viewportCount =
287 graphics_info.fragment_shader.viewports.size();
288 vk_pipeline_viewport_state_create_info_.pScissors =
289 graphics_info.fragment_shader.scissors.data();
290 vk_pipeline_viewport_state_create_info_.scissorCount =
291 graphics_info.fragment_shader.scissors.size();
292
293 /* Color blending */
294 {
295 VkPipelineColorBlendStateCreateInfo &cb = vk_pipeline_color_blend_state_create_info_;
296 VkPipelineColorBlendAttachmentState &att_state =
297 vk_pipeline_color_blend_attachment_state_template_;
298
299 att_state.blendEnable = VK_TRUE;
300 att_state.alphaBlendOp = VK_BLEND_OP_ADD;
301 att_state.colorBlendOp = VK_BLEND_OP_ADD;
302 att_state.srcColorBlendFactor = VK_BLEND_FACTOR_DST_ALPHA;
303 att_state.dstColorBlendFactor = VK_BLEND_FACTOR_ONE;
304 att_state.srcAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
305 att_state.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
306 att_state.colorWriteMask = 0;
307 cb.blendConstants[0] = 1.0f;
308 cb.blendConstants[1] = 1.0f;
309 cb.blendConstants[2] = 1.0f;
310 cb.blendConstants[3] = 1.0f;
311
312 switch (graphics_info.state.blend) {
313 default:
314 case GPU_BLEND_ALPHA:
315 att_state.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
316 att_state.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
317 att_state.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
318 att_state.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
319 break;
320
322 att_state.srcColorBlendFactor = VK_BLEND_FACTOR_ONE;
323 att_state.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
324 att_state.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
325 att_state.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
326 break;
327
329 att_state.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
330 att_state.dstColorBlendFactor = VK_BLEND_FACTOR_ONE;
331 att_state.srcAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
332 att_state.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
333 break;
334
337 att_state.srcColorBlendFactor = VK_BLEND_FACTOR_ONE;
338 att_state.dstColorBlendFactor = VK_BLEND_FACTOR_ONE;
339 att_state.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
340 att_state.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
341 break;
342
344 att_state.srcColorBlendFactor = VK_BLEND_FACTOR_DST_COLOR;
345 att_state.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO;
346 att_state.srcAlphaBlendFactor = VK_BLEND_FACTOR_DST_ALPHA;
347 att_state.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
348 break;
349
350 case GPU_BLEND_INVERT:
351 att_state.srcColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR;
352 att_state.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO;
353 att_state.srcAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
354 att_state.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
355 break;
356
357 case GPU_BLEND_OIT:
358 att_state.srcColorBlendFactor = VK_BLEND_FACTOR_ONE;
359 att_state.dstColorBlendFactor = VK_BLEND_FACTOR_ONE;
360 att_state.srcAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
361 att_state.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
362 break;
363
365 att_state.srcColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA;
366 att_state.dstColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
367 att_state.srcAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
368 att_state.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
369 break;
370
372 att_state.srcColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA;
373 att_state.dstColorBlendFactor = VK_BLEND_FACTOR_ONE;
374 att_state.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA;
375 att_state.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
376 break;
377
378 case GPU_BLEND_CUSTOM:
379 att_state.srcColorBlendFactor = VK_BLEND_FACTOR_ONE;
380 att_state.dstColorBlendFactor = VK_BLEND_FACTOR_SRC1_COLOR;
381 att_state.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
382 att_state.dstAlphaBlendFactor = VK_BLEND_FACTOR_SRC1_ALPHA;
383 break;
384 }
385
386 if (graphics_info.state.blend == GPU_BLEND_SUBTRACT) {
387 att_state.alphaBlendOp = VK_BLEND_OP_REVERSE_SUBTRACT;
388 att_state.colorBlendOp = VK_BLEND_OP_REVERSE_SUBTRACT;
389 }
390 else {
391 att_state.alphaBlendOp = VK_BLEND_OP_ADD;
392 att_state.colorBlendOp = VK_BLEND_OP_ADD;
393 }
394
395 if (graphics_info.state.blend != GPU_BLEND_NONE) {
396 att_state.blendEnable = VK_TRUE;
397 }
398 else {
399 att_state.blendEnable = VK_FALSE;
400 }
401
402 /* Adjust the template with the color components in the write mask. */
403 if ((graphics_info.state.write_mask & GPU_WRITE_RED) != 0) {
404 att_state.colorWriteMask |= VK_COLOR_COMPONENT_R_BIT;
405 }
406 if ((graphics_info.state.write_mask & GPU_WRITE_GREEN) != 0) {
407 att_state.colorWriteMask |= VK_COLOR_COMPONENT_G_BIT;
408 }
409 if ((graphics_info.state.write_mask & GPU_WRITE_BLUE) != 0) {
410 att_state.colorWriteMask |= VK_COLOR_COMPONENT_B_BIT;
411 }
412 if ((graphics_info.state.write_mask & GPU_WRITE_ALPHA) != 0) {
413 att_state.colorWriteMask |= VK_COLOR_COMPONENT_A_BIT;
414 }
415
416 vk_pipeline_color_blend_attachment_states_.clear();
417 vk_pipeline_color_blend_attachment_states_.append_n_times(
418 vk_pipeline_color_blend_attachment_state_template_,
420 vk_pipeline_color_blend_state_create_info_.attachmentCount =
421 vk_pipeline_color_blend_attachment_states_.size();
422 vk_pipeline_color_blend_state_create_info_.pAttachments =
423 vk_pipeline_color_blend_attachment_states_.data();
424 }
425
426 if (graphics_info.fragment_out.depth_attachment_format != VK_FORMAT_UNDEFINED) {
427 vk_graphics_pipeline_create_info_.pDepthStencilState =
428 &vk_pipeline_depth_stencil_state_create_info_;
429 vk_pipeline_depth_stencil_state_create_info_.depthWriteEnable =
430 (graphics_info.state.write_mask & GPU_WRITE_DEPTH) ? VK_TRUE : VK_FALSE;
431
432 vk_pipeline_depth_stencil_state_create_info_.depthTestEnable = VK_TRUE;
433 switch (graphics_info.state.depth_test) {
434 case GPU_DEPTH_LESS:
435 vk_pipeline_depth_stencil_state_create_info_.depthCompareOp = VK_COMPARE_OP_LESS;
436 break;
438 vk_pipeline_depth_stencil_state_create_info_.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL;
439 break;
440 case GPU_DEPTH_EQUAL:
441 vk_pipeline_depth_stencil_state_create_info_.depthCompareOp = VK_COMPARE_OP_EQUAL;
442 break;
444 vk_pipeline_depth_stencil_state_create_info_.depthCompareOp = VK_COMPARE_OP_GREATER;
445 break;
447 vk_pipeline_depth_stencil_state_create_info_.depthCompareOp =
448 VK_COMPARE_OP_GREATER_OR_EQUAL;
449 break;
450 case GPU_DEPTH_ALWAYS:
451 vk_pipeline_depth_stencil_state_create_info_.depthCompareOp = VK_COMPARE_OP_ALWAYS;
452 break;
453 case GPU_DEPTH_NONE:
454 vk_pipeline_depth_stencil_state_create_info_.depthTestEnable = VK_FALSE;
455 vk_pipeline_depth_stencil_state_create_info_.depthCompareOp = VK_COMPARE_OP_NEVER;
456 break;
457 }
458 }
459
460 if (graphics_info.fragment_out.stencil_attachment_format != VK_FORMAT_UNDEFINED) {
461 vk_graphics_pipeline_create_info_.pDepthStencilState =
462 &vk_pipeline_depth_stencil_state_create_info_;
463
464 switch (graphics_info.state.stencil_test) {
466 vk_pipeline_depth_stencil_state_create_info_.stencilTestEnable = VK_TRUE;
467 vk_pipeline_depth_stencil_state_create_info_.front.compareOp = VK_COMPARE_OP_NOT_EQUAL;
468 break;
470 vk_pipeline_depth_stencil_state_create_info_.stencilTestEnable = VK_TRUE;
471 vk_pipeline_depth_stencil_state_create_info_.front.compareOp = VK_COMPARE_OP_EQUAL;
472 break;
474 vk_pipeline_depth_stencil_state_create_info_.stencilTestEnable = VK_TRUE;
475 vk_pipeline_depth_stencil_state_create_info_.front.compareOp = VK_COMPARE_OP_ALWAYS;
476 break;
477 case GPU_STENCIL_NONE:
478 vk_pipeline_depth_stencil_state_create_info_.stencilTestEnable = VK_FALSE;
479 vk_pipeline_depth_stencil_state_create_info_.front.compareOp = VK_COMPARE_OP_ALWAYS;
480 break;
481 }
482
483 vk_pipeline_depth_stencil_state_create_info_.front.compareMask =
485 vk_pipeline_depth_stencil_state_create_info_.front.reference =
486 graphics_info.mutable_state.stencil_reference;
487 vk_pipeline_depth_stencil_state_create_info_.front.writeMask =
488 graphics_info.mutable_state.stencil_write_mask;
489
490 switch (graphics_info.state.stencil_op) {
492 vk_pipeline_depth_stencil_state_create_info_.front.failOp = VK_STENCIL_OP_KEEP;
493 vk_pipeline_depth_stencil_state_create_info_.front.passOp = VK_STENCIL_OP_REPLACE;
494 vk_pipeline_depth_stencil_state_create_info_.front.depthFailOp = VK_STENCIL_OP_KEEP;
495 vk_pipeline_depth_stencil_state_create_info_.back =
496 vk_pipeline_depth_stencil_state_create_info_.front;
497 break;
498
500 vk_pipeline_depth_stencil_state_create_info_.front.failOp = VK_STENCIL_OP_KEEP;
501 vk_pipeline_depth_stencil_state_create_info_.front.passOp =
502 VK_STENCIL_OP_DECREMENT_AND_WRAP;
503 vk_pipeline_depth_stencil_state_create_info_.front.depthFailOp = VK_STENCIL_OP_KEEP;
504 vk_pipeline_depth_stencil_state_create_info_.back =
505 vk_pipeline_depth_stencil_state_create_info_.front;
506 vk_pipeline_depth_stencil_state_create_info_.back.passOp =
507 VK_STENCIL_OP_INCREMENT_AND_WRAP;
508 break;
509
511 vk_pipeline_depth_stencil_state_create_info_.front.failOp = VK_STENCIL_OP_KEEP;
512 vk_pipeline_depth_stencil_state_create_info_.front.passOp = VK_STENCIL_OP_KEEP;
513 vk_pipeline_depth_stencil_state_create_info_.front.depthFailOp =
514 VK_STENCIL_OP_INCREMENT_AND_WRAP;
515 vk_pipeline_depth_stencil_state_create_info_.back =
516 vk_pipeline_depth_stencil_state_create_info_.front;
517 vk_pipeline_depth_stencil_state_create_info_.back.depthFailOp =
518 VK_STENCIL_OP_DECREMENT_AND_WRAP;
519 break;
520
522 default:
523 vk_pipeline_depth_stencil_state_create_info_.front.failOp = VK_STENCIL_OP_KEEP;
524 vk_pipeline_depth_stencil_state_create_info_.front.passOp = VK_STENCIL_OP_KEEP;
525 vk_pipeline_depth_stencil_state_create_info_.front.depthFailOp = VK_STENCIL_OP_KEEP;
526 vk_pipeline_depth_stencil_state_create_info_.back =
527 vk_pipeline_depth_stencil_state_create_info_.front;
528 break;
529 }
530 }
531
532 /* VK_KHR_dynamic_rendering */
533 vk_pipeline_rendering_create_info_.depthAttachmentFormat =
535 vk_pipeline_rendering_create_info_.stencilAttachmentFormat =
537 vk_pipeline_rendering_create_info_.colorAttachmentCount =
539 vk_pipeline_rendering_create_info_.pColorAttachmentFormats =
541
542 /* Common values */
543 vk_graphics_pipeline_create_info_.layout = graphics_info.vk_pipeline_layout;
544 /* TODO: based on `vk_pipeline_base` we should update the flags. */
545 vk_graphics_pipeline_create_info_.basePipelineHandle = vk_pipeline_base;
546
547 /* Build pipeline. */
548 VKBackend &backend = VKBackend::get();
549 VKDevice &device = backend.device;
551
552 VkPipeline pipeline = VK_NULL_HANDLE;
553 vkCreateGraphicsPipelines(device.vk_handle(),
554 is_static_shader ? vk_pipeline_cache_static_ :
555 vk_pipeline_cache_non_static_,
556 1,
557 &vk_graphics_pipeline_create_info_,
558 vk_allocation_callbacks,
559 &pipeline);
560 graphic_pipelines_.add(graphics_info, pipeline);
561
562 /* Reset values to initial value. */
563 specialization_info_reset();
564 vk_graphics_pipeline_create_info_.stageCount = 0;
565 vk_graphics_pipeline_create_info_.layout = VK_NULL_HANDLE;
566 vk_graphics_pipeline_create_info_.basePipelineHandle = VK_NULL_HANDLE;
567 for (VkPipelineShaderStageCreateInfo &info :
568 MutableSpan<VkPipelineShaderStageCreateInfo>(vk_pipeline_shader_stage_create_info_, 3))
569 {
570 info.module = VK_NULL_HANDLE;
571 info.pSpecializationInfo = nullptr;
572 }
573 vk_pipeline_input_assembly_state_create_info_.topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
574 vk_pipeline_input_assembly_state_create_info_.primitiveRestartEnable = VK_TRUE;
575 vk_pipeline_vertex_input_state_create_info_.pVertexAttributeDescriptions = nullptr;
576 vk_pipeline_vertex_input_state_create_info_.vertexAttributeDescriptionCount = 0;
577 vk_pipeline_vertex_input_state_create_info_.pVertexBindingDescriptions = nullptr;
578 vk_pipeline_vertex_input_state_create_info_.vertexBindingDescriptionCount = 0;
579 vk_pipeline_rasterization_state_create_info_.frontFace = VK_FRONT_FACE_CLOCKWISE;
580 vk_pipeline_rasterization_state_create_info_.cullMode = VK_CULL_MODE_NONE;
581 vk_pipeline_rasterization_state_create_info_.depthBiasEnable = VK_FALSE;
582 vk_pipeline_rasterization_state_create_info_.depthBiasSlopeFactor = 0.0f;
583 vk_pipeline_rasterization_state_create_info_.depthBiasConstantFactor = 0.0f;
584 vk_pipeline_rasterization_state_create_info_.depthBiasClamp = 0.0f;
585 vk_pipeline_rasterization_state_create_info_.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
586 vk_pipeline_viewport_state_create_info_.pScissors = nullptr;
587 vk_pipeline_viewport_state_create_info_.scissorCount = 0;
588 vk_pipeline_viewport_state_create_info_.pViewports = nullptr;
589 vk_pipeline_viewport_state_create_info_.viewportCount = 0;
590 vk_pipeline_color_blend_state_create_info_.attachmentCount = 0;
591 vk_pipeline_color_blend_state_create_info_.pAttachments = nullptr;
592 vk_pipeline_rendering_create_info_.colorAttachmentCount = 0;
593 vk_pipeline_rendering_create_info_.depthAttachmentFormat = VK_FORMAT_UNDEFINED;
594 vk_pipeline_rendering_create_info_.pColorAttachmentFormats = nullptr;
595 vk_pipeline_rendering_create_info_.stencilAttachmentFormat = VK_FORMAT_UNDEFINED;
596 vk_pipeline_depth_stencil_state_create_info_.depthTestEnable = VK_FALSE;
597 vk_pipeline_depth_stencil_state_create_info_.depthWriteEnable = VK_FALSE;
598 vk_pipeline_depth_stencil_state_create_info_.depthCompareOp = VK_COMPARE_OP_NEVER;
599 vk_pipeline_depth_stencil_state_create_info_.stencilTestEnable = VK_FALSE;
600 vk_pipeline_depth_stencil_state_create_info_.front = {};
601 vk_pipeline_depth_stencil_state_create_info_.back = {};
602 vk_graphics_pipeline_create_info_.pDepthStencilState = nullptr;
603
604 return pipeline;
605}
606
608{
609 std::scoped_lock lock(mutex_);
610 Vector<VkPipeline> pipelines_to_destroy;
611 compute_pipelines_.remove_if([&](auto item) {
612 if (vk_shader_modules.contains(item.key.vk_shader_module)) {
613 pipelines_to_destroy.append(item.value);
614 return true;
615 }
616 return false;
617 });
618 graphic_pipelines_.remove_if([&](auto item) {
619 if (vk_shader_modules.contains(item.key.pre_rasterization.vk_vertex_module) ||
620 vk_shader_modules.contains(item.key.pre_rasterization.vk_geometry_module) ||
621 vk_shader_modules.contains(item.key.fragment_shader.vk_fragment_module))
622 {
623 pipelines_to_destroy.append(item.value);
624 return true;
625 }
626 return false;
627 });
628
629 VKDevice &device = VKBackend::get().device;
631 for (VkPipeline vk_pipeline : pipelines_to_destroy) {
632 vkDestroyPipeline(device.vk_handle(), vk_pipeline, vk_allocation_callbacks);
633 }
634}
635
637{
638 std::scoped_lock lock(mutex_);
639 VKDevice &device = VKBackend::get().device;
641 for (VkPipeline &vk_pipeline : graphic_pipelines_.values()) {
642 vkDestroyPipeline(device.vk_handle(), vk_pipeline, vk_allocation_callbacks);
643 }
644 graphic_pipelines_.clear();
645 for (VkPipeline &vk_pipeline : compute_pipelines_.values()) {
646 vkDestroyPipeline(device.vk_handle(), vk_pipeline, vk_allocation_callbacks);
647 }
648 compute_pipelines_.clear();
649
650 vkDestroyPipelineCache(device.vk_handle(), vk_pipeline_cache_static_, vk_allocation_callbacks);
651 vkDestroyPipelineCache(
652 device.vk_handle(), vk_pipeline_cache_non_static_, vk_allocation_callbacks);
653}
654
655/* -------------------------------------------------------------------- */
659#ifdef WITH_BUILDINFO
660struct VKPipelineCachePrefixHeader {
661 /* 'B'lender 'C'ache + 2 bytes for file versioning. */
662 uint32_t magic = 0xBC00;
663 uint32_t blender_version = BLENDER_VERSION;
664 uint32_t blender_subversion = BLENDER_VERSION_PATCH;
665 char commit_hash[8];
666 uint32_t data_size;
667 uint32_t vendor_id;
668 uint32_t device_id;
669 uint32_t driver_version;
670 uint8_t pipeline_cache_uuid[VK_UUID_SIZE];
671
672 VKPipelineCachePrefixHeader()
673 {
674 const VKDevice &device = VKBackend::get().device;
675 data_size = 0;
676 const VkPhysicalDeviceProperties &properties = device.physical_device_properties_get();
677 vendor_id = properties.vendorID;
678 device_id = properties.deviceID;
679 driver_version = properties.driverVersion;
680 memcpy(&pipeline_cache_uuid, &properties.pipelineCacheUUID, VK_UUID_SIZE);
681
682 memset(commit_hash, 0, sizeof(commit_hash));
683 STRNCPY(commit_hash, build_hash);
684 }
685};
686
687static std::string pipeline_cache_filepath_get()
688{
689 static char tmp_dir_buffer[1024];
690 BKE_appdir_folder_caches(tmp_dir_buffer, sizeof(tmp_dir_buffer));
691
692 std::string cache_dir = std::string(tmp_dir_buffer) + "vk-pipeline-cache" + SEP_STR;
693 BLI_dir_create_recursive(cache_dir.c_str());
694 std::string cache_file = cache_dir + "static.bin";
695 return cache_file;
696}
697#endif
698
700{
701#ifdef WITH_BUILDINFO
702 /* Don't read the shader cache when GPU debugging is enabled. When enabled we use different
703 * shaders and compilation settings. Previous generated pipelines will not be used. */
704 if (bool(G.debug & G_DEBUG_GPU)) {
705 return;
706 }
707
708 std::string cache_file = pipeline_cache_filepath_get();
709 if (!BLI_exists(cache_file.c_str())) {
710 return;
711 }
712
713 /* Prevent old cache files from being deleted if they're still being used. */
714 BLI_file_touch(cache_file.c_str());
715 /* Read cached binary. */
716 fstream file(cache_file, std::ios::binary | std::ios::in | std::ios::ate);
717 std::streamsize data_size = file.tellg();
718 file.seekg(0, std::ios::beg);
719 void *buffer = MEM_mallocN(data_size, __func__);
720 file.read(reinterpret_cast<char *>(buffer), data_size);
721 file.close();
722
723 /* Validate the prefix header. */
724 VKPipelineCachePrefixHeader prefix;
725 VKPipelineCachePrefixHeader &read_prefix = *static_cast<VKPipelineCachePrefixHeader *>(buffer);
726 prefix.data_size = read_prefix.data_size;
727 if (memcmp(&read_prefix, &prefix, sizeof(VKPipelineCachePrefixHeader)) != 0) {
728 /* Headers are different, most likely the cache will not work and potentially crash the driver.
729 * [https://medium.com/@zeuxcg/creating-a-robust-pipeline-cache-with-vulkan-961d09416cda]
730 */
731 MEM_freeN(buffer);
732 CLOG_INFO(&LOG,
733 1,
734 "Pipeline cache on disk [%s] is ignored as it was written by a different driver or "
735 "Blender version. Cache will be overwritten when exiting.",
736 cache_file.c_str());
737 return;
738 }
739
740 CLOG_INFO(&LOG, 1, "Initialize static pipeline cache from disk [%s].", cache_file.c_str());
741 VKDevice &device = VKBackend::get().device;
742 VkPipelineCacheCreateInfo create_info = {};
743 create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
744 create_info.initialDataSize = read_prefix.data_size;
745 create_info.pInitialData = static_cast<uint8_t *>(buffer) + sizeof(VKPipelineCachePrefixHeader);
746 VkPipelineCache vk_pipeline_cache = VK_NULL_HANDLE;
747 vkCreatePipelineCache(device.vk_handle(), &create_info, nullptr, &vk_pipeline_cache);
748 MEM_freeN(buffer);
749
750 vkMergePipelineCaches(device.vk_handle(), vk_pipeline_cache_static_, 1, &vk_pipeline_cache);
751 vkDestroyPipelineCache(device.vk_handle(), vk_pipeline_cache, nullptr);
752#endif
753}
754
756{
757#ifdef WITH_BUILDINFO
758 /* Don't write the pipeline cache when GPU debugging is enabled. When enabled we use different
759 * shaders and compilation settings. Writing them to disk will clutter the pipeline cache. */
760 if (bool(G.debug & G_DEBUG_GPU)) {
761 return;
762 }
763
764 VKDevice &device = VKBackend::get().device;
765 size_t data_size;
766 vkGetPipelineCacheData(device.vk_handle(), vk_pipeline_cache_static_, &data_size, nullptr);
767 void *buffer = MEM_mallocN(data_size, __func__);
768 vkGetPipelineCacheData(device.vk_handle(), vk_pipeline_cache_static_, &data_size, buffer);
769
770 std::string cache_file = pipeline_cache_filepath_get();
771 CLOG_INFO(&LOG, 1, "Writing static pipeline cache to disk [%s].", cache_file.c_str());
772
773 fstream file(cache_file, std::ios::binary | std::ios::out);
774
775 VKPipelineCachePrefixHeader header;
776 header.data_size = data_size;
777 file.write(reinterpret_cast<char *>(&header), sizeof(VKPipelineCachePrefixHeader));
778 file.write(static_cast<char *>(buffer), data_size);
779
780 MEM_freeN(buffer);
781#endif
782}
783
784/* \} */
785
786} // namespace blender::gpu
bool BKE_appdir_folder_caches(char *path, size_t path_maxncpy) ATTR_NONNULL(1)
Definition appdir.cc:226
#define BLENDER_VERSION_PATCH
#define BLENDER_VERSION
@ G_DEBUG_GPU
#define BLI_assert(a)
Definition BLI_assert.h:50
bool BLI_file_touch(const char *filepath) ATTR_NONNULL(1)
Definition fileops_c.cc:316
int BLI_exists(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition storage.cc:350
bool BLI_dir_create_recursive(const char *dirname) ATTR_NONNULL()
Definition fileops_c.cc:391
File and directory operations.
#define STRNCPY(dst, src)
Definition BLI_string.h:593
#define ELEM(...)
#define CLOG_INFO(clg_ref, level,...)
Definition CLG_log.h:179
@ GPU_BLEND_ADDITIVE_PREMULT
Definition GPU_state.hh:90
@ GPU_BLEND_INVERT
Definition GPU_state.hh:95
@ GPU_BLEND_OIT
Definition GPU_state.hh:98
@ GPU_BLEND_MULTIPLY
Definition GPU_state.hh:91
@ GPU_BLEND_NONE
Definition GPU_state.hh:85
@ GPU_BLEND_ALPHA
Definition GPU_state.hh:87
@ GPU_BLEND_CUSTOM
Definition GPU_state.hh:103
@ GPU_BLEND_ADDITIVE
Definition GPU_state.hh:89
@ GPU_BLEND_SUBTRACT
Definition GPU_state.hh:92
@ GPU_BLEND_ALPHA_UNDER_PREMUL
Definition GPU_state.hh:104
@ GPU_BLEND_BACKGROUND
Definition GPU_state.hh:100
@ GPU_BLEND_ALPHA_PREMULT
Definition GPU_state.hh:88
@ GPU_WRITE_RED
Definition GPU_state.hh:18
@ GPU_WRITE_GREEN
Definition GPU_state.hh:19
@ GPU_WRITE_BLUE
Definition GPU_state.hh:20
@ GPU_WRITE_DEPTH
Definition GPU_state.hh:22
@ GPU_WRITE_ALPHA
Definition GPU_state.hh:21
eGPUFaceCullTest
Definition GPU_state.hh:132
@ GPU_STENCIL_OP_COUNT_DEPTH_FAIL
Definition GPU_state.hh:129
@ GPU_STENCIL_OP_COUNT_DEPTH_PASS
Definition GPU_state.hh:128
@ GPU_STENCIL_OP_REPLACE
Definition GPU_state.hh:126
@ GPU_STENCIL_OP_NONE
Definition GPU_state.hh:125
@ GPU_DEPTH_GREATER
Definition GPU_state.hh:113
@ GPU_DEPTH_EQUAL
Definition GPU_state.hh:112
@ GPU_DEPTH_ALWAYS
Definition GPU_state.hh:109
@ GPU_DEPTH_GREATER_EQUAL
Definition GPU_state.hh:114
@ GPU_DEPTH_LESS
Definition GPU_state.hh:110
@ GPU_DEPTH_LESS_EQUAL
Definition GPU_state.hh:111
@ GPU_DEPTH_NONE
Definition GPU_state.hh:108
@ GPU_STENCIL_EQUAL
Definition GPU_state.hh:120
@ GPU_STENCIL_NEQUAL
Definition GPU_state.hh:121
@ GPU_STENCIL_ALWAYS
Definition GPU_state.hh:119
@ GPU_STENCIL_NONE
Definition GPU_state.hh:118
volatile int lock
constexpr const T * data() const
Definition BLI_span.hh:216
constexpr int64_t size() const
Definition BLI_span.hh:253
constexpr bool is_empty() const
Definition BLI_span.hh:261
constexpr bool contains(const T &value) const
Definition BLI_span.hh:278
int64_t size() const
void append(const T &value)
void append_n_times(const T &value, const int64_t n)
static VKBackend & get()
Definition vk_backend.hh:92
VkDevice vk_handle() const
Definition vk_device.hh:224
const VkPhysicalDeviceProperties & physical_device_properties_get() const
Definition vk_device.hh:199
VkPipeline get_or_create_compute_pipeline(VKComputeInfo &compute_info, bool is_static_shader, VkPipeline vk_pipeline_base)
VkPipeline get_or_create_graphics_pipeline(VKGraphicsInfo &graphics_info, bool is_static_shader, VkPipeline vk_pipeline_base)
void remove(Span< VkShaderModule > vk_shader_modules)
FILE * file
char build_hash[16]
#define LOG(severity)
Definition log.h:33
void *(* MEM_mallocN)(size_t len, const char *str)
Definition mallocn.cc:44
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
#define G(x, y, z)
static CLG_LogRef LOG
VkCullModeFlags to_vk_cull_mode_flags(const eGPUFaceCullTest cull_test)
Definition vk_common.cc:885
unsigned int uint32_t
Definition stdint.h:80
unsigned char uint8_t
Definition stdint.h:78
Vector< shader::SpecializationConstant::Value > specialization_constants
VkPipelineLayout vk_pipeline_layout
Vector< VkVertexInputBindingDescription > bindings
Vector< VkVertexInputAttributeDescription > attributes
Vector< shader::SpecializationConstant::Value > specialization_constants
static int magic(const Tex *tex, const float texvec[3], TexResult *texres)
#define SEP_STR
Definition unit.cc:39
#define VK_ALLOCATION_CALLBACKS
Definition vk_memory.hh:58