Blender V4.5
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 uint32_t conformance_version = VK_MAKE_API_VERSION(
58 vk_physical_device_driver_properties.conformanceVersion.major,
59 vk_physical_device_driver_properties.conformanceVersion.minor,
60 vk_physical_device_driver_properties.conformanceVersion.subminor,
61 vk_physical_device_driver_properties.conformanceVersion.patch);
62
63 /* Intel IRIS on 10th gen CPU (and older) crashes due to multiple driver issues.
64 *
65 * 1) Workbench is working, but EEVEE pipelines are failing. Calling vkCreateGraphicsPipelines
66 * for certain EEVEE shaders (Shadow, Deferred rendering) would return with VK_SUCCESS, but
67 * without a created VkPipeline handle.
68 *
69 * 2) When vkCmdBeginRendering is called some requirements need to be met, that can only be met
70 * when actually calling a vkCmdDraw* command. According to the Vulkan specs the requirements
71 * should only be met when calling a vkCmdDraw* command.
72 */
73 if (vk_physical_device_driver_properties.driverID == VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS &&
74 vk_physical_device_properties.properties.deviceType ==
75 VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU &&
76 conformance_version < VK_MAKE_API_VERSION(1, 3, 2, 0))
77 {
78 return false;
79 }
80
81#ifndef _WIN32
82 /* NVIDIA drivers below 550 don't work on Linux. When sending command to the GPU there is not
83 * always a reply back when they are finished. The issue is reported on the Internet many times,
84 * but there is no mention of a solution. This means that on Linux we can only support GTX900 and
85 * or use MesaNVK.
86 */
87 if (vk_physical_device_driver_properties.driverID == VK_DRIVER_ID_NVIDIA_PROPRIETARY &&
88 conformance_version < VK_MAKE_API_VERSION(1, 3, 7, 2))
89 {
90 return false;
91 }
92
93 /* NVIDIA driver 580.76.05 doesn't start using specific Wayland configurations #144625. There are
94 * multiple reports also not Blender related and NVIDIA mentions that a new driver will be
95 * released. It is unclear if that driver will fix our issue. For now disabling this driver on
96 * Linux. This also disables it for configurations that are working as well (including X11). */
97 if (vk_physical_device_driver_properties.driverID == VK_DRIVER_ID_NVIDIA_PROPRIETARY &&
98 ((StringRefNull(vk_physical_device_driver_properties.driverInfo).find("580.76.5", 0) !=
100 (StringRefNull(vk_physical_device_driver_properties.driverInfo).find("580.76.05", 0) !=
102 {
103 return false;
104 }
105#endif
106
107#ifdef _WIN32
108 if (vk_physical_device_driver_properties.driverID == VK_DRIVER_ID_QUALCOMM_PROPRIETARY) {
109 /* Any Qualcomm driver older than 31.0.112.0 will not be capable of running blender due
110 * to an issue in their semaphore timeline implementation. The driver could return
111 * timelines that have not been provided by Blender. As Blender uses timelines for resource
112 * management this resulted in resources to be destroyed, that are still in use. */
113
114 /* Public version 31.0.112 uses vulkan driver version 512.827.0. */
115 const uint32_t driver_version = vk_physical_device_properties.properties.driverVersion;
116 constexpr uint32_t version_31_0_112 = VK_MAKE_VERSION(512, 827, 0);
117 if (driver_version < version_31_0_112) {
118 CLOG_WARN(&LOG,
119 "Detected qualcomm driver is not supported. To run the Vulkan backend "
120 "driver 31.0.112.0 or later is required. Switching to OpenGL.");
121 return false;
122 }
123 }
124#endif
125
126 return true;
127}
128
129static Vector<StringRefNull> missing_capabilities_get(VkPhysicalDevice vk_physical_device)
130{
131 Vector<StringRefNull> missing_capabilities;
132 /* Check device features. */
133 VkPhysicalDeviceVulkan12Features features_12 = {
134 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES};
135 VkPhysicalDeviceFeatures2 features = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
136 &features_12};
137
138 vkGetPhysicalDeviceFeatures2(vk_physical_device, &features);
139
140#ifndef __APPLE__
141 if (features.features.geometryShader == VK_FALSE) {
142 missing_capabilities.append("geometry shaders");
143 }
144 if (features.features.logicOp == VK_FALSE) {
145 missing_capabilities.append("logical operations");
146 }
147#endif
148 if (features.features.dualSrcBlend == VK_FALSE) {
149 missing_capabilities.append("dual source blending");
150 }
151 if (features.features.imageCubeArray == VK_FALSE) {
152 missing_capabilities.append("image cube array");
153 }
154 if (features.features.multiDrawIndirect == VK_FALSE) {
155 missing_capabilities.append("multi draw indirect");
156 }
157 if (features.features.multiViewport == VK_FALSE) {
158 missing_capabilities.append("multi viewport");
159 }
160 if (features.features.shaderClipDistance == VK_FALSE) {
161 missing_capabilities.append("shader clip distance");
162 }
163 if (features.features.drawIndirectFirstInstance == VK_FALSE) {
164 missing_capabilities.append("draw indirect first instance");
165 }
166 if (features.features.fragmentStoresAndAtomics == VK_FALSE) {
167 missing_capabilities.append("fragment stores and atomics");
168 }
169 if (features_12.timelineSemaphore == VK_FALSE) {
170 missing_capabilities.append("timeline semaphores");
171 }
172 if (features_12.bufferDeviceAddress == VK_FALSE) {
173 missing_capabilities.append("buffer device address");
174 }
175
176 /* Check device extensions. */
177 uint32_t vk_extension_count;
178 vkEnumerateDeviceExtensionProperties(vk_physical_device, nullptr, &vk_extension_count, nullptr);
179
180 Array<VkExtensionProperties> vk_extensions(vk_extension_count);
181 vkEnumerateDeviceExtensionProperties(
182 vk_physical_device, nullptr, &vk_extension_count, vk_extensions.data());
183 Set<StringRefNull> extensions;
184 for (VkExtensionProperties &vk_extension : vk_extensions) {
185 extensions.add(vk_extension.extensionName);
186 }
187
188 if (!extensions.contains(VK_KHR_SWAPCHAIN_EXTENSION_NAME)) {
189 missing_capabilities.append(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
190 }
191#ifndef __APPLE__
192 /* Metal doesn't support provoking vertex. */
193 if (!extensions.contains(VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME)) {
194 missing_capabilities.append(VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME);
195 }
196#endif
197
198 return missing_capabilities;
199}
200
202{
204
205 /*
206 * Disable implicit layers and only allow layers that we trust.
207 *
208 * Render doc layer is hidden behind a debug flag. There are malicious layers that impersonate
209 * RenderDoc and can crash when loaded. See #139543
210 */
211 std::stringstream allowed_layers;
212 allowed_layers << "VK_LAYER_KHRONOS_*";
213 allowed_layers << ",VK_LAYER_AMD_*";
214 allowed_layers << ",VK_LAYER_INTEL_*";
215 allowed_layers << ",VK_LAYER_NV_*";
216 allowed_layers << ",VK_LAYER_MESA_*";
217 if (bool(G.debug & G_DEBUG_GPU)) {
218 allowed_layers << ",VK_LAYER_LUNARG_*";
219 allowed_layers << ",VK_LAYER_RENDERDOC_*";
220 }
221 BLI_setenv("VK_LOADER_LAYERS_DISABLE", "~implicit~");
222 BLI_setenv("VK_LOADER_LAYERS_ALLOW", allowed_layers.str().c_str());
223
224 /* Initialize an vulkan 1.2 instance. */
225 VkApplicationInfo vk_application_info = {VK_STRUCTURE_TYPE_APPLICATION_INFO};
226 vk_application_info.pApplicationName = "Blender";
227 vk_application_info.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
228 vk_application_info.pEngineName = "Blender";
229 vk_application_info.engineVersion = VK_MAKE_VERSION(1, 0, 0);
230 vk_application_info.apiVersion = VK_API_VERSION_1_2;
231
232 VkInstanceCreateInfo vk_instance_info = {VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO};
233 vk_instance_info.pApplicationInfo = &vk_application_info;
234
235 VkInstance vk_instance = VK_NULL_HANDLE;
236 vkCreateInstance(&vk_instance_info, nullptr, &vk_instance);
237 if (vk_instance == VK_NULL_HANDLE) {
238 CLOG_ERROR(&LOG, "Unable to initialize a Vulkan 1.2 instance.");
239 return false;
240 }
241
242 /* Go over all the devices. */
243 uint32_t physical_devices_count = 0;
244 vkEnumeratePhysicalDevices(vk_instance, &physical_devices_count, nullptr);
245 Array<VkPhysicalDevice> vk_physical_devices(physical_devices_count);
246 vkEnumeratePhysicalDevices(vk_instance, &physical_devices_count, vk_physical_devices.data());
247
248 for (VkPhysicalDevice vk_physical_device : vk_physical_devices) {
249 VkPhysicalDeviceProperties vk_properties = {};
250 vkGetPhysicalDeviceProperties(vk_physical_device, &vk_properties);
251
252 if (!GPU_vulkan_is_supported_driver(vk_physical_device)) {
253 CLOG_WARN(&LOG,
254 "Installed driver for device [%s] has known issues and will not be used. Updating "
255 "driver might improve compatibility.",
256 vk_properties.deviceName);
257 continue;
258 }
259 Vector<StringRefNull> missing_capabilities = missing_capabilities_get(vk_physical_device);
260
261 /* Report result. */
262 if (missing_capabilities.is_empty()) {
263 /* This device meets minimum requirements. */
264 CLOG_INFO(&LOG,
265 2,
266 "Device [%s] supports minimum requirements. Skip checking other GPUs. Another GPU "
267 "can still be selected during auto-detection.",
268 vk_properties.deviceName);
269
270 vkDestroyInstance(vk_instance, nullptr);
271 return true;
272 }
273
274 std::stringstream ss;
275 ss << "Device [" << vk_properties.deviceName
276 << "] does not meet minimum requirements. Missing features are [";
277 for (StringRefNull &feature : missing_capabilities) {
278 ss << feature << ", ";
279 }
280 ss.seekp(-2, std::ios_base::end);
281 ss << "]";
282 CLOG_WARN(&LOG, "%s", ss.str().c_str());
283 }
284
285 /* No device found meeting the minimum requirements. */
286
287 vkDestroyInstance(vk_instance, nullptr);
289 "No Vulkan device found that meets the minimum requirements. "
290 "Updating GPU driver can improve compatibility.");
291 return false;
292}
293
295{
296#ifdef _WIN32
297 return GPU_OS_WIN;
298#elif defined(__APPLE__)
299 return GPU_OS_MAC;
300#else
301 return GPU_OS_UNIX;
302#endif
303}
304
306{
312 "",
313 "",
314 "",
316}
317
318static void init_device_list(GHOST_ContextHandle ghost_context)
319{
320 GHOST_VulkanHandles vulkan_handles = {};
321 GHOST_GetVulkanHandles(ghost_context, &vulkan_handles);
322
323 uint32_t physical_devices_count = 0;
324 vkEnumeratePhysicalDevices(vulkan_handles.instance, &physical_devices_count, nullptr);
325 Array<VkPhysicalDevice> vk_physical_devices(physical_devices_count);
326 vkEnumeratePhysicalDevices(
327 vulkan_handles.instance, &physical_devices_count, vk_physical_devices.data());
328 int index = 0;
329 for (VkPhysicalDevice vk_physical_device : vk_physical_devices) {
330 if (missing_capabilities_get(vk_physical_device).is_empty() &&
331 GPU_vulkan_is_supported_driver(vk_physical_device))
332 {
333 VkPhysicalDeviceProperties vk_properties = {};
334 vkGetPhysicalDeviceProperties(vk_physical_device, &vk_properties);
335 std::stringstream identifier;
336 identifier << std::hex << vk_properties.vendorID << "/" << vk_properties.deviceID << "/"
337 << index;
338 GPG.devices.append({identifier.str(),
339 index,
340 vk_properties.vendorID,
341 vk_properties.deviceID,
342 std::string(vk_properties.deviceName)});
343 }
344 index++;
345 }
346
347 std::sort(GPG.devices.begin(), GPG.devices.end(), [&](const GPUDevice &a, const GPUDevice &b) {
348 if (a.name == b.name) {
349 return a.index < b.index;
350 }
351 return a.name < b.name;
352 });
353}
354
356{
357 const VkPhysicalDeviceProperties &properties = device.physical_device_properties_get();
358
359 eGPUDeviceType device_type = device.device_type();
360 eGPUDriverType driver = device.driver_type();
363
364 std::string vendor_name = device.vendor_name();
365 std::string driver_version = device.driver_version();
366
367 /* GPG has already been initialized, but without a specific device. Calling init twice will
368 * clear the list of devices. Making a copy of the device list and set it after initialization to
369 * make sure the list isn't destroyed at this moment, but only when the backend is destroyed. */
370 Vector<GPUDevice> devices = GPG.devices;
371 GPG.init(device_type,
372 os,
373 driver,
374 support_level,
376 vendor_name.c_str(),
377 properties.deviceName,
378 driver_version.c_str(),
380 GPG.devices = devices;
381
382 const VkPhysicalDeviceIDProperties &id_properties = device.physical_device_id_properties_get();
383
384 GPG.device_uuid = Array<uint8_t, 16>(Span<uint8_t>(id_properties.deviceUUID, VK_UUID_SIZE));
385
386 if (id_properties.deviceLUIDValid) {
387 GPG.device_luid = Array<uint8_t, 8>(Span<uint8_t>(id_properties.deviceUUID, VK_LUID_SIZE));
388 GPG.device_luid_node_mask = id_properties.deviceNodeMask;
389 }
390 else {
391 GPG.device_luid.reinitialize(0);
392 GPG.device_luid_node_mask = 0;
393 }
394
395 CLOG_INFO(&LOG,
396 0,
397 "Using vendor [%s] device [%s] driver version [%s].",
398 vendor_name.c_str(),
399 device.vk_physical_device_properties_.deviceName,
400 driver_version.c_str());
401}
402
403void VKBackend::detect_workarounds(VKDevice &device)
404{
405 VKWorkarounds workarounds;
406 VKExtensions extensions;
407
408 if (G.debug & G_DEBUG_GPU_FORCE_WORKAROUNDS) {
409 printf("\n");
410 printf("VK: Forcing workaround usage and disabling features and extensions.\n");
411 printf(" Vendor: %s\n", device.vendor_name().c_str());
412 printf(" Device: %s\n", device.physical_device_properties_get().deviceName);
413 printf(" Driver: %s\n", device.driver_version().c_str());
414 /* Force workarounds and disable extensions. */
415 workarounds.not_aligned_pixel_formats = true;
416 workarounds.vertex_formats.r8g8b8 = true;
417 extensions.shader_output_layer = false;
418 extensions.shader_output_viewport_index = false;
419 extensions.fragment_shader_barycentric = false;
420 extensions.dynamic_rendering = false;
421 extensions.dynamic_rendering_local_read = false;
422 extensions.dynamic_rendering_unused_attachments = false;
423 extensions.descriptor_buffer = false;
424 extensions.pageable_device_local_memory = false;
425
426 GCaps.render_pass_workaround = true;
427
428 device.workarounds_ = workarounds;
429 device.extensions_ = extensions;
430 return;
431 }
432
433 extensions.shader_output_layer =
434 device.physical_device_vulkan_12_features_get().shaderOutputLayer;
436 device.physical_device_vulkan_12_features_get().shaderOutputViewportIndex;
438 VK_KHR_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME);
439 extensions.dynamic_rendering = device.supports_extension(
440 VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME);
442 VK_KHR_DYNAMIC_RENDERING_LOCAL_READ_EXTENSION_NAME);
444 VK_EXT_DYNAMIC_RENDERING_UNUSED_ATTACHMENTS_EXTENSION_NAME);
445 extensions.logic_ops = device.physical_device_features_get().logicOp;
446 /* For stability reasons descriptor buffers have been disabled. */
447#if 0
448 extensions.descriptor_buffer = device.supports_extension(
449 VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME);
450#endif
451 extensions.memory_priority = device.supports_extension(VK_EXT_MEMORY_PRIORITY_EXTENSION_NAME);
453 VK_EXT_PAGEABLE_DEVICE_LOCAL_MEMORY_EXTENSION_NAME);
454#ifdef _WIN32
455 extensions.external_memory = device.supports_extension(
456 VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME);
457#elif not defined(__APPLE__)
458 extensions.external_memory = device.supports_extension(VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME);
459#else
460 extensions.external_memory = false;
461#endif
462
463 /* Descriptor buffers are disabled on the NVIDIA platform due to performance regressions. Both
464 * still seem to be faster than OpenGL.
465 *
466 * See #140125
467 */
468 if (device.vk_physical_device_driver_properties_.driverID == VK_DRIVER_ID_NVIDIA_PROPRIETARY) {
469 extensions.descriptor_buffer = false;
470 }
471
472 /* Running render tests fails consistenly in some scenes. The cause is that too many descriptor
473 * sets are required for rendering resulting in failing allocations of the descriptor buffer. We
474 * work around this issue by not using descriptor buffers on these platforms.
475 *
476 * TODO: recheck when the backed memory gets freed and how to improve it.
477 *
478 * See #141476
479 */
480 if (device.vk_physical_device_driver_properties_.driverID ==
481 VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS)
482 {
483 extensions.descriptor_buffer = false;
484 }
485
486 /* AMD GPUs don't support texture formats that use are aligned to 24 or 48 bits. */
489 {
490 workarounds.not_aligned_pixel_formats = true;
491 }
492
493 /* Only enable by default dynamic rendering local read on Qualcomm devices. NVIDIA, AMD and Intel
494 * performance is better when disabled (20%). On Qualcomm devices the improvement can be
495 * substantial (16% on shader_balls.blend).
496 *
497 * `--debug-gpu-vulkan-local-read` can be used to use dynamic rendering local read on any
498 * supported platform.
499 *
500 * TODO: Check if bottleneck is during command building. If so we could fine-tune this after the
501 * device command building landed (T132682).
502 */
503 if ((G.debug & G_DEBUG_GPU_FORCE_VULKAN_LOCAL_READ) == 0 &&
505 {
506 extensions.dynamic_rendering_local_read = false;
507 }
508
509 VkFormatProperties format_properties = {};
510 vkGetPhysicalDeviceFormatProperties(
511 device.physical_device_get(), VK_FORMAT_R8G8B8_UNORM, &format_properties);
512 workarounds.vertex_formats.r8g8b8 = (format_properties.bufferFeatures &
513 VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT) == 0;
514
516
517#ifdef __APPLE__
518 /* Due to a limitation in MoltenVK, attachments should be sequential even when using
519 * dynamic rendering. MoltenVK internally uses render passes to simulate dynamic rendering and
520 * same limitations apply. */
523 }
524#endif
525
526 device.workarounds_ = workarounds;
527 device.extensions_ = extensions;
528}
529
530void VKBackend::platform_exit()
531{
532 GPG.clear();
533 VKDevice &device = VKBackend::get().device;
534 if (device.is_initialized()) {
535 device.deinit();
536 }
537}
538
540{
541 compiler_ = MEM_new<ShaderCompiler>(
543}
544
546{
547 MEM_delete(compiler_);
548}
549
551{
552 VKDevice &device = VKBackend::get().device;
553 if (device.is_initialized()) {
554 device.reinit();
555 }
556}
557
558void VKBackend::compute_dispatch(int groups_x_len, int groups_y_len, int groups_z_len)
559{
560 VKContext &context = *VKContext::get();
561 render_graph::VKResourceAccessInfo &resources = context.reset_and_get_access_info();
562 render_graph::VKDispatchNode::CreateInfo dispatch_info(resources);
563 context.update_pipeline_data(dispatch_info.dispatch_node.pipeline_data);
564 dispatch_info.dispatch_node.group_count_x = groups_x_len;
565 dispatch_info.dispatch_node.group_count_y = groups_y_len;
566 dispatch_info.dispatch_node.group_count_z = groups_z_len;
567 context.render_graph().add_node(dispatch_info);
568}
569
571{
572 BLI_assert(indirect_buf);
573 VKContext &context = *VKContext::get();
574 VKStorageBuffer &indirect_buffer = *unwrap(indirect_buf);
575 render_graph::VKResourceAccessInfo &resources = context.reset_and_get_access_info();
576 render_graph::VKDispatchIndirectNode::CreateInfo dispatch_indirect_info(resources);
577 context.update_pipeline_data(dispatch_indirect_info.dispatch_indirect_node.pipeline_data);
578 dispatch_indirect_info.dispatch_indirect_node.buffer = indirect_buffer.vk_handle();
579 dispatch_indirect_info.dispatch_indirect_node.offset = 0;
580 context.render_graph().add_node(dispatch_indirect_info);
581}
582
583Context *VKBackend::context_alloc(void *ghost_window, void *ghost_context)
584{
585 if (ghost_window) {
586 BLI_assert(ghost_context == nullptr);
587 ghost_context = GHOST_GetDrawingContext((GHOST_WindowHandle)ghost_window);
588 }
589
590 BLI_assert(ghost_context != nullptr);
591 if (!device.is_initialized()) {
592 device.init(ghost_context);
593 device.extensions_get().log();
594 init_device_list((GHOST_ContextHandle)ghost_context);
595 }
596
597 VKContext *context = new VKContext(ghost_window, ghost_context);
598 device.context_register(*context);
599 GHOST_SetVulkanSwapBuffersCallbacks((GHOST_ContextHandle)ghost_context,
604
605 return context;
606}
607
609{
610 return new VKBatch();
611}
612
614{
615 return new VKFence();
616}
617
619{
620 return new VKFrameBuffer(name);
621}
622
624{
625 return new VKIndexBuffer();
626}
627
629{
630 return new VKPixelBuffer(size);
631}
632
634{
635 return new VKQueryPool();
636}
637
639{
640 return new VKShader(name);
641}
642
644{
645 return new VKTexture(name);
646}
647
649{
650 return new VKUniformBuffer(size, name);
651}
652
654{
655 return new VKStorageBuffer(size, usage, name);
656}
657
659{
660 return new VKVertexBuffer();
661}
662
664{
665 VKThreadData &thread_data = device.current_thread_data();
666 BLI_assert_msg(thread_data.rendering_depth >= 0, "Unbalanced `GPU_render_begin/end`");
667 thread_data.rendering_depth += 1;
668}
669
671{
672 VKThreadData &thread_data = device.current_thread_data();
673 thread_data.rendering_depth -= 1;
674 BLI_assert_msg(thread_data.rendering_depth >= 0, "Unbalanced `GPU_render_begin/end`");
675 if (G.background) {
676 if (thread_data.rendering_depth == 0) {
677 VKContext *context = VKContext::get();
678 if (context != nullptr) {
679 context->flush();
680 }
681 std::scoped_lock lock(device.orphaned_data.mutex_get());
682 device.orphaned_data.move_data(device.orphaned_data_render,
683 device.orphaned_data.timeline_ + 1);
684 }
685 }
686
687 /* When performing animation render we want to release any discarded resources during rendering
688 * after each frame.
689 */
690 if (G.is_rendering && thread_data.rendering_depth == 0 && !BLI_thread_is_main()) {
691 std::scoped_lock lock(device.orphaned_data.mutex_get());
692 device.orphaned_data.move_data(device.orphaned_data_render,
693 device.orphaned_data.timeline_ + 1);
694 }
695}
696
697void VKBackend::render_step(bool force_resource_release)
698{
699 if (force_resource_release) {
700 std::scoped_lock lock(device.orphaned_data.mutex_get());
701 device.orphaned_data.move_data(device.orphaned_data_render,
702 device.orphaned_data.timeline_ + 1);
703 }
704}
705
707{
708 const VkPhysicalDeviceProperties &properties = device.physical_device_properties_get();
709 const VkPhysicalDeviceLimits &limits = properties.limits;
710
711 /* Reset all capabilities from previous context. */
712 GCaps = {};
713 GCaps.geometry_shader_support = true;
714 GCaps.clip_control_support = true;
715 GCaps.stencil_export_support = device.supports_extension(
716 VK_EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME);
717 GCaps.shader_draw_parameters_support =
718 device.physical_device_vulkan_11_features_get().shaderDrawParameters;
719
720 GCaps.max_texture_size = max_ii(limits.maxImageDimension1D, limits.maxImageDimension2D);
721 GCaps.max_texture_3d_size = min_uu(limits.maxImageDimension3D, INT_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_storage_buffer_size = size_t(limits.maxStorageBufferRange);
741 GCaps.storage_buffer_alignment = limits.minStorageBufferOffsetAlignment;
742
743 GCaps.max_parallel_compilations = BLI_system_thread_count();
744 GCaps.mem_stats_support = true;
745
746 uint32_t vk_extension_count;
747 vkEnumerateDeviceExtensionProperties(
748 device.physical_device_get(), nullptr, &vk_extension_count, nullptr);
749 GCaps.extensions_len = vk_extension_count;
750 GCaps.extension_get = vk_extension_get;
751
752 detect_workarounds(device);
753}
754
755} // 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:182
#define CLOG_WARN(clg_ref,...)
Definition CLG_log.h:181
void CLG_logref_init(CLG_LogRef *clg_ref)
Definition clog.c:762
#define CLOG_INFO(clg_ref, level,...)
Definition CLG_log.h:179
GHOST C-API function and type declarations.
GHOST_ContextHandle GHOST_GetDrawingContext(GHOST_WindowHandle windowhandle)
int GPU_max_parallel_compilations()
eGPUDriverType
@ GPU_DRIVER_ANY
@ GPU_ARCHITECTURE_IMR
eGPUSupportLevel
@ GPU_SUPPORT_LEVEL_SUPPORTED
eGPUOSType
@ GPU_OS_WIN
@ GPU_OS_UNIX
@ GPU_OS_ANY
@ GPU_OS_MAC
eGPUDeviceType
@ GPU_DEVICE_ATI
@ GPU_DEVICE_QUALCOMM
@ GPU_DEVICE_ANY
@ GPU_DEVICE_APPLE
bool GPU_type_matches(eGPUDeviceType device, eGPUOSType os, eGPUDriverType driver)
volatile int lock
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
const T * data() const
Definition BLI_array.hh:301
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(eGPUDeviceType gpu_device, eGPUOSType os_type, eGPUDriverType driver_type, eGPUSupportLevel gpu_support_level, eGPUBackendType 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 openxr_release_framebuffer_image_callback(GHOST_VulkanOpenXRData *data)
static void swap_buffers_post_callback()
static void swap_buffers_pre_callback(const GHOST_VulkanSwapChainData *data)
static VKContext * get()
const char * extension_name_get(int index) const
Definition vk_device.hh:290
const VkPhysicalDeviceFeatures & physical_device_features_get() const
Definition vk_device.hh:316
bool supports_extension(const char *extension_name) const
Definition vk_device.cc:253
const VkPhysicalDeviceProperties & physical_device_properties_get() const
Definition vk_device.hh:300
std::string vendor_name() const
Definition vk_device.cc:468
std::string driver_version() const
Definition vk_device.cc:495
VkPhysicalDevice physical_device_get() const
Definition vk_device.hh:295
const VkPhysicalDeviceVulkan12Features & physical_device_vulkan_12_features_get() const
Definition vk_device.hh:326
#define printf(...)
#define LOG(severity)
Definition log.h:32
#define G(x, y, z)
GPUPlatformGlobal GPG
static Context * unwrap(GPUContext *ctx)
static eGPUOSType determine_os_type()
static CLG_LogRef LOG
bool GPU_vulkan_is_supported_driver(VkPhysicalDevice vk_physical_device)
Definition vk_backend.cc:48
GPUCapabilities GCaps
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)
std::string name
struct blender::gpu::VKWorkarounds::@144366115005041264305201362101242107317250331264 vertex_formats
i
Definition text_draw.cc:230