Blender V5.0
vk_backend.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2022 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <sstream>
10
11#include "GHOST_C-api.h"
12
13#include "BLI_path_utils.hh"
14#include "BLI_threads.h"
15
16#include "CLG_log.h"
17
18#include "GPU_capabilities.hh"
21
22#include "vk_batch.hh"
23#include "vk_context.hh"
24#include "vk_fence.hh"
25#include "vk_framebuffer.hh"
26#include "vk_ghost_api.hh"
27#include "vk_index_buffer.hh"
28#include "vk_pixel_buffer.hh"
29#include "vk_query.hh"
30#include "vk_shader.hh"
31#include "vk_state_manager.hh"
32#include "vk_storage_buffer.hh"
33#include "vk_texture.hh"
34#include "vk_uniform_buffer.hh"
35#include "vk_vertex_buffer.hh"
36
37#include "vk_backend.hh"
38
39static CLG_LogRef LOG = {"gpu.vulkan"};
40
41namespace blender::gpu {
42
43static const char *vk_extension_get(int index)
44{
46}
47
48bool GPU_vulkan_is_supported_driver(VkPhysicalDevice vk_physical_device)
49{
50 /* Check for known faulty drivers. */
51 VkPhysicalDeviceProperties2 vk_physical_device_properties = {};
52 VkPhysicalDeviceDriverProperties vk_physical_device_driver_properties = {};
53 vk_physical_device_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
54 vk_physical_device_driver_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES;
55 vk_physical_device_properties.pNext = &vk_physical_device_driver_properties;
56 vkGetPhysicalDeviceProperties2(vk_physical_device, &vk_physical_device_properties);
57
58#ifdef _WIN32
59 /* Intel IRIS on 10th gen CPU (and older) crashes with drivers before 101.2140 due to multiple
60 * driver issues.
61 *
62 * 1) Workbench is working, but EEVEE pipelines are failing. Calling vkCreateGraphicsPipelines
63 * for certain EEVEE shaders (Shadow, Deferred rendering) would return with VK_SUCCESS, but
64 * without a created VkPipeline handle.
65 *
66 * 2) When vkCmdBeginRendering is called some requirements need to be met, that can only be met
67 * when actually calling a vkCmdDraw* command. According to the Vulkan specs the requirements
68 * should only be met when calling a vkCmdDraw* command.
69 */
70 if (vk_physical_device_driver_properties.driverID == VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS &&
71 vk_physical_device_properties.properties.deviceType ==
72 VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU)
73 {
74 const uint32_t driver_version = vk_physical_device_properties.properties.driverVersion;
75 uint32_t driver_version_major = driver_version >> 14u;
76 uint32_t driver_version_minor = driver_version & 0x3fffu;
77 if (driver_version_major < 101 || driver_version_major == 101 && driver_version_minor < 2140) {
78 return false;
79 }
80 }
81#endif
82
83#ifndef _WIN32
84 /* NVIDIA drivers below 550 don't work on Linux. When sending command to the GPU there is not
85 * always a reply back when they are finished. The issue is reported on the Internet many times,
86 * but there is no mention of a solution. This means that on Linux we can only support GTX900 and
87 * or use MesaNVK.
88 */
89 uint32_t conformance_version = VK_MAKE_API_VERSION(
90 vk_physical_device_driver_properties.conformanceVersion.major,
91 vk_physical_device_driver_properties.conformanceVersion.minor,
92 vk_physical_device_driver_properties.conformanceVersion.subminor,
93 vk_physical_device_driver_properties.conformanceVersion.patch);
94 if (vk_physical_device_driver_properties.driverID == VK_DRIVER_ID_NVIDIA_PROPRIETARY &&
95 conformance_version < VK_MAKE_API_VERSION(1, 3, 7, 2))
96 {
97 return false;
98 }
99
100 /* NVIDIA driver 580.76.05 doesn't start using specific Wayland configurations #144625. There are
101 * multiple reports also not Blender related and NVIDIA mentions that a new driver will be
102 * released. It is unclear if that driver will fix our issue. For now disabling this driver on
103 * Linux. This also disables it for configurations that are working as well (including X11). */
104 if (vk_physical_device_driver_properties.driverID == VK_DRIVER_ID_NVIDIA_PROPRIETARY &&
105 ((StringRefNull(vk_physical_device_driver_properties.driverInfo).find("580.76.5", 0) !=
107 (StringRefNull(vk_physical_device_driver_properties.driverInfo).find("580.76.05", 0) !=
109 {
110 return false;
111 }
112#endif
113
114#ifdef _WIN32
115 if (vk_physical_device_driver_properties.driverID == VK_DRIVER_ID_QUALCOMM_PROPRIETARY) {
116 /* Any Qualcomm driver older than 31.0.112.0 will not be capable of running blender due
117 * to an issue in their semaphore timeline implementation. The driver could return
118 * timelines that have not been provided by Blender. As Blender uses timelines for resource
119 * management this resulted in resources to be destroyed, that are still in use. */
120
121 /* Public version 31.0.112 uses vulkan driver version 512.827.0. */
122 const uint32_t driver_version = vk_physical_device_properties.properties.driverVersion;
123 constexpr uint32_t version_31_0_112 = VK_MAKE_VERSION(512, 827, 0);
124 if (driver_version < version_31_0_112) {
125 CLOG_WARN(&LOG,
126 "Detected qualcomm driver is not supported. To run the Vulkan backend "
127 "driver 31.0.112.0 or later is required. Switching to OpenGL.");
128 return false;
129 }
130 }
131#endif
132
133 return true;
134}
135
136static Vector<StringRefNull> missing_capabilities_get(VkPhysicalDevice vk_physical_device)
137{
138 Vector<StringRefNull> missing_capabilities;
139 /* Check device features. */
140 VkPhysicalDeviceVulkan12Features features_12 = {
141 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES};
142 VkPhysicalDeviceVulkan11Features features_11 = {
143 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES, &features_12};
144 VkPhysicalDeviceFeatures2 features = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
145 &features_11};
146
147 vkGetPhysicalDeviceFeatures2(vk_physical_device, &features);
148
149#ifndef __APPLE__
150 if (features.features.geometryShader == VK_FALSE) {
151 missing_capabilities.append("geometry shaders");
152 }
153 if (features.features.logicOp == VK_FALSE) {
154 missing_capabilities.append("logical operations");
155 }
156#endif
157 if (features.features.dualSrcBlend == VK_FALSE) {
158 missing_capabilities.append("dual source blending");
159 }
160 if (features.features.imageCubeArray == VK_FALSE) {
161 missing_capabilities.append("image cube array");
162 }
163 if (features.features.multiDrawIndirect == VK_FALSE) {
164 missing_capabilities.append("multi draw indirect");
165 }
166 if (features.features.multiViewport == VK_FALSE) {
167 missing_capabilities.append("multi viewport");
168 }
169 if (features.features.shaderClipDistance == VK_FALSE) {
170 missing_capabilities.append("shader clip distance");
171 }
172 if (features.features.drawIndirectFirstInstance == VK_FALSE) {
173 missing_capabilities.append("draw indirect first instance");
174 }
175 if (features.features.fragmentStoresAndAtomics == VK_FALSE) {
176 missing_capabilities.append("fragment stores and atomics");
177 }
178 if (features_11.shaderDrawParameters == VK_FALSE) {
179 missing_capabilities.append("shader draw parameters");
180 }
181 if (features_12.timelineSemaphore == VK_FALSE) {
182 missing_capabilities.append("timeline semaphores");
183 }
184 if (features_12.bufferDeviceAddress == VK_FALSE) {
185 missing_capabilities.append("buffer device address");
186 }
187
188 /* Check device extensions. */
189 uint32_t vk_extension_count;
190 vkEnumerateDeviceExtensionProperties(vk_physical_device, nullptr, &vk_extension_count, nullptr);
191
192 Array<VkExtensionProperties> vk_extensions(vk_extension_count);
193 vkEnumerateDeviceExtensionProperties(
194 vk_physical_device, nullptr, &vk_extension_count, vk_extensions.data());
195 Set<StringRefNull> extensions;
196 for (VkExtensionProperties &vk_extension : vk_extensions) {
197 extensions.add(vk_extension.extensionName);
198 }
199
200 if (!extensions.contains(VK_KHR_SWAPCHAIN_EXTENSION_NAME)) {
201 missing_capabilities.append(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
202 }
203 if (!extensions.contains(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME)) {
204 missing_capabilities.append(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME);
205 }
206#ifndef __APPLE__
207 /* Metal doesn't support provoking vertex. */
208 if (!extensions.contains(VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME)) {
209 missing_capabilities.append(VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME);
210 }
211#endif
212
213 return missing_capabilities;
214}
215
217{
219
220 /*
221 * Disable implicit layers and only allow layers that we trust.
222 *
223 * Render doc layer is hidden behind a debug flag. There are malicious layers that impersonate
224 * RenderDoc and can crash when loaded. See #139543
225 */
226 std::stringstream allowed_layers;
227 allowed_layers << "VK_LAYER_KHRONOS_*";
228 allowed_layers << ",VK_LAYER_AMD_*";
229 allowed_layers << ",VK_LAYER_INTEL_*";
230 allowed_layers << ",VK_LAYER_NV_*";
231 allowed_layers << ",VK_LAYER_MESA_*";
232 if (bool(G.debug & G_DEBUG_GPU)) {
233 allowed_layers << ",VK_LAYER_LUNARG_*";
234 allowed_layers << ",VK_LAYER_RENDERDOC_*";
235 }
236 BLI_setenv("VK_LOADER_LAYERS_DISABLE", "~implicit~");
237 BLI_setenv("VK_LOADER_LAYERS_ALLOW", allowed_layers.str().c_str());
238
239 /* Initialize an vulkan 1.2 instance. */
240 VkApplicationInfo vk_application_info = {VK_STRUCTURE_TYPE_APPLICATION_INFO};
241 vk_application_info.pApplicationName = "Blender";
242 vk_application_info.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
243 vk_application_info.pEngineName = "Blender";
244 vk_application_info.engineVersion = VK_MAKE_VERSION(1, 0, 0);
245 vk_application_info.apiVersion = VK_API_VERSION_1_2;
246
247 VkInstanceCreateInfo vk_instance_info = {VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO};
248 vk_instance_info.pApplicationInfo = &vk_application_info;
249
250 VkInstance vk_instance = VK_NULL_HANDLE;
251 vkCreateInstance(&vk_instance_info, nullptr, &vk_instance);
252 if (vk_instance == VK_NULL_HANDLE) {
253 CLOG_ERROR(&LOG, "Unable to initialize a Vulkan 1.2 instance.");
254 return false;
255 }
256
257 /* Go over all the devices. */
258 uint32_t physical_devices_count = 0;
259 vkEnumeratePhysicalDevices(vk_instance, &physical_devices_count, nullptr);
260 Array<VkPhysicalDevice> vk_physical_devices(physical_devices_count);
261 vkEnumeratePhysicalDevices(vk_instance, &physical_devices_count, vk_physical_devices.data());
262
263 for (VkPhysicalDevice vk_physical_device : vk_physical_devices) {
264 VkPhysicalDeviceProperties vk_properties = {};
265 vkGetPhysicalDeviceProperties(vk_physical_device, &vk_properties);
266
267 if (!GPU_vulkan_is_supported_driver(vk_physical_device)) {
268 CLOG_WARN(&LOG,
269 "Installed driver for device [%s] has known issues and will not be used. Updating "
270 "driver might improve compatibility.",
271 vk_properties.deviceName);
272 continue;
273 }
274 Vector<StringRefNull> missing_capabilities = missing_capabilities_get(vk_physical_device);
275
276 /* Report result. */
277 if (missing_capabilities.is_empty()) {
278 /* This device meets minimum requirements. */
280 &LOG,
281 "Device [%s] supports minimum requirements. Skip checking other GPUs. Another GPU "
282 "can still be selected during auto-detection.",
283 vk_properties.deviceName);
284
285 vkDestroyInstance(vk_instance, nullptr);
286 return true;
287 }
288
289 std::stringstream ss;
290 ss << "Device [" << vk_properties.deviceName
291 << "] does not meet minimum requirements. Missing features are [";
292 for (StringRefNull &feature : missing_capabilities) {
293 ss << feature << ", ";
294 }
295 ss.seekp(-2, std::ios_base::end);
296 ss << "]";
297 CLOG_WARN(&LOG, "%s", ss.str().c_str());
298 }
299
300 /* No device found meeting the minimum requirements. */
301
302 vkDestroyInstance(vk_instance, nullptr);
304 "No Vulkan device found that meets the minimum requirements. "
305 "Updating GPU driver can improve compatibility.");
306 return false;
307}
308
310{
311#ifdef _WIN32
312 return GPU_OS_WIN;
313#elif defined(__APPLE__)
314 return GPU_OS_MAC;
315#else
316 return GPU_OS_UNIX;
317#endif
318}
319
321{
327 "",
328 "",
329 "",
331}
332
333static void init_device_list(GHOST_ContextHandle ghost_context)
334{
335 GHOST_VulkanHandles vulkan_handles = {};
336 GHOST_GetVulkanHandles(ghost_context, &vulkan_handles);
337
338 uint32_t physical_devices_count = 0;
339 vkEnumeratePhysicalDevices(vulkan_handles.instance, &physical_devices_count, nullptr);
340 Array<VkPhysicalDevice> vk_physical_devices(physical_devices_count);
341 vkEnumeratePhysicalDevices(
342 vulkan_handles.instance, &physical_devices_count, vk_physical_devices.data());
343 int index = 0;
344 for (VkPhysicalDevice vk_physical_device : vk_physical_devices) {
345 if (missing_capabilities_get(vk_physical_device).is_empty() &&
346 GPU_vulkan_is_supported_driver(vk_physical_device))
347 {
348 VkPhysicalDeviceProperties vk_properties = {};
349 vkGetPhysicalDeviceProperties(vk_physical_device, &vk_properties);
350 std::stringstream identifier;
351 identifier << std::hex << vk_properties.vendorID << "/" << vk_properties.deviceID << "/"
352 << index;
353 GPG.devices.append({identifier.str(),
354 index,
355 vk_properties.vendorID,
356 vk_properties.deviceID,
357 std::string(vk_properties.deviceName)});
358 }
359 index++;
360 }
361
362 std::sort(GPG.devices.begin(), GPG.devices.end(), [&](const GPUDevice &a, const GPUDevice &b) {
363 if (a.name == b.name) {
364 return a.index < b.index;
365 }
366 return a.name < b.name;
367 });
368}
369
371{
372 const VkPhysicalDeviceProperties &properties = device.physical_device_properties_get();
373
374 GPUDeviceType device_type = device.device_type();
375 GPUDriverType driver = device.driver_type();
378
379 std::string vendor_name = device.vendor_name();
380 std::string driver_version = device.driver_version();
381
382 /* GPG has already been initialized, but without a specific device. Calling init twice will
383 * clear the list of devices. Making a copy of the device list and set it after initialization to
384 * make sure the list isn't destroyed at this moment, but only when the backend is destroyed. */
385 Vector<GPUDevice> devices = GPG.devices;
386 GPG.init(device_type,
387 os,
388 driver,
389 support_level,
391 vendor_name.c_str(),
392 properties.deviceName,
393 driver_version.c_str(),
395 GPG.devices = devices;
396
397 const VkPhysicalDeviceIDProperties &id_properties = device.physical_device_id_properties_get();
398
399 GPG.device_uuid = Array<uint8_t, 16>(Span<uint8_t>(id_properties.deviceUUID, VK_UUID_SIZE));
400
401 if (id_properties.deviceLUIDValid) {
402 GPG.device_luid = Array<uint8_t, 8>(Span<uint8_t>(id_properties.deviceUUID, VK_LUID_SIZE));
403 GPG.device_luid_node_mask = id_properties.deviceNodeMask;
404 }
405 else {
406 GPG.device_luid.reinitialize(0);
407 GPG.device_luid_node_mask = 0;
408 }
409
410 CLOG_INFO(&LOG,
411 "Using vendor [%s] device [%s] driver version [%s].",
412 vendor_name.c_str(),
413 device.vk_physical_device_properties_.deviceName,
414 driver_version.c_str());
415}
416
417void VKBackend::detect_workarounds(VKDevice &device)
418{
419 VKWorkarounds workarounds;
420 VKExtensions extensions;
421
422 if (G.debug & G_DEBUG_GPU_FORCE_WORKAROUNDS) {
423 printf("\n");
424 printf("VK: Forcing workaround usage and disabling features and extensions.\n");
425 printf(" Vendor: %s\n", device.vendor_name().c_str());
426 printf(" Device: %s\n", device.physical_device_properties_get().deviceName);
427 printf(" Driver: %s\n", device.driver_version().c_str());
428 /* Force workarounds and disable extensions. */
429 workarounds.not_aligned_pixel_formats = true;
430 workarounds.vertex_formats.r8g8b8 = true;
431 extensions.shader_output_layer = false;
432 extensions.shader_output_viewport_index = false;
433 extensions.fragment_shader_barycentric = false;
434 extensions.dynamic_rendering_local_read = false;
435 extensions.dynamic_rendering_unused_attachments = false;
436 extensions.descriptor_buffer = false;
437 extensions.pageable_device_local_memory = false;
438 extensions.wide_lines = false;
439 GCaps.stencil_export_support = false;
440
441 device.workarounds_ = workarounds;
442 device.extensions_ = extensions;
443 return;
444 }
445
446 extensions.shader_output_layer =
447 device.physical_device_vulkan_12_features_get().shaderOutputLayer;
449 device.physical_device_vulkan_12_features_get().shaderOutputViewportIndex;
450 extensions.wide_lines = device.physical_device_features_get().wideLines;
452 VK_KHR_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME);
454 VK_KHR_DYNAMIC_RENDERING_LOCAL_READ_EXTENSION_NAME);
456 VK_EXT_DYNAMIC_RENDERING_UNUSED_ATTACHMENTS_EXTENSION_NAME);
457 extensions.logic_ops = device.physical_device_features_get().logicOp;
458 /* For stability reasons descriptor buffers have been disabled. */
459#if 0
460 extensions.descriptor_buffer = device.supports_extension(
461 VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME);
462#endif
463 extensions.maintenance4 = device.supports_extension(VK_KHR_MAINTENANCE_4_EXTENSION_NAME);
464 extensions.memory_priority = device.supports_extension(VK_EXT_MEMORY_PRIORITY_EXTENSION_NAME);
466 VK_EXT_PAGEABLE_DEVICE_LOCAL_MEMORY_EXTENSION_NAME);
467#ifdef _WIN32
468 extensions.external_memory = device.supports_extension(
469 VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME);
470#elif not defined(__APPLE__)
471 extensions.external_memory = device.supports_extension(VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME);
472#else
473 extensions.external_memory = false;
474#endif
475
476 /* Descriptor buffers are disabled on the NVIDIA platform due to performance regressions. Both
477 * still seem to be faster than OpenGL.
478 *
479 * See #140125
480 */
481 if (device.vk_physical_device_driver_properties_.driverID == VK_DRIVER_ID_NVIDIA_PROPRIETARY) {
482 extensions.descriptor_buffer = false;
483 }
484
485 /* Running render tests fails consistently in some scenes. The cause is that too many descriptor
486 * sets are required for rendering resulting in failing allocations of the descriptor buffer. We
487 * work around this issue by not using descriptor buffers on these platforms.
488 *
489 * TODO: recheck when the backed memory gets freed and how to improve it.
490 *
491 * See #141476
492 */
493 if (device.vk_physical_device_driver_properties_.driverID ==
494 VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS)
495 {
496 extensions.descriptor_buffer = false;
497 }
498
499 /* AMD GPUs don't support texture formats that use are aligned to 24 or 48 bits. */
502 {
503 workarounds.not_aligned_pixel_formats = true;
504 }
505
506 /* Only enable by default dynamic rendering local read on Qualcomm devices. NVIDIA, AMD and Intel
507 * performance is better when disabled (20%). On Qualcomm devices the improvement can be
508 * substantial (16% on shader_balls.blend).
509 *
510 * `--debug-gpu-vulkan-local-read` can be used to use dynamic rendering local read on any
511 * supported platform.
512 *
513 * TODO: Check if bottleneck is during command building. If so we could fine-tune this after the
514 * device command building landed (T132682).
515 */
516 if ((G.debug & G_DEBUG_GPU_FORCE_VULKAN_LOCAL_READ) == 0 &&
518 {
519 extensions.dynamic_rendering_local_read = false;
520 }
521
522 VkFormatProperties format_properties = {};
523 vkGetPhysicalDeviceFormatProperties(
524 device.physical_device_get(), VK_FORMAT_R8G8B8_UNORM, &format_properties);
525 workarounds.vertex_formats.r8g8b8 = (format_properties.bufferFeatures &
526 VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT) == 0;
527
528 device.workarounds_ = workarounds;
529 device.extensions_ = extensions;
530}
531
532void VKBackend::platform_exit()
533{
534 GPG.clear();
535 VKDevice &device = VKBackend::get().device;
536 if (device.is_initialized()) {
537 device.deinit();
538 }
539}
540
542{
543 compiler_ = MEM_new<ShaderCompiler>(
545}
546
548{
549 MEM_delete(compiler_);
550}
551
553{
554 VKDevice &device = VKBackend::get().device;
555 if (device.is_initialized()) {
556 device.reinit();
557 }
558}
559
560void VKBackend::compute_dispatch(int groups_x_len, int groups_y_len, int groups_z_len)
561{
562 VKContext &context = *VKContext::get();
563 render_graph::VKResourceAccessInfo &resources = context.reset_and_get_access_info();
564 render_graph::VKDispatchNode::CreateInfo dispatch_info(resources);
565 context.update_pipeline_data(dispatch_info.dispatch_node.pipeline_data);
566 dispatch_info.dispatch_node.group_count_x = groups_x_len;
567 dispatch_info.dispatch_node.group_count_y = groups_y_len;
568 dispatch_info.dispatch_node.group_count_z = groups_z_len;
569 context.render_graph().add_node(dispatch_info);
570}
571
573{
574 BLI_assert(indirect_buf);
575 VKContext &context = *VKContext::get();
576 VKStorageBuffer &indirect_buffer = *unwrap(indirect_buf);
577 render_graph::VKResourceAccessInfo &resources = context.reset_and_get_access_info();
578 render_graph::VKDispatchIndirectNode::CreateInfo dispatch_indirect_info(resources);
579 context.update_pipeline_data(dispatch_indirect_info.dispatch_indirect_node.pipeline_data);
580 dispatch_indirect_info.dispatch_indirect_node.buffer = indirect_buffer.vk_handle();
581 dispatch_indirect_info.dispatch_indirect_node.offset = 0;
582 context.render_graph().add_node(dispatch_indirect_info);
583}
584
585Context *VKBackend::context_alloc(void *ghost_window, void *ghost_context)
586{
587 if (ghost_window) {
588 BLI_assert(ghost_context == nullptr);
589 ghost_context = GHOST_GetDrawingContext((GHOST_WindowHandle)ghost_window);
590 }
591
592 BLI_assert(ghost_context != nullptr);
593 if (!device.is_initialized()) {
594 device.init(ghost_context);
595 device.extensions_get().log();
596 init_device_list((GHOST_ContextHandle)ghost_context);
597 }
598
599 VKContext *context = new VKContext(ghost_window, ghost_context);
600 device.context_register(*context);
601 GHOST_SetVulkanSwapBuffersCallbacks((GHOST_ContextHandle)ghost_context,
606
607 return context;
608}
609
611{
612 return new VKBatch();
613}
614
616{
617 return new VKFence();
618}
619
621{
622 return new VKFrameBuffer(name);
623}
624
626{
627 return new VKIndexBuffer();
628}
629
631{
632 return new VKPixelBuffer(size);
633}
634
636{
637 return new VKQueryPool();
638}
639
641{
642 return new VKShader(name);
643}
644
646{
647 return new VKTexture(name);
648}
649
651{
652 return new VKUniformBuffer(size, name);
653}
654
656{
657 return new VKStorageBuffer(size, usage, name);
658}
659
661{
662 return new VKVertexBuffer();
663}
664
666{
667 VKThreadData &thread_data = device.current_thread_data();
668 BLI_assert_msg(thread_data.rendering_depth >= 0, "Unbalanced `GPU_render_begin/end`");
669 thread_data.rendering_depth += 1;
670}
671
673{
674 VKThreadData &thread_data = device.current_thread_data();
675 thread_data.rendering_depth -= 1;
676 BLI_assert_msg(thread_data.rendering_depth >= 0, "Unbalanced `GPU_render_begin/end`");
677 if (G.background) {
678 if (thread_data.rendering_depth == 0) {
679 VKContext *context = VKContext::get();
680 if (context != nullptr) {
681 context->flush();
682 }
683 std::scoped_lock lock(device.orphaned_data.mutex_get());
684 device.orphaned_data.move_data(device.orphaned_data_render,
685 device.orphaned_data.timeline_ + 1);
686 }
687 }
688
689 /* When performing animation render we want to release any discarded resources during rendering
690 * after each frame.
691 */
692 if (G.is_rendering && thread_data.rendering_depth == 0 && !BLI_thread_is_main()) {
693 std::scoped_lock lock(device.orphaned_data.mutex_get());
694 device.orphaned_data.move_data(device.orphaned_data_render,
695 device.orphaned_data.timeline_ + 1);
696 }
697}
698
699void VKBackend::render_step(bool force_resource_release)
700{
701 if (force_resource_release) {
702 std::scoped_lock lock(device.orphaned_data.mutex_get());
703 device.orphaned_data.move_data(device.orphaned_data_render,
704 device.orphaned_data.timeline_ + 1);
705 }
706}
707
709{
710 const VkPhysicalDeviceProperties &properties = device.physical_device_properties_get();
711 const VkPhysicalDeviceLimits &limits = properties.limits;
712
713 /* Reset all capabilities from previous context. */
714 GCaps = {};
715 GCaps.geometry_shader_support = true;
716 GCaps.stencil_export_support = device.supports_extension(
717 VK_EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME);
718
719 GCaps.max_texture_size = max_ii(limits.maxImageDimension1D, limits.maxImageDimension2D);
720 GCaps.max_texture_3d_size = min_uu(limits.maxImageDimension3D, INT_MAX);
721 GCaps.max_buffer_texture_size = min_uu(limits.maxTexelBufferElements, UINT_MAX);
722 GCaps.max_texture_layers = min_uu(limits.maxImageArrayLayers, INT_MAX);
723 GCaps.max_textures = min_uu(limits.maxDescriptorSetSampledImages, INT_MAX);
724 GCaps.max_textures_vert = GCaps.max_textures_geom = GCaps.max_textures_frag = min_uu(
725 limits.maxPerStageDescriptorSampledImages, INT_MAX);
726 GCaps.max_samplers = min_uu(limits.maxSamplerAllocationCount, INT_MAX);
727 GCaps.max_images = min_uu(limits.maxPerStageDescriptorStorageImages, INT_MAX);
728 for (int i = 0; i < 3; i++) {
729 GCaps.max_work_group_count[i] = min_uu(limits.maxComputeWorkGroupCount[i], INT_MAX);
730 GCaps.max_work_group_size[i] = min_uu(limits.maxComputeWorkGroupSize[i], INT_MAX);
731 }
732 GCaps.max_uniforms_vert = GCaps.max_uniforms_frag = min_uu(
733 limits.maxPerStageDescriptorUniformBuffers, INT_MAX);
734 GCaps.max_batch_indices = min_uu(limits.maxDrawIndirectCount, INT_MAX);
735 GCaps.max_batch_vertices = min_uu(limits.maxDrawIndexedIndexValue, INT_MAX);
736 GCaps.max_vertex_attribs = min_uu(limits.maxVertexInputAttributes, INT_MAX);
737 GCaps.max_varying_floats = min_uu(limits.maxVertexOutputComponents, INT_MAX);
738 GCaps.max_shader_storage_buffer_bindings = GCaps.max_compute_shader_storage_blocks = min_uu(
739 limits.maxPerStageDescriptorStorageBuffers, INT_MAX);
740 GCaps.max_uniform_buffer_size = size_t(limits.maxUniformBufferRange);
741 GCaps.max_storage_buffer_size = size_t(limits.maxStorageBufferRange);
742 GCaps.storage_buffer_alignment = limits.minStorageBufferOffsetAlignment;
743
744 GCaps.max_parallel_compilations = BLI_system_thread_count();
745 GCaps.mem_stats_support = true;
746
747 uint32_t vk_extension_count;
748 vkEnumerateDeviceExtensionProperties(
749 device.physical_device_get(), nullptr, &vk_extension_count, nullptr);
750 GCaps.extensions_len = vk_extension_count;
751 GCaps.extension_get = vk_extension_get;
752
753 detect_workarounds(device);
754}
755
756} // namespace blender::gpu
@ G_DEBUG_GPU
@ G_DEBUG_GPU_FORCE_WORKAROUNDS
@ G_DEBUG_GPU_FORCE_VULKAN_LOCAL_READ
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
MINLINE uint min_uu(uint a, uint b)
MINLINE int max_ii(int a, int b)
void BLI_setenv(const char *env, const char *val) ATTR_NONNULL(1)
int BLI_system_thread_count(void)
Definition threads.cc:253
int BLI_thread_is_main(void)
Definition threads.cc:179
#define CLOG_ERROR(clg_ref,...)
Definition CLG_log.h:188
#define CLOG_DEBUG(clg_ref,...)
Definition CLG_log.h:191
#define CLOG_WARN(clg_ref,...)
Definition CLG_log.h:189
void CLG_logref_init(CLG_LogRef *clg_ref)
Definition clog.cc:984
#define CLOG_INFO(clg_ref,...)
Definition CLG_log.h:190
GHOST C-API function and type declarations.
GHOST_ContextHandle GHOST_GetDrawingContext(GHOST_WindowHandle windowhandle)
int GPU_max_parallel_compilations()
GPUDeviceType
@ GPU_DEVICE_ATI
@ GPU_DEVICE_QUALCOMM
@ GPU_DEVICE_ANY
@ GPU_DEVICE_APPLE
@ GPU_ARCHITECTURE_IMR
bool GPU_type_matches(GPUDeviceType device, GPUOSType os, GPUDriverType driver)
GPUSupportLevel
@ GPU_SUPPORT_LEVEL_SUPPORTED
GPUDriverType
@ GPU_DRIVER_ANY
GPUOSType
@ GPU_OS_WIN
@ GPU_OS_UNIX
@ GPU_OS_ANY
@ GPU_OS_MAC
volatile int lock
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
const T * data() const
Definition BLI_array.hh:312
bool contains(const Key &key) const
Definition BLI_set.hh:310
bool add(const Key &key)
Definition BLI_set.hh:248
static constexpr int64_t not_found
constexpr int64_t find(char c, int64_t pos=0) const
void append(const T &value)
bool is_empty() const
ShaderCompiler * compiler_
void init(GPUDeviceType gpu_device, GPUOSType os_type, GPUDriverType driver_type, GPUSupportLevel gpu_support_level, GPUBackendType backend, const char *vendor_str, const char *renderer_str, const char *version_str, GPUArchitectureType arch_type)
void render_step(bool) override
Context * context_alloc(void *ghost_window, void *ghost_context) override
Batch * batch_alloc() override
StorageBuf * storagebuf_alloc(size_t size, GPUUsageType usage, const char *name) override
static void capabilities_init(VKDevice &device)
static VKBackend & get()
Definition vk_backend.hh:91
IndexBuf * indexbuf_alloc() override
static void platform_init(const VKDevice &device)
QueryPool * querypool_alloc() override
static bool is_supported()
UniformBuf * uniformbuf_alloc(size_t size, const char *name) override
Texture * texture_alloc(const char *name) override
void samplers_update() override
PixelBuffer * pixelbuf_alloc(size_t size) override
void render_begin() override
Shader * shader_alloc(const char *name) override
void render_end() override
FrameBuffer * framebuffer_alloc(const char *name) override
void compute_dispatch(int groups_x_len, int groups_y_len, int groups_z_len) override
void compute_dispatch_indirect(StorageBuf *indirect_buf) override
void delete_resources() override
void init_resources() override
VertBuf * vertbuf_alloc() override
Fence * fence_alloc() override
static void openxr_acquire_framebuffer_image_callback(GHOST_VulkanOpenXRData *data)
static void swap_buffer_acquired_callback()
static void openxr_release_framebuffer_image_callback(GHOST_VulkanOpenXRData *data)
static void swap_buffer_draw_callback(const GHOST_VulkanSwapChainData *data)
static VKContext * get()
const char * extension_name_get(int index) const
Definition vk_device.hh:259
const VkPhysicalDeviceFeatures & physical_device_features_get() const
Definition vk_device.hh:291
bool supports_extension(const char *extension_name) const
Definition vk_device.cc:259
const VkPhysicalDeviceProperties & physical_device_properties_get() const
Definition vk_device.hh:269
std::string vendor_name() const
Definition vk_device.cc:411
std::string driver_version() const
Definition vk_device.cc:438
VkPhysicalDevice physical_device_get() const
Definition vk_device.hh:264
const VkPhysicalDeviceVulkan12Features & physical_device_vulkan_12_features_get() const
Definition vk_device.hh:301
#define printf(...)
#define UINT_MAX
Definition hash_md5.cc:44
#define LOG(level)
Definition log.h:97
#define G(x, y, z)
GPUPlatformGlobal GPG
static Context * unwrap(GPUContext *ctx)
static CLG_LogRef LOG
bool GPU_vulkan_is_supported_driver(VkPhysicalDevice vk_physical_device)
Definition vk_backend.cc:48
GPUCapabilities GCaps
static GPUOSType determine_os_type()
static void init_device_list(GHOST_ContextHandle ghost_context)
static const char * vk_extension_get(int index)
Definition vk_backend.cc:43
static Vector< StringRefNull > missing_capabilities_get(VkPhysicalDevice vk_physical_device)
const char * name
std::string name
struct blender::gpu::VKWorkarounds::@332200143060210304170234105102153121344114125320 vertex_formats
i
Definition text_draw.cc:230